awaitable coroutine library for C
#include "s_task.h"
void* g_stack_main[64 * 1024]; void* g_stack0[64 * 1024]; void* g_stack1[64 * 1024];
void sub_task(async, void* arg) { int i; int n = (int)(size_t)arg; for (i = 0; i resolve host struct addrinfo* addr = s_uv_getaddrinfo(await, loop, HOST, NULL, NULL); if (addr == NULL) { fprintf(stderr, "can not resolve host %s\n", HOST); goto out0; }
if (addr->ai_addr->sa_family == AF_INET) {
struct sockaddr_in* sin = (struct sockaddr_in*)(addr->ai_addr);
sin->sin_port = htons(PORT);
}
else if (addr->ai_addr->sa_family == AF_INET6) {
struct sockaddr_in6* sin = (struct sockaddr_in6*)(addr->ai_addr);
sin->sin6_port = htons(PORT);
}
// connect
uv_tcp_t tcp_client;
int ret = uv_tcp_init(loop, &tcp_client);
if (ret != 0)
goto out1;
ret = s_uv_tcp_connect(__await__, &tcp_client, addr->ai_addr);
if (ret != 0)
goto out2;
// send request
const char *request = "GET / HTTP/1.0\r\n\r\n";
uv_stream_t* tcp_stream = (uv_stream_t*)&tcp_client;
s_uv_write(__await__, tcp_stream, request, strlen(request));
// read response
ssize_t nread;
char buf[1024];
while (true) {
ret = s_uv_read(__await__, tcp_stream, buf, sizeof(buf), &nread);
if (ret != 0) break;
// output response to console
fwrite(buf, 1, nread, stdout);
}
// close connections
out2:; s_uv_close(await, (uv_handle_t*)&tcp_client); out1:; uv_freeaddrinfo(addr); out0:; }
### [Example 3](build/arduino/arduino.ino) - control LED with multitasking on ardinuo
```c
#include
#include "src/s_task/s_task.h"
//This program demonstrates three tasks:
// 1) main_task -
// Wait 10 seconds and set flag g_exit.
// After all tasks finished, set LED on always.
// 2) sub_task_fast_blinking -
// Set led blinking fast
// 3) sub_task_set_low -
// Set led off for 1 second, and then blinking for 3 seconds.
void setup() {
// put your setup code here, to run once:
pinMode(LED_BUILTIN, OUTPUT);
}
char g_stack0[384];
char g_stack1[384];
volatile bool g_is_low = false;
volatile bool g_exit = false;
void sub_task_fast_blinking(__async__, void* arg) {
while(!g_exit) {
if(!g_is_low)
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on
s_task_msleep(__await__, 50); // wait for 50 milliseconds
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
s_task_msleep(__await__, 50); // wait for 50 milliseconds
}
}
void sub_task_set_low(__async__, void* arg) {
while(!g_exit) {
g_is_low = true; // stop fast blinking
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
s_task_sleep(__await__, 1); // wait for 1 second
g_is_low = false; // start fast blinking
s_task_sleep(__await__, 3); // wait for 3 seconds
}
}
void main_task(__async__, void* arg) {
// create two sub tasks
s_task_create(g_stack0, sizeof(g_stack0), sub_task_fast_blinking, NULL);
s_task_create(g_stack1, sizeof(g_stack1), sub_task_set_low, NULL);
// wait for 10 seconds
s_task_sleep(__await__, 10);
g_exit = true;
// wait two sub tasks return
s_task_join(__await__, g_stack0);
s_task_join(__await__, g_stack1);
}
void loop() {
s_task_init_system();
main_task(__await__, NULL);
// turn the LED on always
digitalWrite(LED_BUILTIN, HIGH);
while(1);
}
…
c
/*
* Return values --
* For all functions marked by __async__ and hava an int return value, will
* return 0 on waiting successfully,
* return -1 on waiting cancalled by s_task_cancel_wait() called by other task.
*/
/* Function type for task entrance */
typedef void(*s_task_fn_t)(__async__, void *arg);
/* System initialization (without USE_LIBUV defined) */
void s_task_init_system();
/* System initialization (with USE_LIBUV defined) */
void s_task_init_uv_system(uv_loop_t *loop);
/* Create a new task */
void s_task_create(void *stack, size_t stack_size, s_task_fn_t entry, void *arg);
/* Wait a task to exit */
int s_task_join(__async__, void *stack);
/* Sleep in milliseconds */
int s_task_msleep(__async__, uint32_t msec);
/* Sleep in seconds */
int s_task_sleep(__async__, uint32_t sec);
/* Yield current task */
void s_task_yield(__async__);
/* Cancel task waiting and make it running */
void s_task_cancel_wait(void* stack);
/*
* macro: Declare the chan variable
* name: name of the chan
* TYPE: type of element in the chan
* count: max count of element buffer in the chan
*/
s_chan_declare(name,TYPE,count);
/*
* macro: Initialize the chan (parameters same as what's in s_declare_chan).
* To make a chan, we need to use "s_chan_declare" and then call "s_chan_init".
*/
s_chan_init(name,TYPE,count);
/*
* Put element into chan
* return 0 on chan put successfully
* return -1 on chan cancelled
*/
int s_chan_put(__async__, s_chan_t *chan, const void *in_object);
/*
* Put number of elements into chan
* return 0 on chan put successfully
* return -1 on chan cancelled
*/
int s_chan_put_n(__async__, s_chan_t *chan, const void *in_object, uint16_t number);
/*
* Get element from chan
* return 0 on chan get successfully
* return -1 on chan cancelled
*/
int s_chan_get(__async__, s_chan_t *chan, void *out_object);
/*
* Get number of elements from chan
* return 0 on chan get successfully
* return -1 on chan cancelled
*/
int s_chan_get_n(__async__, s_chan_t *chan, void *out_object, uint16_t number);
/* Initialize a mutex */
void s_mutex_init(s_mutex_t *mutex);
/* Lock the mutex */
int s_mutex_lock(__async__, s_mutex_t *mutex);
/* Unlock the mutex */
void s_mutex_unlock(s_mutex_t *mutex);
/* Initialize a wait event */
void s_event_init(s_event_t *event);
/* Wait event */
int s_event_wait(__async__, s_event_t *event);
/* Set event */
void s_event_set(s_event_t *event);
/* Wait event with timeout */
int s_event_wait_msec(__async__, s_event_t *event, uint32_t msec);
/* Wait event with timeout */
int s_event_wait_sec(__async__, s_event_t *event, uint32_t sec);
API on embedded platform
/* Task puts element into chan and waits interrupt to read the chan */
void s_chan_put__to_irq(__async__, s_chan_t *chan, const void *in_object);
/* Task puts number of elements into chan and waits interrupt to read the chan */
void s_chan_put_n__to_irq(__async__, s_chan_t *chan, const void *in_object, uint16_t number);
/* Task waits interrupt to write the chan and then gets element from chan */
void s_chan_get__from_irq(__async__, s_chan_t *chan, void *out_object);
/* Task waits interrupt to write the chan and then gets number of elements from chan */
void s_chan_get_n__from_irq(__async__, s_chan_t *chan, void *out_object, uint16_t number);
/*
* Interrupt writes element into the chan,
* return number of element was written into chan
*/
uint16_t s_chan_put__in_irq(s_chan_t *chan, const void *in_object);
/*
* Interrupt writes number of elements into the chan,
* return number of element was written into chan
*/
uint16_t s_chan_put_n__in_irq(s_chan_t *chan, const void *in_object, uint16_t number);
/*
* Interrupt reads element from chan,
* return number of element was read from chan
*/
uint16_t s_chan_get__in_irq(s_chan_t *chan, void *out_object);
/*
* Interrupt reads number of elements from chan,
* return number of element was read from chan
*/
uint16_t s_chan_get_n__in_irq(s_chan_t *chan, void *out_object, uint16_t number);
/*
* Wait event from irq, disable irq before call this function!
* S_IRQ_DISABLE()
* ...
* s_event_wait__from_irq(...)
* ...
* S_IRQ_ENABLE()
*/
int s_event_wait__from_irq(__async__, s_event_t *event);
/*
* Wait event from irq, disable irq before call this function!
* S_IRQ_DISABLE()
* ...
* s_event_wait_msec__from_irq(...)
* ...
* S_IRQ_ENABLE()
*/
int s_event_wait_msec__from_irq(__async__, s_event_t *event, uint32_t msec);
/*
* Wait event from irq, disable irq before call this function!
* S_IRQ_DISABLE()
* ...
* s_event_wait_sec__from_irq(...)
* ...
* S_IRQ_ENABLE()
*/
int s_event_wait_sec__from_irq(__async__, s_event_t *event, uint32_t sec);
/* Set event in interrupt */
void s_event_set__in_irq(s_event_t *event);
Low power mode
If there's no code in function "my_on_idle", the program will run in busy wait mode, which may cause CPU 100% occupied. But we can avoid this and support low power mode by adding correct sleeping instructions in function my_on_idle.
Now we have do that on Windows/Linux/MacOS and Android.
On embedded platform without OS, we may not fully implement low power mode. Please check function "my_on_idle" for the corresponding platform if you want to optimize the power consumption.
void my_on_idle(uint64_t max_idle_ms) {
/* Add code here to make CPU run into sleep mode,
the maximum sleeping time is "max_idle_ms" milliseconds. */
}
使用中有任何问题或建议,欢迎QQ加群 567780316 交流。
No open issues yet, or sync has not completed.