/src/unix/ev/event.c

http://github.com/joyent/libuv · C · 402 lines · 278 code · 80 blank · 44 comment · 32 complexity · cb275ba0534c032bb89b4500bc45c648 MD5 · raw file

  1. /*
  2. * libevent compatibility layer
  3. *
  4. * Copyright (c) 2007,2008,2009,2010 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. #include <stddef.h>
  40. #include <stdlib.h>
  41. #include <assert.h>
  42. #ifdef EV_EVENT_H
  43. # include EV_EVENT_H
  44. #else
  45. # include "event.h"
  46. #endif
  47. #if EV_MULTIPLICITY
  48. # define dLOOPev struct ev_loop *loop = (struct ev_loop *)ev->ev_base
  49. # define dLOOPbase struct ev_loop *loop = (struct ev_loop *)base
  50. #else
  51. # define dLOOPev
  52. # define dLOOPbase
  53. #endif
  54. /* never accessed, will always be cast from/to ev_loop */
  55. struct event_base
  56. {
  57. int dummy;
  58. };
  59. static struct event_base *ev_x_cur;
  60. static ev_tstamp
  61. ev_tv_get (struct timeval *tv)
  62. {
  63. if (tv)
  64. {
  65. ev_tstamp after = tv->tv_sec + tv->tv_usec * 1e-6;
  66. return after ? after : 1e-6;
  67. }
  68. else
  69. return -1.;
  70. }
  71. #define EVENT_STRINGIFY(s) # s
  72. #define EVENT_VERSION(a,b) EVENT_STRINGIFY (a) "." EVENT_STRINGIFY (b)
  73. const char *event_get_version (void)
  74. {
  75. /* returns ABI, not API or library, version */
  76. return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR);
  77. }
  78. const char *event_get_method (void)
  79. {
  80. return "libev";
  81. }
  82. void *event_init (void)
  83. {
  84. #if EV_MULTIPLICITY
  85. if (ev_x_cur)
  86. ev_x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO);
  87. else
  88. ev_x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO);
  89. #else
  90. assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY", !ev_x_cur));
  91. ev_x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO);
  92. #endif
  93. return ev_x_cur;
  94. }
  95. void event_base_free (struct event_base *base)
  96. {
  97. dLOOPbase;
  98. #if EV_MULTIPLICITY
  99. if (!ev_is_default_loop (loop))
  100. ev_loop_destroy (loop);
  101. #endif
  102. }
  103. int event_dispatch (void)
  104. {
  105. return event_base_dispatch (ev_x_cur);
  106. }
  107. #ifdef EV_STANDALONE
  108. void event_set_log_callback (event_log_cb cb)
  109. {
  110. /* nop */
  111. }
  112. #endif
  113. int event_loop (int flags)
  114. {
  115. return event_base_loop (ev_x_cur, flags);
  116. }
  117. int event_loopexit (struct timeval *tv)
  118. {
  119. return event_base_loopexit (ev_x_cur, tv);
  120. }
  121. static void
  122. ev_x_cb (struct event *ev, int revents)
  123. {
  124. revents &= EV_READ | EV_WRITE | EV_TIMER | EV_SIGNAL;
  125. ev->ev_res = revents;
  126. ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg);
  127. }
  128. static void
  129. ev_x_cb_sig (EV_P_ struct ev_signal *w, int revents)
  130. {
  131. struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig));
  132. if (revents & EV_ERROR)
  133. event_del (ev);
  134. ev_x_cb (ev, revents);
  135. }
  136. static void
  137. ev_x_cb_io (EV_P_ struct ev_io *w, int revents)
  138. {
  139. struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io));
  140. if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST))
  141. event_del (ev);
  142. ev_x_cb (ev, revents);
  143. }
  144. static void
  145. ev_x_cb_to (EV_P_ struct ev_timer *w, int revents)
  146. {
  147. struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to));
  148. event_del (ev);
  149. ev_x_cb (ev, revents);
  150. }
  151. void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg)
  152. {
  153. if (events & EV_SIGNAL)
  154. ev_init (&ev->iosig.sig, ev_x_cb_sig);
  155. else
  156. ev_init (&ev->iosig.io, ev_x_cb_io);
  157. ev_init (&ev->to, ev_x_cb_to);
  158. ev->ev_base = ev_x_cur; /* not threadsafe, but it's how libevent works */
  159. ev->ev_fd = fd;
  160. ev->ev_events = events;
  161. ev->ev_pri = 0;
  162. ev->ev_callback = cb;
  163. ev->ev_arg = arg;
  164. ev->ev_res = 0;
  165. ev->ev_flags = EVLIST_INIT;
  166. }
  167. int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
  168. {
  169. return event_base_once (ev_x_cur, fd, events, cb, arg, tv);
  170. }
  171. int event_add (struct event *ev, struct timeval *tv)
  172. {
  173. dLOOPev;
  174. if (ev->ev_events & EV_SIGNAL)
  175. {
  176. if (!ev_is_active (&ev->iosig.sig))
  177. {
  178. ev_signal_set (&ev->iosig.sig, ev->ev_fd);
  179. ev_signal_start (EV_A_ &ev->iosig.sig);
  180. ev->ev_flags |= EVLIST_SIGNAL;
  181. }
  182. }
  183. else if (ev->ev_events & (EV_READ | EV_WRITE))
  184. {
  185. if (!ev_is_active (&ev->iosig.io))
  186. {
  187. ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE));
  188. ev_io_start (EV_A_ &ev->iosig.io);
  189. ev->ev_flags |= EVLIST_INSERTED;
  190. }
  191. }
  192. if (tv)
  193. {
  194. ev->to.repeat = ev_tv_get (tv);
  195. ev_timer_again (EV_A_ &ev->to);
  196. ev->ev_flags |= EVLIST_TIMEOUT;
  197. }
  198. else
  199. {
  200. ev_timer_stop (EV_A_ &ev->to);
  201. ev->ev_flags &= ~EVLIST_TIMEOUT;
  202. }
  203. ev->ev_flags |= EVLIST_ACTIVE;
  204. return 0;
  205. }
  206. int event_del (struct event *ev)
  207. {
  208. dLOOPev;
  209. if (ev->ev_events & EV_SIGNAL)
  210. ev_signal_stop (EV_A_ &ev->iosig.sig);
  211. else if (ev->ev_events & (EV_READ | EV_WRITE))
  212. ev_io_stop (EV_A_ &ev->iosig.io);
  213. if (ev_is_active (&ev->to))
  214. ev_timer_stop (EV_A_ &ev->to);
  215. ev->ev_flags = EVLIST_INIT;
  216. return 0;
  217. }
  218. void event_active (struct event *ev, int res, short ncalls)
  219. {
  220. dLOOPev;
  221. if (res & EV_TIMEOUT)
  222. ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT);
  223. if (res & EV_SIGNAL)
  224. ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL);
  225. if (res & (EV_READ | EV_WRITE))
  226. ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE));
  227. }
  228. int event_pending (struct event *ev, short events, struct timeval *tv)
  229. {
  230. short revents = 0;
  231. dLOOPev;
  232. if (ev->ev_events & EV_SIGNAL)
  233. {
  234. /* sig */
  235. if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig))
  236. revents |= EV_SIGNAL;
  237. }
  238. else if (ev->ev_events & (EV_READ | EV_WRITE))
  239. {
  240. /* io */
  241. if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io))
  242. revents |= ev->ev_events & (EV_READ | EV_WRITE);
  243. }
  244. if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to))
  245. {
  246. revents |= EV_TIMEOUT;
  247. if (tv)
  248. {
  249. ev_tstamp at = ev_now (EV_A);
  250. tv->tv_sec = (long)at;
  251. tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6);
  252. }
  253. }
  254. return events & revents;
  255. }
  256. int event_priority_init (int npri)
  257. {
  258. return event_base_priority_init (ev_x_cur, npri);
  259. }
  260. int event_priority_set (struct event *ev, int pri)
  261. {
  262. ev->ev_pri = pri;
  263. return 0;
  264. }
  265. int event_base_set (struct event_base *base, struct event *ev)
  266. {
  267. ev->ev_base = base;
  268. return 0;
  269. }
  270. int event_base_loop (struct event_base *base, int flags)
  271. {
  272. dLOOPbase;
  273. ev_run (EV_A_ flags);
  274. return 0;
  275. }
  276. int event_base_dispatch (struct event_base *base)
  277. {
  278. return event_base_loop (base, 0);
  279. }
  280. static void
  281. ev_x_loopexit_cb (int revents, void *base)
  282. {
  283. dLOOPbase;
  284. ev_break (EV_A_ EVBREAK_ONE);
  285. }
  286. int event_base_loopexit (struct event_base *base, struct timeval *tv)
  287. {
  288. ev_tstamp after = ev_tv_get (tv);
  289. dLOOPbase;
  290. ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., ev_x_loopexit_cb, (void *)base);
  291. return 0;
  292. }
  293. struct ev_x_once
  294. {
  295. int fd;
  296. void (*cb)(int, short, void *);
  297. void *arg;
  298. };
  299. static void
  300. ev_x_once_cb (int revents, void *arg)
  301. {
  302. struct ev_x_once *once = (struct ev_x_once *)arg;
  303. once->cb (once->fd, (short)revents, once->arg);
  304. free (once);
  305. }
  306. int event_base_once (struct event_base *base, int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
  307. {
  308. struct ev_x_once *once = (struct ev_x_once *)malloc (sizeof (struct ev_x_once));
  309. dLOOPbase;
  310. if (!once)
  311. return -1;
  312. once->fd = fd;
  313. once->cb = cb;
  314. once->arg = arg;
  315. ev_once (EV_A_ fd, events & (EV_READ | EV_WRITE), ev_tv_get (tv), ev_x_once_cb, (void *)once);
  316. return 0;
  317. }
  318. int event_base_priority_init (struct event_base *base, int npri)
  319. {
  320. /*dLOOPbase;*/
  321. return 0;
  322. }