diff options
Diffstat (limited to 'src/mbgl/util/uv-messenger.c')
-rw-r--r-- | src/mbgl/util/uv-messenger.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/mbgl/util/uv-messenger.c b/src/mbgl/util/uv-messenger.c new file mode 100644 index 0000000000..935b6f1c41 --- /dev/null +++ b/src/mbgl/util/uv-messenger.c @@ -0,0 +1,86 @@ +#include <mbgl/util/uv-messenger.h> +#include <mbgl/util/queue.h> + +#include <stdlib.h> +#include <assert.h> + +typedef struct { + void *data; + void *queue[2]; +} uv__messenger_item_t; + +#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10 +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +void uv__messenger_callback(uv_async_t *async, int status) { +#pragma clang diagnostic pop +#else +void uv__messenger_callback(uv_async_t *async) { +#endif + uv_messenger_t *msgr = (uv_messenger_t *)async->data; + + uv__messenger_item_t *item; + QUEUE *head; + + while (1) { + uv_mutex_lock(&msgr->mutex); + if (QUEUE_EMPTY(&msgr->queue)) { + uv_mutex_unlock(&msgr->mutex); + break; + } + + head = QUEUE_HEAD(&msgr->queue); + item = QUEUE_DATA(head, uv__messenger_item_t, queue); + QUEUE_REMOVE(head); + uv_mutex_unlock(&msgr->mutex); + + msgr->callback(item->data); + + free(item); + } +} + +int uv_messenger_init(uv_loop_t *loop, uv_messenger_t *msgr, uv_messenger_cb callback) { + int ret = uv_mutex_init(&msgr->mutex); + if (ret < 0) { + return ret; + } + + msgr->callback = callback; + msgr->stop_callback = NULL; + + QUEUE_INIT(&msgr->queue); + + msgr->async.data = msgr; + return uv_async_init(loop, &msgr->async, uv__messenger_callback); +} + +void uv_messenger_send(uv_messenger_t *msgr, void *data) { + uv__messenger_item_t *item = (uv__messenger_item_t *)malloc(sizeof(uv__messenger_item_t)); + item->data = data; + + uv_mutex_lock(&msgr->mutex); + QUEUE_INSERT_TAIL(&msgr->queue, &item->queue); + uv_mutex_unlock(&msgr->mutex); + + uv_async_send(&msgr->async); +} + +void uv_messenger_ref(uv_messenger_t *msgr) { + uv_ref((uv_handle_t *)&msgr->async); +} + +void uv_messenger_unref(uv_messenger_t *msgr) { + uv_unref((uv_handle_t *)&msgr->async); +} + +void uv__messenger_stop_callback(uv_handle_t *handle) { + uv_messenger_t *msgr = (uv_messenger_t *)handle->data; + msgr->stop_callback(msgr); +} + +void uv_messenger_stop(uv_messenger_t *msgr, uv_messenger_stop_cb stop_callback) { + assert(!msgr->stop_callback); + msgr->stop_callback = stop_callback; + uv_close((uv_handle_t *)&msgr->async, uv__messenger_stop_callback); +} |