diff --git a/README.md b/README.md index dcf7c8e..1aec3b9 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ Function|Description *async_call(func, state)*|Asynchronously call `func(state)` and return true if done executing (optional). You can also simply call `func(state)`directly which returns true/false. *async_init(state)*|Initialize async subroutine state *async_done(state)*|Returns true if async subroutine has completed execution, otherwise false +*async_run(cond)*|Runs your async function(s) from a non async function separated by `&` or `\|` to specify when all or one complete respectively # Examples diff --git a/async/async.h b/async/async.h index d22166c..7a64f1f 100644 --- a/async/async.h +++ b/async/async.h @@ -34,6 +34,7 @@ * Pulled from: https://github.com/naasking/async.h * * Author: Sandro Magi + * Contributor: Paul Sorensen */ /** @@ -135,4 +136,10 @@ struct async { async_state; }; */ #define async_call(f, state) (async_done(state) || (f)(state)) +/** + * Wait until the condition succeeds from a non-async function + * @param cond The condition that must be satisfied before execution can proceed + */ +#define async_run(cond) while(!(cond)) + #endif \ No newline at end of file diff --git a/async/example-buffer.c b/async/example-buffer.c index a55778d..2fe2fb6 100644 --- a/async/example-buffer.c +++ b/async/example-buffer.c @@ -146,19 +146,9 @@ example_buffer(void) async_init(&driver_pt); - while (!driver_thread(&driver_pt)) { - - /* - * When running this example on a multitasking system, we must - * give other processes a chance to run too and therefore we call - * usleep() resp. Sleep() here. On a dedicated embedded system, - * we usually do not need to do this. - */ -#ifdef _WIN32 - Sleep(0); -#else - usleep(10); -#endif - } + async_run( + driver_thread(&driver_pt) + ); + return 0; } diff --git a/async/example-codelock.c b/async/example-codelock.c index aeac93b..cfe8daa 100644 --- a/async/example-codelock.c +++ b/async/example-codelock.c @@ -367,21 +367,10 @@ example_codelock(void) /* * Schedule the two asyncs until the codelock_thread() exits. */ - while(!codelock_thread(&codelock_pt)) { - input_thread(&input_pt); - - /* - * When running this example on a multitasking system, we must - * give other processes a chance to run too and therefore we call - * usleep() resp. Sleep() here. On a dedicated embedded system, - * we usually do not need to do this. - */ -#ifdef _WIN32 - Sleep(0); -#else - usleep(10); -#endif - } + async_run( + codelock_thread(&codelock_pt) & + input_thread(&input_pt) + ); return 0; } diff --git a/async/example-small.c b/async/example-small.c index 2d3cff6..c161a62 100644 --- a/async/example-small.c +++ b/async/example-small.c @@ -1,7 +1,8 @@ /** * This is a very small example that shows how to use * async.h. The program consists of two async subroutines that wait - * for each other to toggle a variable. + * for each other to toggle a variable. This continues while a third async + * subroutine counts down from a provided starting integer. */ /* We must always include async.h in our asyncs code. */ @@ -10,7 +11,7 @@ #include /* For printf(). */ /* Two flags that the two async functions use. */ -static int async1_flag, async2_flag; +static int async1_flag, async2_flag, counter; /** * The first async function. A async function must always @@ -71,27 +72,47 @@ async2(struct async *pt) async_end; } +/** + * An async function to decrement the global countdown + */ +static async +countdown(struct async *pt) +{ + async_begin(pt); + + /* Yield control to other functions while the counter is above 0 */ + while (counter-- >= 0) { + async_yield; + } + + async_end; +} + /** * Finally, we have the main loop. Here is where the asyncs are * initialized and scheduled. First, however, we define the - * async state variables pt1 and pt2, which hold the state of - * the two asyncs. + * async state variables pt1, pt2, and count, which hold the state of + * the 3 asyncs. */ -static struct async pt1, pt2; +static struct async pt1, pt2, count; void example_small(int i) { /* Initialize the async state variables with async_init(). */ async_init(&pt1); async_init(&pt2); + async_init(&count); + + counter = i; /* - * Then we schedule the two asyncs by repeatedly calling their - * async functions and passing a pointer to the async + * Then we schedule the three asyncs by repeatedly calling their async + * functions via the `async_run` macro and passing a pointer to the async * state variables as arguments. */ - while (--i >= 0) { - async1(&pt1); - async2(&pt2); - } + async_run( + countdown(&count) | + async1(&pt1) | + async2(&pt2) + ); }