Skip to content

Draft: (dependencies) Add example print after #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 62 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,69 @@ 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

The following is a sample program where multiple coroutines print they are starting, sleep for a specified time, and
print they slept the specified time
```c
#include "async.h"
#include "async-time.h"

struct print_after_state
{
async_state;
struct async_sleep_state async_sleep_state;
};

static async print_after(struct print_after_state *state, unsigned int duration)
{
async_begin(state);

printf("Starting %d second counter...\n", duration);
async_yield;
printf("Yield from %d second counter demo'd!\n", duration);
async_init(&state->async_sleep_state);
await(async_sleep(&state->async_sleep_state, duration * 1000));
printf("Slept: %d seconds\n", duration);

async_end;
}

int example_print_after(void)
{
struct print_after_state a = {}, b = {}, c = {};

async_run(
print_after(&a, 3) &
print_after(&b, 5) &
print_after(&c, 1)
);

return 0;
}
```

Prints the following and runs a total of 5 seconds:

```
Starting 3 second counter...
Starting 5 second counter...
Starting 1 second counter...
Yield from 3 second counter demo'd!
Yield from 5 second counter demo'd!
Yield from 1 second counter demo'd!
Slept: 1 seconds
Slept: 3 seconds
Slept: 5 seconds
```

I ported the examples found in the protothreads distribution to async.h. Here
is the async.h equivalent of the protothreads sample on the home page:
```C
```c
#include "async.h"
#include "async-time.h"

struct async pt;
struct timer timer;
Expand All @@ -40,7 +96,7 @@ async example(struct async *pt) {

while(1) {
if(initiate_io()) {
timer_start(&timer);
timer_set(&timer);
await(io_completed() || timer_expired(&timer));
read_data();
}
Expand All @@ -54,12 +110,13 @@ to accept the async structure/local continuation as an argument.

Here is the same example as above, but where the timer is lifted to
a local parameter:
```C
```c
#include "async.h"
#include "async-time.h"

typedef struct {
async_state; // declare the asynchronous state
timer timer; // declare local state
struct timer timer; // declare local state
} example_state;
example_state pt;

Expand All @@ -68,7 +125,7 @@ async example(example_state *pt) {

while(1) {
if(initiate_io()) {
timer_start(&pt->timer);
timer_set(&pt->timer);
await(io_completed() || timer_expired(&pt->timer));
read_data();
}
Expand Down
2 changes: 1 addition & 1 deletion async/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ CC = gcc
CCFlags = -Wall
BUILD_DIR = build

SRC = example-buffer.c example-codelock.c example-small.c main.c
SRC = async-time.c example-buffer.c example-codelock.c example-print-after.c example-small.c main.c
OBJ = $(patsubst %.c,$(BUILD_DIR)/%.o,$(SRC))

all : $(OBJ)
Expand Down
49 changes: 49 additions & 0 deletions async/async-time.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <sys/time.h>
#endif

#include "async.h"
#include "async-time.h"

#ifdef _WIN32

static int clock_time(void)
{
return (int)GetTickCount();
}

#else /* _WIN32 */

static int clock_time(void)
{
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

#endif /* _WIN32 */

int timer_expired(struct timer *t)
{
return (int)(clock_time() - t->start) >= (int)t->interval;
}

void timer_set(struct timer *t, unsigned int interval)
{
t->interval = interval;
t->start = clock_time();
}

async async_sleep(struct async_sleep_state *state, unsigned int usecs)
{
async_begin(state);

timer_set(&state->timer, usecs);
await(timer_expired(&state->timer));

async_end;
}
42 changes: 42 additions & 0 deletions async/async-time.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "async.h"

/**
* Timer structure for tracking when a timer has expired
*/
struct timer
{
unsigned int start;
unsigned int interval;
};

/**
* State structure for calls to the async_sleep function
*/
struct async_sleep_state
{
async_state;
struct timer timer;
};

/**
* Initialize a timer with a specified time duration
*
* @param t timer struct to initialize
* @param usecs number of milliseconds the timer is good for
*/
void timer_set(struct timer *t, unsigned int usecs);

/**
* Determine if the supplied timer is expired
*
* @param t timer struct to examine for expiration
*/
int timer_expired(struct timer *t);

/**
* Sleep asynchronously for a specified duration
*
* @param state async_sleep_state structure to hold state of operation
* @param usecs number of milliseconds to sleep for
*/
async async_sleep(struct async_sleep_state *state, unsigned int usecs);
7 changes: 7 additions & 0 deletions async/async.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
* Pulled from: https://github.com/naasking/async.h
*
* Author: Sandro Magi <[email protected]>
* Contributor: Paul Sorensen <[email protected]>
*/

/**
Expand Down Expand Up @@ -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
18 changes: 4 additions & 14 deletions async/example-buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
55 changes: 5 additions & 50 deletions async/example-codelock.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,8 @@
#include <stdio.h>

#include "async.h"
#include "async-time.h"

/*---------------------------------------------------------------------------*/
/*
* The following definitions are just for the simple timer library
* used in this example. The actual implementation of the functions
* can be found at the end of this file.
*/
struct timer { int start, interval; };
static int timer_expired(struct timer *t);
static void timer_set(struct timer *t, int usecs);
/*---------------------------------------------------------------------------*/
/*
* This example uses two timers: one for the code lock async and
Expand Down Expand Up @@ -367,48 +359,11 @@ 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;
}
/*---------------------------------------------------------------------------*/
/*
* Finally, the implementation of the simple timer library follows.
*/
#ifdef _WIN32

static int clock_time(void)
{ return (int)GetTickCount(); }

#else /* _WIN32 */

static int clock_time(void)
{
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

#endif /* _WIN32 */

static int timer_expired(struct timer *t)
{ return (int)(clock_time() - t->start) >= (int)t->interval; }

static void timer_set(struct timer *t, int interval)
{ t->interval = interval; t->start = clock_time(); }
/*---------------------------------------------------------------------------*/
Loading