[beast: 6/47] V8BSE: handle remote events even if uv_loop missed pollfd notifications
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast: 6/47] V8BSE: handle remote events even if uv_loop missed pollfd notifications
- Date: Sat, 2 Sep 2017 00:42:26 +0000 (UTC)
commit 87a83895a76295182225e43f2b9864c8a8d79a12
Author: Tim Janik <timj gnu org>
Date: Sat Apr 8 16:25:46 2017 +0200
V8BSE: handle remote events even if uv_loop missed pollfd notifications
Signed-off-by: Tim Janik <timj gnu org>
ebeast/v8bse/nodemodule.cc | 44 ++++++++++++++++++++++++++++++++++----------
1 files changed, 34 insertions(+), 10 deletions(-)
---
diff --git a/ebeast/v8bse/nodemodule.cc b/ebeast/v8bse/nodemodule.cc
index 3cc819b..acc3aad 100644
--- a/ebeast/v8bse/nodemodule.cc
+++ b/ebeast/v8bse/nodemodule.cc
@@ -200,6 +200,8 @@ static V8stub *bse_v8stub = NULL;
static uv_poll_t bse_uv_watcher;
static Aida::ClientConnectionP bse_client_connection;
static Bse::ServerH bse_server;
+static uv_async_t bse_uv_dispatcher;
+static uv_prepare_t bse_uv_preparer;
// register bindings and start Bse
static void
@@ -225,18 +227,40 @@ v8bse_register_module (v8::Local<v8::Object> exports)
assert (bse_server != NULL);
// hook BSE connection into libuv event loop
- uv_loop_t *loop = uv_default_loop();
- uv_poll_init (loop, &bse_uv_watcher, bse_client_connection->notify_fd());
- auto bse_uv_callback = [] (uv_poll_t *watcher, int status, int revents) {
+ uv_loop_t *uvloop = uv_default_loop();
+ // Dispatch any pending events from uvlooop
+ auto uvdispatchcb = [] (uv_async_t*) {
+ if (bse_client_connection)
+ while (bse_client_connection->pending())
+ bse_client_connection->dispatch();
+ };
+ uv_async_init (uvloop, &bse_uv_dispatcher, uvdispatchcb);
+ // Poll notify_fd, clear fd and queue dispatcher events
+ auto uvpollcb = [] (uv_poll_t*, int, int) {
if (bse_client_connection && bse_client_connection->pending())
- bse_client_connection->dispatch();
+ uv_async_send (&bse_uv_dispatcher);
};
- uv_poll_start (&bse_uv_watcher, UV_READABLE, bse_uv_callback);
-
- // hook BSE connection into GLib event loop
- Bse::AidaGlibSource *source = Bse::AidaGlibSource::create (bse_client_connection.get());
- g_source_set_priority (source, G_PRIORITY_DEFAULT);
- g_source_attach (source, g_main_context_default());
+ uv_poll_init (uvloop, &bse_uv_watcher, bse_client_connection->notify_fd());
+ uv_poll_start (&bse_uv_watcher, UV_READABLE, uvpollcb);
+ // Prevent libuv from waiting in poll if events are pending
+ auto uvpreparecb = [] (uv_prepare_t*) {
+ if (bse_client_connection && bse_client_connection->pending())
+ uv_async_send (&bse_uv_dispatcher);
+ };
+ uv_prepare_init (uvloop, &bse_uv_preparer);
+ uv_prepare_start (&bse_uv_preparer, uvpreparecb);
+ /* Electron drives the uvloop via UV_RUN_NOWAIT and outsources fd polling into
+ * a dedicated worker thread. And that means the bse_client_connection may be
+ * dispatching calls *and* fetching remote events or return values without
+ * notify_fd getting a chance to wakeup poll(2). So we use a notify_callback
+ * to check for pending events after each remote call.
+ */
+ auto bsenotfycb = [] (Rapicorn::Aida::ClientConnection &con) {
+ // bse_client_connection == &con
+ if (bse_client_connection && bse_client_connection->pending())
+ uv_async_send (&bse_uv_dispatcher);
+ };
+ bse_client_connection->notify_callback (bsenotfycb);
// register v8stub
v8::Local<v8::Context> context = isolate->GetCurrentContext();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]