Allow to remove systemd library
[src/app-framework-binder.git] / src / evmgr.c
index 2dc35e4..d26502d 100644 (file)
 
 #include "evmgr.h"
 #include "verbose.h"
+
+#if WITH_SYSTEMD
 #include "systemd.h"
+#else
+#include "fdev-epoll.h"
+#include "fdev.h"
+#endif
 
 /** Description of handled event loops */
 struct evmgr
 {
-       unsigned state;        /**< encoded state */
        int efd;               /**< event notification */
+       unsigned state;        /**< encoded state */
        void *holder;          /**< holder of the evmgr */
+#if WITH_SYSTEMD
        struct sd_event *sdev; /**< the systemd event loop */
+#endif
+#if WITH_FDEV_EPOLL
+       struct fdev_epoll *fdev_epoll;
+       struct fdev *fdev;
+#endif
 };
 
 #define EVLOOP_STATE_WAIT           1U
 #define EVLOOP_STATE_RUN            2U
 
+
+/**
+ * Internal callback for evmgr management.
+ * The effect of this function is hidden: it exits
+ * the waiting poll if any.
+ */
+static void evmgr_on_efd_event(struct evmgr *evmgr)
+{
+       uint64_t x;
+       read(evmgr->efd, &x, sizeof x);
+}
+
+/**
+ * wakeup the event loop if needed by sending
+ * an event.
+ */
+void evmgr_wakeup(struct evmgr *evmgr)
+{
+       uint64_t x;
+
+       if (evmgr->state & EVLOOP_STATE_WAIT) {
+               x = 1;
+               write(evmgr->efd, &x, sizeof x);
+       }
+}
+
+/**
+ */
+void *evmgr_holder(struct evmgr *evmgr)
+{
+       return evmgr->holder;
+}
+
+/**
+ */
+int evmgr_release_if(struct evmgr *evmgr, void *holder)
+{
+       if (evmgr->holder != holder)
+               return 0;
+       evmgr->holder = 0;
+       return 1;
+}
+
+/**
+ */
+int evmgr_try_hold(struct evmgr *evmgr, void *holder)
+{
+       if (!evmgr->holder)
+               evmgr->holder = holder;
+       return evmgr->holder == holder;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+/******  SYSTEM D                                                        ******/
+/******************************************************************************/
+/******************************************************************************/
+
+#if WITH_SYSTEMD
+
 /**
  * Run the event loop is set.
  */
@@ -98,59 +170,101 @@ int evmgr_can_run(struct evmgr *evmgr)
 /**
  * Internal callback for evmgr management.
  * The effect of this function is hidden: it exits
- * the waiting poll if any.
+ * the waiting poll if any. Then it wakes up a thread
+ * awaiting the evmgr using signal.
  */
-static void evmgr_on_efd_event(struct evmgr *evmgr)
+static int on_evmgr_efd(sd_event_source *s, int fd, uint32_t revents, void *userdata)
 {
-       uint64_t x;
-       read(evmgr->efd, &x, sizeof x);
+       struct evmgr *evmgr = userdata;
+       evmgr_on_efd_event(evmgr);
+       return 1;
 }
 
 /**
- * wakeup the event loop if needed by sending
- * an event.
+ * Gets a sd_event item for the current thread.
+ * @return a sd_event or NULL in case of error
  */
-void evmgr_wakeup(struct evmgr *evmgr)
+int evmgr_create(struct evmgr **result)
 {
-       uint64_t x;
+       int rc;
+       struct evmgr *evmgr;
 
-       if (evmgr->state & EVLOOP_STATE_WAIT) {
-               x = 1;
-               write(evmgr->efd, &x, sizeof x);
+       /* creates the evmgr on need */
+       evmgr = malloc(sizeof *evmgr);
+       if (!evmgr) {
+               ERROR("out of memory");
+               rc = -ENOMEM;
+               goto error;
+       }
+
+       /* creates the eventfd for waking up polls */
+       evmgr->efd = eventfd(0, EFD_CLOEXEC|EFD_SEMAPHORE);
+       if (evmgr->efd < 0) {
+               ERROR("can't make eventfd for events");
+               rc = -errno;
+               goto error1;
        }
+       /* create the systemd event loop */
+       evmgr->sdev = systemd_get_event_loop();
+       if (!evmgr->sdev) {
+               ERROR("can't make new event loop");
+               goto error2;
+       }
+       /* put the eventfd in the event loop */
+       rc = sd_event_add_io(evmgr->sdev, NULL, evmgr->efd, EPOLLIN, on_evmgr_efd, evmgr);
+       if (rc < 0) {
+               ERROR("can't register eventfd");
+               goto error2;
+       }
+
+       /* start the creation */
+       evmgr->state = 0;
+       evmgr->holder = 0;
+       *result = evmgr;
+       return 0;
+
+
+error2:
+       close(evmgr->efd);
+error1:
+       free(evmgr);
+error:
+       *result = 0;
+       return rc;
 }
 
+#endif
+#if WITH_FDEV_EPOLL
+
 /**
+ * Run the event loop is set.
  */
-void *evmgr_holder(struct evmgr *evmgr)
+void evmgr_run(struct evmgr *evmgr)
 {
-       return evmgr->holder;
+       int rc;
+
+       evmgr->state = EVLOOP_STATE_WAIT|EVLOOP_STATE_RUN;
+       rc = fdev_epoll_wait_and_dispatch(evmgr->fdev_epoll, -1);
+       evmgr->state = 0;
 }
 
-/**
- */
-int evmgr_release_if(struct evmgr *evmgr, void *holder)
+void evmgr_job_run(int signum, struct evmgr *evmgr)
 {
-       if (evmgr->holder != holder)
-               return 0;
-       evmgr->holder = 0;
-       return 1;
+       if (signum)
+               evmgr->state = 0;
+       else
+               evmgr_run(evmgr);
 }
 
-/**
- */
-int evmgr_try_hold(struct evmgr *evmgr, void *holder)
+int evmgr_can_run(struct evmgr *evmgr)
 {
-       if (!evmgr->holder)
-               evmgr->holder = holder;
-       return evmgr->holder == holder;
+       return !evmgr->state;
 }
 
-/******************************************************************************/
-/******************************************************************************/
-/******  SYSTEM D                                                        ******/
-/******************************************************************************/
-/******************************************************************************/
+struct fdev_epoll *evmgr_get_fdev_epoll(struct evmgr *evmgr)
+{
+       return evmgr->fdev_epoll;
+}
 
 /**
  * Internal callback for evmgr management.
@@ -158,11 +272,10 @@ int evmgr_try_hold(struct evmgr *evmgr, void *holder)
  * the waiting poll if any. Then it wakes up a thread
  * awaiting the evmgr using signal.
  */
-static int on_evmgr_efd(sd_event_source *s, int fd, uint32_t revents, void *userdata)
+static void on_evmgr_efd(void *closure, uint32_t event, struct fdev *fdev)
 {
-       struct evmgr *evmgr = userdata;
+       struct evmgr *evmgr = closure;
        evmgr_on_efd_event(evmgr);
-       return 1;
 }
 
 /**
@@ -189,19 +302,23 @@ int evmgr_create(struct evmgr **result)
                rc = -errno;
                goto error1;
        }
+
        /* create the systemd event loop */
-       evmgr->sdev = systemd_get_event_loop();
-       if (!evmgr->sdev) {
+       evmgr->fdev_epoll = fdev_epoll_create();
+       if (!evmgr->fdev_epoll) {
                ERROR("can't make new event loop");
                goto error2;
        }
        /* put the eventfd in the event loop */
-       rc = sd_event_add_io(evmgr->sdev, NULL, evmgr->efd, EPOLLIN, on_evmgr_efd, evmgr);
-       if (rc < 0) {
-               ERROR("can't register eventfd");
-               goto error2;
+       evmgr->fdev = fdev_epoll_add(evmgr->fdev_epoll, evmgr->efd);
+       if (evmgr->fdev == NULL) {
+               ERROR("can't add eventfd");
+               goto error3;
        }
 
+       fdev_set_callback(evmgr->fdev, on_evmgr_efd, evmgr);
+       fdev_set_events(evmgr->fdev, EPOLLIN);
+
        /* start the creation */
        evmgr->state = 0;
        evmgr->holder = 0;
@@ -209,6 +326,8 @@ int evmgr_create(struct evmgr **result)
        return 0;
 
 
+error3:
+       fdev_epoll_destroy(evmgr->fdev_epoll);
 error2:
        close(evmgr->efd);
 error1:
@@ -218,3 +337,4 @@ error:
        return rc;
 }
 
+#endif