bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 1/7] libnotify: add a general notification library


From: Justus Winter
Subject: [PATCH 1/7] libnotify: add a general notification library
Date: Mon, 16 Sep 2013 16:08:59 +0200

XXX
---
 libhurdnotify/Makefile |   28 ++++++
 libhurdnotify/notify.c |  251 ++++++++++++++++++++++++++++++++++++++++++++++++
 libhurdnotify/notify.h |   73 ++++++++++++++
 3 files changed, 352 insertions(+)
 create mode 100644 libhurdnotify/Makefile
 create mode 100644 libhurdnotify/notify.c
 create mode 100644 libhurdnotify/notify.h

diff --git a/libhurdnotify/Makefile b/libhurdnotify/Makefile
new file mode 100644
index 0000000..8c7b780
--- /dev/null
+++ b/libhurdnotify/Makefile
@@ -0,0 +1,28 @@
+# Copyright (C) 2013 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Hurd.
+#
+# The GNU Hurd is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2, or (at
+# your option) any later version.
+#
+# The GNU Hurd is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.
+
+dir := libhurdnotify
+makemode := library
+
+libname := libhurdnotify
+SRCS = notify.c
+installhdrs = notify.h
+
+OBJS = $(SRCS:.c=.o)
+HURDLIBS = ihash
+
+include ../Makeconf
diff --git a/libhurdnotify/notify.c b/libhurdnotify/notify.c
new file mode 100644
index 0000000..26bc149
--- /dev/null
+++ b/libhurdnotify/notify.c
@@ -0,0 +1,251 @@
+/* XXX */
+
+#include <hurd/notify.h>
+#include <stdlib.h>
+#include <time.h>
+
+static void hurd_notify_cleanup (hurd_ihash_value_t value, void *arg);
+
+/* XXX */
+void
+hurd_notify_init (hurd_notify_t n,
+                  hurd_notify_func_t notify_func,
+                  hurd_notify_cleanup_t cleanup_func)
+{
+  hurd_ihash_init (&n->receivers, HURD_IHASH_NO_LOCP);
+  hurd_ihash_set_cleanup (&n->receivers, hurd_notify_cleanup, &n);
+  n->notify_func = notify_func;
+  n->cleanup_func = cleanup_func;
+  n->first = NULL;
+  n->last = NULL;
+}
+
+/* XXX */
+void
+hurd_notify_destroy (hurd_notify_t n)
+{
+  hurd_ihash_destroy (&n->receivers);
+}
+
+/* XXX */
+error_t
+hurd_notify_create (hurd_notify_t *n,
+                    hurd_notify_func_t notify_func,
+                    hurd_notify_cleanup_t cleanup_func)
+{
+  *n = malloc (sizeof (struct hurd_notify));
+  if (*n == NULL)
+    return ENOMEM;
+
+  hurd_notify_init (*n, notify_func, cleanup_func);
+
+  return 0;
+}
+
+/* XXX */
+void
+hurd_notify_free (hurd_notify_t n)
+{
+  hurd_notify_destroy (n);
+  free (n);
+}
+
+static struct hurd_notify_receiver *
+new_receiver (mach_port_t notify,
+              void *data,
+              struct hurd_notify_receiver *previous,
+              struct hurd_notify_receiver *next)
+{
+  struct hurd_notify_receiver *r;
+  r = malloc (sizeof (struct hurd_notify_receiver));
+  if (! r)
+    return NULL;
+
+  r->port = notify;
+  r->data = data;
+  r->previous = previous;
+  r->next = next;
+  return r;
+}
+
+
+/* XXX */
+error_t
+hurd_notify_prepend (hurd_notify_t n, mach_port_t notify, void *data)
+{
+  error_t err;
+
+  struct hurd_notify_receiver *r;
+  r = new_receiver (notify, data, NULL, n->first);
+  if (! r)
+    return ENOMEM;
+
+  err = hurd_ihash_add (&n->receivers, notify, r);
+  if (err)
+    {
+      free (r);
+      return err;
+    }
+
+  n->first = r;
+  if (! n->last)
+    n->last = r;
+  return 0;
+}
+
+/* XXX */
+error_t
+hurd_notify_append (hurd_notify_t n, mach_port_t notify, void *data)
+{
+  error_t err;
+
+  struct hurd_notify_receiver *r;
+  r = new_receiver (notify, data, n->last, NULL);
+  if (! r)
+    return ENOMEM;
+
+  err = hurd_ihash_add (&n->receivers, notify, r);
+  if (err)
+    {
+      free (r);
+      return err;
+    }
+
+  if (! n->first)
+    n->first = r;
+  n->last = r;
+  return 0;
+}
+
+static void
+hurd_notify_cleanup (hurd_ihash_value_t value, void *arg)
+{
+  struct hurd_notify *n = arg;
+  struct hurd_notify_receiver *r = value;
+
+  if (n->cleanup_func)
+    n->cleanup_func (r);
+
+  if (r->previous)
+    r->previous->next = r->next;
+  else
+    n->first = r->next;
+
+  if (r->next)
+    r->next->previous = r->previous;
+  else
+    n->last = r->previous;
+
+  free (r);
+}
+
+/* XXX */
+int
+hurd_notify_remove (hurd_notify_t n, mach_port_t notify)
+{
+  return hurd_ihash_remove (&n->receivers, notify);
+}
+
+/* XXX */
+error_t
+hurd_notify_do_notify (hurd_notify_t n, void *common_data)
+{
+  error_t err;
+  for (struct hurd_notify_receiver *r = n->first;
+       r; r = r? r->next: n->first)
+    {
+      err = n->notify_func (r->port,
+                            MACH_PORT_NULL,
+                            r->data,
+                            common_data);
+      if (err == MACH_SEND_INVALID_DEST)
+        {
+          hurd_ihash_key_t key = (hurd_ihash_key_t) r->port;
+          r = r->previous?: NULL;
+          hurd_notify_remove (n, key);
+        }
+    }
+
+  return 0;
+}
+
+/* XXX */
+error_t
+hurd_notify_do_notify_wait (hurd_notify_t n,
+                            void *common_data,
+                            natural_t timeout)
+{
+  error_t err;
+  mach_port_t port_set;
+  err = mach_port_allocate (mach_task_self (),
+                            MACH_PORT_RIGHT_PORT_SET,
+                            &port_set);
+  if (err)
+    return err;
+
+  int count = 0;
+  for (struct hurd_notify_receiver *r = n->first;
+       r; r = r? r->next: n->first)
+    {
+      mach_port_t reply_port = mach_reply_port ();
+      if (reply_port == MACH_PORT_NULL)
+        return ENOMEM; /* XXX */
+
+      err = mach_port_move_member (mach_task_self (),
+                                   reply_port,
+                                   port_set);
+      if (err)
+        return err; /* XXX */
+
+      err = n->notify_func (r->port,
+                            reply_port,
+                            r->data,
+                            common_data);
+      if (err == MACH_SEND_INVALID_DEST)
+        {
+          hurd_ihash_key_t key = (hurd_ihash_key_t) r->port;
+          r = r->previous?: NULL;
+          hurd_notify_remove (n, key);
+          continue;
+        }
+
+      count += 1;
+    }
+
+  time_t start_time = time (NULL);
+  time_t remaining_time;
+  while (count > 0 &&
+         (remaining_time = timeout - (time (NULL) - start_time) * 1000) > 0)
+    {
+      struct Reply {
+        mach_msg_header_t Head;
+        mach_msg_type_t RetCodeType;
+        kern_return_t RetCode;
+      } reply;
+
+      /* Receive a reply message from any port in our port set with
+         timeout being set to the remaining time.  */
+      err = mach_msg (&reply.Head,
+                      MACH_RCV_MSG|MACH_MSG_OPTION_NONE|MACH_RCV_TIMEOUT,
+                      0,
+                      sizeof (struct Reply),
+                      port_set,
+                      remaining_time,
+                      MACH_PORT_NULL);
+      if (err)
+        return err; /* XXX */
+
+      /* Remove that port from the set.  */
+      err = mach_port_move_member (mach_task_self (),
+                                   reply.Head.msgh_remote_port,
+                                   MACH_PORT_NULL);
+      if (err)
+        return err; /* XXX */
+
+      mach_port_deallocate (mach_task_self (), reply.Head.msgh_remote_port);
+
+      count -= 1;
+    }
+
+  return 0;
+}
diff --git a/libhurdnotify/notify.h b/libhurdnotify/notify.h
new file mode 100644
index 0000000..7428180
--- /dev/null
+++ b/libhurdnotify/notify.h
@@ -0,0 +1,73 @@
+/* XXX */
+
+#ifndef _HURD_NOTIFY_H
+#define _HURD_NOTIFY_H
+
+#include <hurd/ihash.h>
+#include <mach.h>
+
+/* XXX */
+typedef error_t (*hurd_notify_func_t) (mach_port_t port,
+                                       mach_port_t reply_port,
+                                       void *data,
+                                       void *common_data);
+
+/* Cleanup function.  */
+typedef void (*hurd_notify_cleanup_t) (void *data);
+
+/* This structure keeps track of each receiver.  */
+struct hurd_notify_receiver
+{
+  mach_port_t port;
+  void *data;
+  struct hurd_notify_receiver *previous;
+  struct hurd_notify_receiver *next;
+};
+
+
+/* XXX */
+struct hurd_notify
+{
+  struct hurd_ihash receivers;
+  hurd_notify_func_t notify_func;
+  hurd_notify_cleanup_t cleanup_func;
+  struct hurd_notify_receiver *first;
+  struct hurd_notify_receiver *last;
+};
+
+typedef struct hurd_notify *hurd_notify_t;
+
+/* XXX */
+void hurd_notify_init (hurd_notify_t n,
+                       hurd_notify_func_t notify_func,
+                       hurd_notify_cleanup_t cleanup_func);
+
+/* XXX */
+void hurd_notify_destroy (hurd_notify_t n);
+
+/* XXX */
+error_t hurd_notify_create (hurd_notify_t *n,
+                            hurd_notify_func_t notify_func,
+                            hurd_notify_cleanup_t cleanup_func);
+
+/* XXX */
+void hurd_notify_free (hurd_notify_t n);
+
+/* XXX */
+error_t hurd_notify_prepend (hurd_notify_t n, mach_port_t notify, void *data);
+
+/* XXX */
+error_t hurd_notify_append (hurd_notify_t n, mach_port_t notify, void *data);
+
+/* XXX */
+int hurd_notify_remove (hurd_notify_t n, mach_port_t notify);
+
+/* XXX */
+error_t hurd_notify_do_notify (hurd_notify_t n, void *common_data);
+
+/* XXX */
+error_t hurd_notify_do_notify_wait (hurd_notify_t n,
+                                    void *common_data,
+                                    natural_t timeout);
+
+#endif /* _HURD_NOTIFY_H */
-- 
1.7.10.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]