Mirror of :pserver:anonymous@cvs.schmorp.de/schmorpforge libev http://software.schmorp.de/pkg/libev.html
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

401 lines
9.3 KiB

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