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 |
|
10 | template <class Item, class Parent> class Async {
|
11 | typedef void (*Callback)(Parent* parent, Item* item);
|
12 |
|
13 | protected:
|
14 | uv_async_t watcher;
|
15 | NODE_SQLITE3_MUTEX_t
|
16 | std::vector<Item*> data;
|
17 | Callback callback;
|
18 | public:
|
19 | Parent* parent;
|
20 |
|
21 | public:
|
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 |
|
50 |
|
51 |
|
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
|