Print this page
XXX rework to avoid changing api
XXX well, it works now...
@@ -16,10 +16,16 @@
v8::Persistent<v8::Function> v8plus::ObjectWrap::_constructor;
v8plus_method_descr_t *v8plus::ObjectWrap::_mtbl;
v8plus_static_descr_t *v8plus::ObjectWrap::_stbl;
std::unordered_map<void *, v8plus::ObjectWrap *> v8plus::ObjectWrap::_objhash;
+uv_async_t v8plus::ObjectWrap::_uv_async;
+pthread_mutex_t v8plus::ObjectWrap::_callq_mutex;
+std::queue<v8plus_async_call_t *> v8plus::ObjectWrap::_callq;
+boolean_t v8plus::ObjectWrap::_crossthread_init_done = _B_FALSE;
+unsigned long v8plus::ObjectWrap::_uv_event_thread;
+
static char *
function_name(const char *lambda)
{
char *fn;
size_t len;
@@ -111,10 +117,28 @@
nvlist_t *c_args;
if ((c_args = v8plus::v8_Arguments_to_nvlist(args)) == NULL)
return (V8PLUS_THROW_DEFAULT());
+ if (_crossthread_init_done == _B_FALSE) {
+ /*
+ * Initialise structures for off-event-loop method calls.
+ *
+ * Note that uv_async_init() must be called inside the libuv
+ * Event Loop, so we do it here. We also want to record the
+ * thread ID of the Event Loop thread so as to determine what
+ * kind of method calls to make later.
+ */
+ _uv_event_thread = pthread_self();
+ if (uv_async_init(uv_default_loop(), &_uv_async,
+ v8plus_async_callback) != 0)
+ v8plus_panic("unable to initialise uv_async_t");
+ if (pthread_mutex_init(&_callq_mutex, NULL) != 0)
+ v8plus_panic("unable to initialise mutex");
+ _crossthread_init_done = _B_TRUE;
+ }
+
c_excp = v8plus_ctor(c_args, &op->_c_impl);
nvlist_free(c_args);
if (op->_c_impl == NULL) {
if (c_excp == NULL) {
return (V8PLUS_THROW_DEFAULT());
@@ -310,10 +334,52 @@
v8plus::ObjectWrap::public_Unref(void)
{
this->Unref();
}
+boolean_t
+v8plus::ObjectWrap::in_event_thread(void)
+{
+ if (_crossthread_init_done != _B_TRUE)
+ v8plus_panic("cross thread call init not done!");
+
+ return (_uv_event_thread == pthread_self() ? _B_TRUE : _B_FALSE);
+}
+
+v8plus_async_call_t *
+v8plus::ObjectWrap::next_async_call(void)
+{
+ v8plus_async_call_t *ret = NULL;
+
+ if (pthread_mutex_lock(&_callq_mutex) != 0)
+ v8plus_panic("could not lock callq mutex");
+
+ if (!_callq.empty()) {
+ ret = _callq.front();
+ _callq.pop();
+ }
+
+ if (pthread_mutex_unlock(&_callq_mutex) != 0)
+ v8plus_panic("could not release callq mutex");
+
+ return (ret);
+}
+
+void
+v8plus::ObjectWrap::post_async_call(v8plus_async_call_t *ac)
+{
+ if (pthread_mutex_lock(&_callq_mutex) != 0)
+ v8plus_panic("could not lock callq mutex");
+
+ _callq.push(ac);
+
+ if (pthread_mutex_unlock(&_callq_mutex) != 0)
+ v8plus_panic("could not release callq mutex");
+
+ uv_async_send(&_uv_async);
+}
+
extern "C" void
init(v8::Handle<v8::Object> target)
{
v8plus::ObjectWrap::init(target);
}