UNPKG

1.9 kBtext/x-cView Raw
1#ifndef NODE_SQLITE3_SRC_ASYNC_H
2#define NODE_SQLITE3_SRC_ASYNC_H
3
4#include <napi.h>
5#include <uv.h>
6
7#include "threading.h"
8
9// Generic uv_async handler.
10template <class Item, class Parent> class Async {
11 typedef void (*Callback)(Parent* parent, Item* item);
12
13protected:
14 uv_async_t watcher;
15 NODE_SQLITE3_MUTEX_t
16 std::vector<Item*> data;
17 Callback callback;
18public:
19 Parent* parent;
20
21public:
22 Async(Parent* parent_, Callback cb_)
23 : callback(cb_), parent(parent_) {
24 watcher.data = this;
25 NODE_SQLITE3_MUTEX_INIT
26 uv_loop_t *loop;
27 napi_get_uv_event_loop(parent_->Env(), &loop);
28 uv_async_init(loop, &watcher, reinterpret_cast<uv_async_cb>(listener));
29 }
30
31 static void listener(uv_async_t* handle) {
32 auto* async = static_cast<Async*>(handle->data);
33 std::vector<Item*> rows;
34 NODE_SQLITE3_MUTEX_LOCK(&async->mutex)
35 rows.swap(async->data);
36 NODE_SQLITE3_MUTEX_UNLOCK(&async->mutex)
37 for(auto row : rows)
38 async->callback(async->parent, row);
39 }
40
41 static void close(uv_handle_t* handle) {
42 assert(handle != NULL);
43 assert(handle->data != NULL);
44 auto* async = static_cast<Async*>(handle->data);
45 delete async;
46 }
47
48 void finish() {
49 // Need to call the listener again to ensure all items have been
50 // processed. Is this a bug in uv_async? Feels like uv_close
51 // should handle that.
52 listener(&watcher);
53 uv_close((uv_handle_t*)&watcher, close);
54 }
55
56 void add(Item* item) {
57 NODE_SQLITE3_MUTEX_LOCK(&mutex);
58 data.emplace_back(item);
59 NODE_SQLITE3_MUTEX_UNLOCK(&mutex)
60 }
61
62 void send() {
63 uv_async_send(&watcher);
64 }
65
66 void send(Item* item) {
67 add(item);
68 send();
69 }
70
71 ~Async() {
72 NODE_SQLITE3_MUTEX_DESTROY
73 }
74};
75
76#endif