aboutsummaryrefslogtreecommitdiff
path: root/src/core/pollable.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/pollable.c')
-rw-r--r--src/core/pollable.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/src/core/pollable.c b/src/core/pollable.c
new file mode 100644
index 00000000..b5cecf37
--- /dev/null
+++ b/src/core/pollable.c
@@ -0,0 +1,101 @@
+//
+// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
+// Copyright 2018 Capitar IT Group BV <info@capitar.com>
+//
+// 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"
+
+struct nni_pollable {
+ int p_rfd;
+ int p_wfd;
+ nni_mtx p_lock;
+ bool p_raised;
+ bool p_open;
+};
+
+int
+nni_pollable_alloc(nni_pollable **pp)
+{
+ nni_pollable *p;
+ if ((p = NNI_ALLOC_STRUCT(p)) == NULL) {
+ return (NNG_ENOMEM);
+ }
+ p->p_open = false;
+ p->p_raised = false;
+ nni_mtx_init(&p->p_lock);
+ *pp = p;
+ return (0);
+}
+
+void
+nni_pollable_free(nni_pollable *p)
+{
+ if (p == NULL) {
+ return;
+ }
+ if (p->p_open) {
+ nni_plat_pipe_close(p->p_rfd, p->p_wfd);
+ }
+ nni_mtx_fini(&p->p_lock);
+ NNI_FREE_STRUCT(p);
+}
+
+void
+nni_pollable_raise(nni_pollable *p)
+{
+ if (p == NULL) {
+ return;
+ }
+ nni_mtx_lock(&p->p_lock);
+ p->p_raised = true;
+ if (p->p_open) {
+ nni_mtx_unlock(&p->p_lock);
+ nni_plat_pipe_raise(p->p_wfd);
+ return;
+ }
+ nni_mtx_unlock(&p->p_lock);
+}
+
+void
+nni_pollable_clear(nni_pollable *p)
+{
+ if (p == NULL) {
+ return;
+ }
+ nni_mtx_lock(&p->p_lock);
+ p->p_raised = false;
+ if (p->p_open) {
+ nni_mtx_unlock(&p->p_lock);
+ nni_plat_pipe_clear(p->p_rfd);
+ return;
+ }
+ nni_mtx_unlock(&p->p_lock);
+}
+
+int
+nni_pollable_getfd(nni_pollable *p, int *fdp)
+{
+ if (p == NULL) {
+ return (NNG_EINVAL);
+ }
+ nni_mtx_lock(&p->p_lock);
+ if (!p->p_open) {
+ int rv;
+ if ((rv = nni_plat_pipe_open(&p->p_wfd, &p->p_rfd)) != 0) {
+ nni_mtx_unlock(&p->p_lock);
+ return (rv);
+ }
+ p->p_open = true;
+ if (p->p_raised) {
+ nni_plat_pipe_raise(p->p_wfd);
+ }
+ }
+ nni_mtx_unlock(&p->p_lock);
+ *fdp = p->p_rfd;
+ return (0);
+}