"Fossies" - the Fresh Open Source Software Archive

Member "libev-4.33/event.c" (28 Aug 2019, 9950 Bytes) of package /linux/misc/libev-4.33.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "event.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * libevent compatibility layer
    3  *
    4  * Copyright (c) 2007,2008,2009,2010,2012 Marc Alexander Lehmann <libev@schmorp.de>
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without modifica-
    8  * tion, are permitted provided that the following conditions are met:
    9  *
   10  *   1.  Redistributions of source code must retain the above copyright notice,
   11  *       this list of conditions and the following disclaimer.
   12  *
   13  *   2.  Redistributions in binary form must reproduce the above copyright
   14  *       notice, this list of conditions and the following disclaimer in the
   15  *       documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
   18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
   19  * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO
   20  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
   21  * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
   25  * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   26  * OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * Alternatively, the contents of this file may be used under the terms of
   29  * the GNU General Public License ("GPL") version 2 or any later version,
   30  * in which case the provisions of the GPL are applicable instead of
   31  * the above. If you wish to allow the use of your version of this file
   32  * only under the terms of the GPL and not to allow others to use your
   33  * version of this file under the BSD license, indicate your decision
   34  * by deleting the provisions above and replace them with the notice
   35  * and other provisions required by the GPL. If you do not delete the
   36  * provisions above, a recipient may use your version of this file under
   37  * either the BSD or the GPL.
   38  */
   39 
   40 #include <stddef.h>
   41 #include <stdlib.h>
   42 #include <assert.h>
   43 
   44 #ifdef EV_EVENT_H
   45 # include EV_EVENT_H
   46 #else
   47 # include "event.h"
   48 #endif
   49 
   50 #if EV_MULTIPLICITY
   51 # define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base
   52 # define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base
   53 #else
   54 # define dLOOPev
   55 # define dLOOPbase
   56 #endif
   57 
   58 /* never accessed, will always be cast from/to ev_loop */
   59 struct event_base
   60 {
   61   int dummy;
   62 };
   63 
   64 static struct event_base *ev_x_cur;
   65 
   66 static ev_tstamp
   67 ev_tv_get (struct timeval *tv)
   68 {
   69   if (tv)
   70     {
   71       ev_tstamp after = tv->tv_sec + tv->tv_usec * 1e-6;
   72       return after ? after : 1e-6;
   73     }
   74   else
   75     return -1.;
   76 }
   77 
   78 #define EVENT_STRINGIFY(s) # s
   79 #define EVENT_VERSION(a,b) EVENT_STRINGIFY (a) "." EVENT_STRINGIFY (b)
   80 
   81 const char *
   82 event_get_version (void)
   83 {
   84   /* returns ABI, not API or library, version */
   85   return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR);
   86 }
   87 
   88 const char *
   89 event_get_method (void)
   90 {
   91   return "libev";
   92 }
   93 
   94 void *event_init (void)
   95 {
   96 #if EV_MULTIPLICITY
   97   if (ev_x_cur)
   98     ev_x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO);
   99   else
  100     ev_x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO);
  101 #else
  102   assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY", !ev_x_cur));
  103 
  104   ev_x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO);
  105 #endif
  106 
  107   return ev_x_cur;
  108 }
  109 
  110 const char *
  111 event_base_get_method (const struct event_base *base)
  112 {
  113   return "libev";
  114 }
  115 
  116 struct event_base *
  117 event_base_new (void)
  118 {
  119 #if EV_MULTIPLICITY
  120   return (struct event_base *)ev_loop_new (EVFLAG_AUTO);
  121 #else
  122   assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY"));
  123   return NULL;
  124 #endif
  125 }
  126 
  127 void event_base_free (struct event_base *base)
  128 {
  129   dLOOPbase;
  130 
  131 #if EV_MULTIPLICITY
  132   if (!ev_is_default_loop (loop))
  133     ev_loop_destroy (loop);
  134 #endif
  135 }
  136 
  137 int event_dispatch (void)
  138 {
  139   return event_base_dispatch (ev_x_cur);
  140 }
  141 
  142 #ifdef EV_STANDALONE
  143 void event_set_log_callback (event_log_cb cb)
  144 {
  145   /* nop */
  146 }
  147 #endif
  148 
  149 int event_loop (int flags)
  150 {
  151   return event_base_loop (ev_x_cur, flags);
  152 }
  153 
  154 int event_loopexit (struct timeval *tv)
  155 {
  156   return event_base_loopexit (ev_x_cur, tv);
  157 }
  158 
  159 event_callback_fn event_get_callback
  160 (const struct event *ev)
  161 {
  162   return ev->ev_callback;
  163 }
  164 
  165 static void
  166 ev_x_cb (struct event *ev, int revents)
  167 {
  168   revents &= EV_READ | EV_WRITE | EV_TIMER | EV_SIGNAL;
  169 
  170   ev->ev_res = revents;
  171   ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg);
  172 }
  173 
  174 static void
  175 ev_x_cb_sig (EV_P_ struct ev_signal *w, int revents)
  176 {
  177   struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig));
  178 
  179   if (revents & EV_ERROR)
  180     event_del (ev);
  181 
  182   ev_x_cb (ev, revents);
  183 }
  184 
  185 static void
  186 ev_x_cb_io (EV_P_ struct ev_io *w, int revents)
  187 {
  188   struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io));
  189 
  190   if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST))
  191     event_del (ev);
  192 
  193   ev_x_cb (ev, revents);
  194 }
  195 
  196 static void
  197 ev_x_cb_to (EV_P_ struct ev_timer *w, int revents)
  198 {
  199   struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to));
  200 
  201   event_del (ev);
  202 
  203   ev_x_cb (ev, revents);
  204 }
  205 
  206 void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg)
  207 {
  208   if (events & EV_SIGNAL)
  209     ev_init (&ev->iosig.sig, ev_x_cb_sig);
  210   else
  211     ev_init (&ev->iosig.io, ev_x_cb_io);
  212 
  213   ev_init (&ev->to, ev_x_cb_to);
  214 
  215   ev->ev_base     = ev_x_cur; /* not threadsafe, but it's how libevent works */
  216   ev->ev_fd       = fd;
  217   ev->ev_events   = events;
  218   ev->ev_pri      = 0;
  219   ev->ev_callback = cb;
  220   ev->ev_arg      = arg;
  221   ev->ev_res      = 0;
  222   ev->ev_flags    = EVLIST_INIT;
  223 }
  224 
  225 int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
  226 {
  227   return event_base_once (ev_x_cur, fd, events, cb, arg, tv);
  228 }
  229 
  230 int event_add (struct event *ev, struct timeval *tv)
  231 {
  232   dLOOPev;
  233 
  234   if (ev->ev_events & EV_SIGNAL)
  235     {
  236       if (!ev_is_active (&ev->iosig.sig))
  237         {
  238           ev_signal_set (&ev->iosig.sig, ev->ev_fd);
  239           ev_signal_start (EV_A_ &ev->iosig.sig);
  240 
  241           ev->ev_flags |= EVLIST_SIGNAL;
  242         }
  243     }
  244   else if (ev->ev_events & (EV_READ | EV_WRITE))
  245     {
  246       if (!ev_is_active (&ev->iosig.io))
  247         {
  248           ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE));
  249           ev_io_start (EV_A_ &ev->iosig.io);
  250 
  251           ev->ev_flags |= EVLIST_INSERTED;
  252         }
  253     }
  254 
  255   if (tv)
  256     {
  257       ev->to.repeat = ev_tv_get (tv);
  258       ev_timer_again (EV_A_ &ev->to);
  259       ev->ev_flags |= EVLIST_TIMEOUT;
  260     }
  261   else
  262     {
  263       ev_timer_stop (EV_A_ &ev->to);
  264       ev->ev_flags &= ~EVLIST_TIMEOUT;
  265     }
  266 
  267   ev->ev_flags |= EVLIST_ACTIVE;
  268 
  269   return 0;
  270 }
  271 
  272 int event_del (struct event *ev)
  273 {
  274   dLOOPev;
  275 
  276   if (ev->ev_events & EV_SIGNAL)
  277     ev_signal_stop (EV_A_ &ev->iosig.sig);
  278   else if (ev->ev_events & (EV_READ | EV_WRITE))
  279     ev_io_stop (EV_A_ &ev->iosig.io);
  280 
  281   if (ev_is_active (&ev->to))
  282     ev_timer_stop (EV_A_ &ev->to);
  283 
  284   ev->ev_flags = EVLIST_INIT;
  285 
  286   return 0;
  287 }
  288 
  289 void event_active (struct event *ev, int res, short ncalls)
  290 {
  291   dLOOPev;
  292 
  293   if (res & EV_TIMEOUT)
  294     ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT);
  295 
  296   if (res & EV_SIGNAL)
  297     ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL);
  298 
  299   if (res & (EV_READ | EV_WRITE))
  300     ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE));
  301 }
  302 
  303 int event_pending (struct event *ev, short events, struct timeval *tv)
  304 {
  305   short revents = 0;
  306   dLOOPev;
  307 
  308   if (ev->ev_events & EV_SIGNAL)
  309     {
  310       /* sig */
  311       if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig))
  312         revents |= EV_SIGNAL;
  313     }
  314   else if (ev->ev_events & (EV_READ | EV_WRITE))
  315     {
  316       /* io */
  317       if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io))
  318         revents |= ev->ev_events & (EV_READ | EV_WRITE);
  319     }
  320 
  321   if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to))
  322     {
  323       revents |= EV_TIMEOUT;
  324 
  325       if (tv)
  326         {
  327           ev_tstamp at = ev_now (EV_A);
  328 
  329           tv->tv_sec  = (long)at;
  330           tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6);
  331         }
  332     }
  333 
  334   return events & revents;
  335 }
  336 
  337 int event_priority_init (int npri)
  338 {
  339   return event_base_priority_init (ev_x_cur, npri);
  340 }
  341 
  342 int event_priority_set (struct event *ev, int pri)
  343 {
  344   ev->ev_pri = pri;
  345 
  346   return 0;
  347 }
  348 
  349 int event_base_set (struct event_base *base, struct event *ev)
  350 {
  351   ev->ev_base = base;
  352 
  353   return 0;
  354 }
  355 
  356 int event_base_loop (struct event_base *base, int flags)
  357 {
  358   dLOOPbase;
  359 
  360   return !ev_run (EV_A_ flags);
  361 }
  362 
  363 int event_base_dispatch (struct event_base *base)
  364 {
  365   return event_base_loop (base, 0);
  366 }
  367 
  368 static void
  369 ev_x_loopexit_cb (int revents, void *base)
  370 {
  371   dLOOPbase;
  372 
  373   ev_break (EV_A_ EVBREAK_ONE);
  374 }
  375 
  376 int event_base_loopexit (struct event_base *base, struct timeval *tv)
  377 {
  378   ev_tstamp after = ev_tv_get (tv);
  379   dLOOPbase;
  380 
  381   ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., ev_x_loopexit_cb, (void *)base);
  382 
  383   return 0;
  384 }
  385 
  386 struct ev_x_once
  387 {
  388   int fd;
  389   void (*cb)(int, short, void *);
  390   void *arg;
  391 };
  392 
  393 static void
  394 ev_x_once_cb (int revents, void *arg)
  395 {
  396   struct ev_x_once *once = (struct ev_x_once *)arg;
  397 
  398   once->cb (once->fd, (short)revents, once->arg);
  399   free (once);
  400 }
  401 
  402 int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
  403 {
  404   struct ev_x_once *once = (struct ev_x_once *)malloc (sizeof (struct ev_x_once));
  405   dLOOPbase;
  406 
  407   if (!once)
  408     return -1;
  409 
  410   once->fd  = fd;
  411   once->cb  = cb;
  412   once->arg = arg;
  413 
  414   ev_once (EV_A_ fd, events & (EV_READ | EV_WRITE), ev_tv_get (tv), ev_x_once_cb, (void *)once);
  415 
  416   return 0;
  417 }
  418 
  419 int event_base_priority_init (struct event_base *base, int npri)
  420 {
  421   /*dLOOPbase;*/
  422 
  423   return 0;
  424 }
  425