Last active
February 6, 2020 16:09
-
-
Save braydonf/a28c6283fa1f2b5e9219a8a283a9f2f8 to your computer and use it in GitHub Desktop.
libuv example for cancelling queued work
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// An implementation of what is decribed at: | |
// https://nikhilm.github.io/uvbook/threads.html#id1 | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdbool.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <uv.h> | |
static const int FIB_UNTIL = 100; | |
static uv_work_t **fib_reqs; | |
long fib_(int n) | |
{ | |
int c = 0; | |
int next = 0; | |
int first = 0; | |
int second = 1; | |
for (c = 0; c < n; c++) { | |
if (c <= 1) { | |
next = c; | |
} else { | |
next = first + second; | |
first = second; | |
second = next; | |
} | |
} | |
return next; | |
} | |
void fib(uv_work_t *req) { | |
int n = *(int *) req->data; | |
if (random() % 2){ | |
sleep(1); | |
} else { | |
sleep(3); | |
} | |
long fib = fib_(n); | |
printf("%dth fibonacci is %lu\n", n, fib); | |
} | |
void after_fib(uv_work_t *req, int status) { | |
int i = *(int *) req->data; | |
if (status == UV_ECANCELED) { | |
printf("Cancelled\n"); | |
} else if (!status){ | |
printf("Done calculating %dth fibonacci\n", i); | |
} | |
free(req->data); | |
free(req); | |
} | |
void close_signal(uv_handle_t *handle) | |
{ | |
free(fib_reqs); | |
} | |
void signal_handler(uv_signal_t *req, int signum) | |
{ | |
printf("Signal received!\n"); | |
int i; | |
for (i = 0; i < FIB_UNTIL; i++) { | |
uv_cancel((uv_req_t*) fib_reqs[i]); | |
} | |
if (uv_signal_stop(req)) { | |
printf("Unable to stop signal\n"); | |
} | |
uv_close((uv_handle_t *)req, close_signal); | |
} | |
int main() { | |
uv_loop_t *loop = malloc(sizeof(uv_loop_t)); | |
if (uv_loop_init(loop)) { | |
printf("Unable no init loop\n"); | |
return 1; | |
} | |
fib_reqs = malloc(sizeof(uv_work_t) * FIB_UNTIL); | |
if (!fib_reqs) { | |
printf("Unable to allocate memory\n"); | |
exit(1); | |
} | |
int i; | |
for (i = 0; i < FIB_UNTIL; i++) { | |
int *data = malloc(sizeof(int)); | |
memcpy(data, &i, sizeof(int)); | |
uv_work_t *work = malloc(sizeof(uv_work_t)); | |
work->data = (void *) data; | |
fib_reqs[i] = work; | |
uv_queue_work(loop, fib_reqs[i], fib, after_fib); | |
} | |
uv_signal_t sig; | |
uv_signal_init(loop, &sig); | |
uv_signal_start(&sig, signal_handler, SIGINT); | |
bool more; | |
do { | |
more = uv_run(loop, UV_RUN_ONCE); | |
if (more == false) { | |
more = uv_loop_alive(loop); | |
if (uv_run(loop, UV_RUN_NOWAIT) != 0) { | |
more = true; | |
} | |
} | |
} while (more == true); | |
printf("Loop alive: %i\n", uv_loop_alive(loop)); | |
int status = uv_loop_close(loop); | |
if (status == 0) { | |
printf("Event loop closed!\n"); | |
} else if (status == UV_ECANCELED) { | |
printf("Cancelled!\n"); | |
return 1; | |
} else if (status == UV_EBUSY) { | |
printf("Busy!\n"); | |
return 1; | |
} else if (status){ | |
printf("Error when closing loop: %i\n", status); | |
return 1; | |
} | |
free(loop); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment