#ifndef NODE_SQLITE3_SRC_ASYNC_H #define NODE_SQLITE3_SRC_ASYNC_H #include "threading.h" #include #if defined(NODE_SQLITE3_BOOST_THREADING) #include #endif // Generic uv_async handler. template class Async { typedef void (*Callback)(Parent* parent, Item* item); protected: uv_async_t watcher; NODE_SQLITE3_MUTEX_t std::vector data; Callback callback; public: Parent* parent; public: Async(Parent* parent_, Callback cb_) : callback(cb_), parent(parent_) { watcher.data = this; NODE_SQLITE3_MUTEX_INIT uv_async_init(uv_default_loop(), &watcher, reinterpret_cast(listener)); } static void listener(uv_async_t* handle, int status) { Async* async = static_cast(handle->data); std::vector rows; NODE_SQLITE3_MUTEX_LOCK(&async->mutex) rows.swap(async->data); NODE_SQLITE3_MUTEX_UNLOCK(&async->mutex) for (unsigned int i = 0, size = rows.size(); i < size; i++) { #if NODE_VERSION_AT_LEAST(0, 7, 9) uv_unref((uv_handle_t *)&async->watcher); #else uv_unref(uv_default_loop()); #endif async->callback(async->parent, rows[i]); } } static void close(uv_handle_t* handle) { assert(handle != NULL); assert(handle->data != NULL); Async* async = static_cast(handle->data); delete async; } void finish() { // Need to call the listener again to ensure all items have been // processed. Is this a bug in uv_async? Feels like uv_close // should handle that. listener(&watcher, 0); uv_close((uv_handle_t*)&watcher, close); } void add(Item* item) { // Make sure node runs long enough to deliver the messages. #if NODE_VERSION_AT_LEAST(0, 7, 9) uv_ref((uv_handle_t *)&watcher); #else uv_ref(uv_default_loop()); #endif NODE_SQLITE3_MUTEX_LOCK(&mutex); data.push_back(item); NODE_SQLITE3_MUTEX_UNLOCK(&mutex) } void send() { uv_async_send(&watcher); } void send(Item* item) { add(item); send(); } ~Async() { NODE_SQLITE3_MUTEX_DESTROY } }; #endif