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.

403 lines
9.1 KiB

14 years ago
14 years ago
  1. /*
  2. * libevent compatibility layer
  3. *
  4. * Copyright (c) 2007,2008 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. #ifndef WIN32
  43. # include <sys/time.h>
  44. #endif
  45. #ifdef EV_EVENT_H
  46. # include EV_EVENT_H
  47. #else
  48. # include "event.h"
  49. #endif
  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. /* never accessed, will always be cast from/to ev_loop */
  58. struct event_base
  59. {
  60. int dummy;
  61. };
  62. static struct event_base *x_cur;
  63. static void
  64. tv_set (struct timeval *tv, ev_tstamp at)
  65. {
  66. tv->tv_sec = (long)at;
  67. tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6);
  68. }
  69. static ev_tstamp
  70. tv_get (struct timeval *tv)
  71. {
  72. if (tv)
  73. return tv->tv_sec + tv->tv_usec * 1e-6;
  74. else
  75. return -1.;
  76. }
  77. #define EVENT_VERSION(a,b) # a "." # b
  78. const char *event_get_version (void)
  79. {
  80. return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR);
  81. }
  82. const char *event_get_method (void)
  83. {
  84. return "libev";
  85. }
  86. void *event_init (void)
  87. {
  88. #if EV_MULTIPLICITY
  89. if (x_cur)
  90. x_cur = (struct event_base *)ev_loop_new (EVFLAG_AUTO);
  91. else
  92. x_cur = (struct event_base *)ev_default_loop (EVFLAG_AUTO);
  93. #else
  94. assert (("multiple event bases not supported when not compiled with EV_MULTIPLICITY", !x_cur));
  95. x_cur = (struct event_base *)(long)ev_default_loop (EVFLAG_AUTO);
  96. #endif
  97. return x_cur;
  98. }
  99. void event_base_free (struct event_base *base)
  100. {
  101. dLOOPbase;
  102. #if EV_MULTIPLICITY
  103. if (ev_default_loop (EVFLAG_AUTO) != loop)
  104. ev_loop_destroy (loop);
  105. #endif
  106. }
  107. int event_dispatch (void)
  108. {
  109. return event_base_dispatch (x_cur);
  110. }
  111. #ifdef EV_STANDALONE
  112. void event_set_log_callback (event_log_cb cb)
  113. {
  114. /* nop */
  115. }
  116. #endif
  117. int event_loop (int flags)
  118. {
  119. return event_base_loop (x_cur, flags);
  120. }
  121. int event_loopexit (struct timeval *tv)
  122. {
  123. return event_base_loopexit (x_cur, tv);
  124. }
  125. static void
  126. x_cb (struct event *ev, int revents)
  127. {
  128. revents &= EV_READ | EV_WRITE | EV_TIMEOUT | EV_SIGNAL;
  129. ev->ev_res = revents;
  130. ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg);
  131. }
  132. static void
  133. x_cb_sig (EV_P_ struct ev_signal *w, int revents)
  134. {
  135. struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.sig));
  136. if (revents & EV_ERROR)
  137. event_del (ev);
  138. x_cb (ev, revents);
  139. }
  140. static void
  141. x_cb_io (EV_P_ struct ev_io *w, int revents)
  142. {
  143. struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, iosig.io));
  144. if ((revents & EV_ERROR) || !(ev->ev_events & EV_PERSIST))
  145. event_del (ev);
  146. x_cb (ev, revents);
  147. }
  148. static void
  149. x_cb_to (EV_P_ struct ev_timer *w, int revents)
  150. {
  151. struct event *ev = (struct event *)(((char *)w) - offsetof (struct event, to));
  152. event_del (ev);
  153. x_cb (ev, revents);
  154. }
  155. void event_set (struct event *ev, int fd, short events, void (*cb)(int, short, void *), void *arg)
  156. {
  157. if (events & EV_SIGNAL)
  158. ev_init (&ev->iosig.sig, x_cb_sig);
  159. else
  160. ev_init (&ev->iosig.io, x_cb_io);
  161. ev_init (&ev->to, x_cb_to);
  162. ev->ev_base = x_cur; /* not threadsafe, but its like libevent works */
  163. ev->ev_fd = fd;
  164. ev->ev_events = events;
  165. ev->ev_pri = 0;
  166. ev->ev_callback = cb;
  167. ev->ev_arg = arg;
  168. ev->ev_res = 0;
  169. ev->ev_flags = EVLIST_INIT;
  170. }
  171. int event_once (int fd, short events, void (*cb)(int, short, void *), void *arg, struct timeval *tv)
  172. {
  173. return event_base_once (x_cur, fd, events, cb, arg, tv);
  174. }
  175. int event_add (struct event *ev, struct timeval *tv)
  176. {
  177. dLOOPev;
  178. if (ev->ev_events & EV_SIGNAL)
  179. {
  180. if (!ev_is_active (&ev->iosig.sig))
  181. {
  182. ev_signal_set (&ev->iosig.sig, ev->ev_fd);
  183. ev_signal_start (EV_A_ &ev->iosig.sig);
  184. ev->ev_flags |= EVLIST_SIGNAL;
  185. }
  186. }
  187. else if (ev->ev_events & (EV_READ | EV_WRITE))
  188. {
  189. if (!ev_is_active (&ev->iosig.io))
  190. {
  191. ev_io_set (&ev->iosig.io, ev->ev_fd, ev->ev_events & (EV_READ | EV_WRITE));
  192. ev_io_start (EV_A_ &ev->iosig.io);
  193. ev->ev_flags |= EVLIST_INSERTED;
  194. }
  195. }
  196. if (tv)
  197. {
  198. ev->to.repeat = tv_get (tv);
  199. ev_timer_again (EV_A_ &ev->to);
  200. ev->ev_flags |= EVLIST_TIMEOUT;
  201. }
  202. else
  203. {
  204. ev_timer_stop (EV_A_ &ev->to);
  205. ev->ev_flags &= ~EVLIST_TIMEOUT;
  206. }
  207. ev->ev_flags |= EVLIST_ACTIVE;
  208. return 0;
  209. }
  210. int event_del (struct event *ev)
  211. {
  212. dLOOPev;
  213. if (ev->ev_events & EV_SIGNAL)
  214. ev_signal_stop (EV_A_ &ev->iosig.sig);
  215. else if (ev->ev_events & (EV_READ | EV_WRITE))
  216. ev_io_stop (EV_A_ &ev->iosig.io);
  217. if (ev_is_active (&ev->to))
  218. ev_timer_stop (EV_A_ &ev->to);
  219. ev->ev_flags = EVLIST_INIT;
  220. return 0;
  221. }
  222. void event_active (struct event *ev, int res, short ncalls)
  223. {
  224. dLOOPev;
  225. if (res & EV_TIMEOUT)
  226. ev_feed_event (EV_A_ &ev->to, res & EV_TIMEOUT);
  227. if (res & EV_SIGNAL)
  228. ev_feed_event (EV_A_ &ev->iosig.sig, res & EV_SIGNAL);
  229. if (res & (EV_READ | EV_WRITE))
  230. ev_feed_event (EV_A_ &ev->iosig.io, res & (EV_READ | EV_WRITE));
  231. }
  232. int event_pending (struct event *ev, short events, struct timeval *tv)
  233. {
  234. short revents = 0;
  235. dLOOPev;
  236. if (ev->ev_events & EV_SIGNAL)
  237. {
  238. /* sig */
  239. if (ev_is_active (&ev->iosig.sig) || ev_is_pending (&ev->iosig.sig))
  240. revents |= EV_SIGNAL;
  241. }
  242. else if (ev->ev_events & (EV_READ | EV_WRITE))
  243. {
  244. /* io */
  245. if (ev_is_active (&ev->iosig.io) || ev_is_pending (&ev->iosig.io))
  246. revents |= ev->ev_events & (EV_READ | EV_WRITE);
  247. }
  248. if (ev->ev_events & EV_TIMEOUT || ev_is_active (&ev->to) || ev_is_pending (&ev->to))
  249. {
  250. revents |= EV_TIMEOUT;
  251. if (tv)
  252. tv_set (tv, ev_now (EV_A)); /* not sure if this is right :) */
  253. }
  254. return events & revents;
  255. }
  256. int event_priority_init (int npri)
  257. {
  258. return event_base_priority_init (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_loop (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. x_loopexit_cb (int revents, void *base)
  282. {
  283. dLOOPbase;
  284. ev_unloop (EV_A_ EVUNLOOP_ONE);
  285. }
  286. int event_base_loopexit (struct event_base *base, struct timeval *tv)
  287. {
  288. ev_tstamp after = tv_get (tv);
  289. dLOOPbase;
  290. ev_once (EV_A_ -1, 0, after >= 0. ? after : 0., x_loopexit_cb, (void *)base);
  291. return 0;
  292. }
  293. struct x_once
  294. {
  295. int fd;
  296. void (*cb)(int, short, void *);
  297. void *arg;
  298. };
  299. static void
  300. x_once_cb (int revents, void *arg)
  301. {
  302. struct x_once *once = (struct 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 x_once *once = (struct x_once *)malloc (sizeof (struct 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), tv_get (tv), 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. }