# ccoroutines
Coroutines in C, using standard libraries.

## What's Here

### ccoroutines
The coroutine engine.

### generator
Provides generators - coroutines which yield values. These are especially useful for nested searches which provide values to a for loop (eg searching for files in a directory tree).

### async
Provides asynchronous tasks. Each task volunteers to be switched away-from by waiting on a `Async_Future`.

Note that `generator` and `async` can be used together.

## Prerequisites

These rely on as much as possible on C's cross-platform comfort zone. C's standard libraries are used as far as possible, but, as `threads.h` is not usually supported, `pthread.h` has been used instead.

### Style

The style is influenced by C++. For example, where possible, a `Something *Something_New(a, b, c)` and `Something_Delete(Something *)`, where a `Something` is `malloc`ed, will have corresponding `Somthing_ctor(Somthing *, a, b, c)` and `Something_dtor(Something *)` to initialise and finalise a `Something` on the stack, or within another object. Using `.._ctor()` and `.._dtor()` will be faster as they avoid the `malloc()` and `free()`.

    Something *oneofthem = Something_New();
    // use oneofthem
    Something_Delete(oneofthem);

Can be also be done like this, and this will run faster:

    Something oneofthem;
    Something_ctor(&oneofthem);
    // use oneofthem
    Something_dtor(&oneofthem);

## Usage

When you are using coroutines or generators:

    void *myfunc(void *){
        // your function here
    }

    Coroutine_StartSystem();
    Coroutine_Run(myfunc, (void *)myparam);
    Coroutine_StopSystem();

If you also use async, then:

    bool myfunc(void *myparam, void **res){
        // your async function here
    }

    Async_StartSystem();
    void *res = NULL;
    bool canceled = Async_Run(myfunc, myparam, &res);
    Async_StopSystem();

While the system is started, you can make many calls to `Coroutine_Run()` or `Async_Run()`. A running system is thread local - each thread you want to use coroutines on will need to be `Coroutine_StartSystem()`ed or `Async_StartSystem()`ed.

### Generators

    void *yield_files(void *param){
        bool domore = true;

            // loop/call functions to find more values to yield, and when you have one:
            domore = Generator_Yield(res);
            // .. if domore is false, exit your generator - it is being destructed

        // not actually used by generators, but this is a useful convention for bubbling
        // the flag out to calling functions.
        return (void *)domore;
    }

    Generator gen;
    Generator_ctor(&gen, yield_files, "..");
    int count = 0;
    void *res;
    while(Generator_Next(&gen, &res)){
        // use res - a value yielded by your generator
        printf("%d) %s\n", count, (char *)res);
        free(res);

        // exit your loop early if you want to
        if (++count>16000) break;
    }
    Generator_dtor(&gen);

### Async

To run an Async program:

    Async_StartSystem();
    void *res = NULL;
    bool canceled = Async_Run(asyncmain, &param, &res);
    Async_StopSystem();

Async runs tasks, switching between them when the current task waits on an `Async_Future`. The async main is also a task. The entry function for any task looks like this:

    bool asyncmain(void *param, void **res){

        // do your thing here

        return canceled;
    }

Tasks can complete, or be canceled. Return whether your task was canceled or not.

Within your async task, create `Async_Task`s and `Async_Future_Await()` them when you want to wait for their result. Note that an `Async_Task` has a member, `base`, which is an `Async_Future`, which is what you should wait on:

    bool asyncmain(void *param, void **res){
        ...
        Async_Task task1;
        Async_Task_ctor(&task1, anasynctask, &task1param);

        bool canceled = Async_Future_Await(&task1.base);

        // use the result stored in the future

        Async_Task_dtor(&task1);
        ...
    }
