aboutsummaryrefslogtreecommitdiff
path: root/src/core/event.c
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2017-01-16 16:27:22 -0800
committerGarrett D'Amore <garrett@damore.org>2017-01-16 16:27:22 -0800
commitac8415c24ffea645105c3859e814843e81c97f8a (patch)
tree7b64b4aab3de6ce5bdd69c3d5b7ead57f4a4b4e7 /src/core/event.c
parentb8f7236aa2928d70d9bff2e1071654982539eeda (diff)
downloadnng-ac8415c24ffea645105c3859e814843e81c97f8a.tar.gz
nng-ac8415c24ffea645105c3859e814843e81c97f8a.tar.bz2
nng-ac8415c24ffea645105c3859e814843e81c97f8a.zip
Start of event framework.
This compiles correctly, but doesn't actually deliver events yet. As part of this, I've made most of the initializables in nng safe to tear-down if uninitialized (or set to zero e.g. via calloc). This makes it loads easier to write the teardown on error code, since I can deinit everything, without worrying about which things have been initialized and which have not.
Diffstat (limited to 'src/core/event.c')
-rw-r--r--src/core/event.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/core/event.c b/src/core/event.c
new file mode 100644
index 00000000..3f7d1143
--- /dev/null
+++ b/src/core/event.c
@@ -0,0 +1,103 @@
+//
+// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+#include "core/nng_impl.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+int
+nni_event_init(nni_event *event, int type, nni_sock *sock)
+{
+ int rv;
+
+ memset(event, 0, sizeof (*event));
+ if ((rv = nni_cv_init(&event->e_cv, &sock->s_mx)) != 0) {
+ return (rv);
+ }
+ NNI_LIST_NODE_INIT(&event->e_node);
+ event->e_type = type;
+ event->e_sock = sock;
+ return (0);
+}
+
+
+void
+nni_event_fini(nni_event *event)
+{
+ nni_cv_fini(&event->e_cv);
+}
+
+
+void
+nni_event_submit(nni_sock *sock, nni_event *event)
+{
+ // Call with socket mutex owned!
+ if (event->e_pending == 0) {
+ event->e_pending = 1;
+ event->e_done = 0;
+ nni_list_append(&sock->s_events, event);
+ nni_cv_wake(&sock->s_notify_cv);
+ }
+}
+
+
+void
+nni_event_wait(nni_sock *sock, nni_event *event)
+{
+ // Call with socket mutex owned!
+ // Note that the socket mutex is dropped during the call.
+ while ((event->e_pending) && (!event->e_done)) {
+ nni_cv_wait(&event->e_cv);
+ }
+}
+
+
+void
+nni_event_notifier(void *arg)
+{
+ nni_sock *sock = arg;
+ nni_event *event;
+ nni_notify *notify;
+
+ nni_mtx_lock(&sock->s_mx);
+ for (;;) {
+ if (sock->s_closing) {
+ break;
+ }
+
+ if ((event = nni_list_first(&sock->s_events)) != NULL) {
+ event->e_pending = 0;
+ nni_list_remove(&sock->s_events, event);
+ nni_mtx_unlock(&sock->s_mx);
+
+ // Lock the notify list, it must not change.
+ nni_mtx_lock(&sock->s_notify_mx);
+ NNI_LIST_FOREACH (&sock->s_notify, notify) {
+ if ((notify->n_mask & event->e_type) == 0) {
+ // No interest.
+ continue;
+ }
+ notify->n_func(event, &notify->n_arg);
+ }
+ nni_mtx_unlock(&sock->s_notify_mx);
+
+ nni_mtx_lock(&sock->s_mx);
+ // Let the event submitter know we are done, unless
+ // they have resubmitted. Submitters can wait on this
+ // lock.
+ event->e_done = 1;
+ nni_cv_wake(&event->e_cv);
+ continue;
+ }
+
+ nni_cv_wait(&sock->s_notify_cv);
+ }
+ nni_mtx_unlock(&sock->s_mx);
+}