Skip to content

Instantly share code, notes, and snippets.

@braydonf
Last active February 6, 2020 16:09
Show Gist options
  • Save braydonf/a28c6283fa1f2b5e9219a8a283a9f2f8 to your computer and use it in GitHub Desktop.
Save braydonf/a28c6283fa1f2b5e9219a8a283a9f2f8 to your computer and use it in GitHub Desktop.
libuv example for cancelling queued work
// 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