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.

816 lines
20 KiB

11 years ago
  1. /*
  2. * libev simple C++ wrapper classes
  3. *
  4. * Copyright (c) 2007,2008,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. #ifndef EVPP_H__
  40. #define EVPP_H__
  41. #ifdef EV_H
  42. # include EV_H
  43. #else
  44. # include "ev.h"
  45. #endif
  46. #ifndef EV_USE_STDEXCEPT
  47. # define EV_USE_STDEXCEPT 1
  48. #endif
  49. #if EV_USE_STDEXCEPT
  50. # include <stdexcept>
  51. #endif
  52. namespace ev {
  53. typedef ev_tstamp tstamp;
  54. enum {
  55. UNDEF = EV_UNDEF,
  56. NONE = EV_NONE,
  57. READ = EV_READ,
  58. WRITE = EV_WRITE,
  59. #if EV_COMPAT3
  60. TIMEOUT = EV_TIMEOUT,
  61. #endif
  62. TIMER = EV_TIMER,
  63. PERIODIC = EV_PERIODIC,
  64. SIGNAL = EV_SIGNAL,
  65. CHILD = EV_CHILD,
  66. STAT = EV_STAT,
  67. IDLE = EV_IDLE,
  68. CHECK = EV_CHECK,
  69. PREPARE = EV_PREPARE,
  70. FORK = EV_FORK,
  71. ASYNC = EV_ASYNC,
  72. EMBED = EV_EMBED,
  73. # undef ERROR // some systems stupidly #define ERROR
  74. ERROR = EV_ERROR
  75. };
  76. enum
  77. {
  78. AUTO = EVFLAG_AUTO,
  79. NOENV = EVFLAG_NOENV,
  80. FORKCHECK = EVFLAG_FORKCHECK,
  81. SELECT = EVBACKEND_SELECT,
  82. POLL = EVBACKEND_POLL,
  83. EPOLL = EVBACKEND_EPOLL,
  84. KQUEUE = EVBACKEND_KQUEUE,
  85. DEVPOLL = EVBACKEND_DEVPOLL,
  86. PORT = EVBACKEND_PORT
  87. };
  88. enum
  89. {
  90. #if EV_COMPAT3
  91. NONBLOCK = EVLOOP_NONBLOCK,
  92. ONESHOT = EVLOOP_ONESHOT,
  93. #endif
  94. NOWAIT = EVRUN_NOWAIT,
  95. ONCE = EVRUN_ONCE
  96. };
  97. enum how_t
  98. {
  99. ONE = EVBREAK_ONE,
  100. ALL = EVBREAK_ALL
  101. };
  102. struct bad_loop
  103. #if EV_USE_STDEXCEPT
  104. : std::runtime_error
  105. #endif
  106. {
  107. #if EV_USE_STDEXCEPT
  108. bad_loop ()
  109. : std::runtime_error ("libev event loop cannot be initialized, bad value of LIBEV_FLAGS?")
  110. {
  111. }
  112. #endif
  113. };
  114. #ifdef EV_AX
  115. # undef EV_AX
  116. #endif
  117. #ifdef EV_AX_
  118. # undef EV_AX_
  119. #endif
  120. #if EV_MULTIPLICITY
  121. # define EV_AX raw_loop
  122. # define EV_AX_ raw_loop,
  123. #else
  124. # define EV_AX
  125. # define EV_AX_
  126. #endif
  127. struct loop_ref
  128. {
  129. loop_ref (EV_P) throw ()
  130. #if EV_MULTIPLICITY
  131. : EV_AX (EV_A)
  132. #endif
  133. {
  134. }
  135. bool operator == (const loop_ref &other) const throw ()
  136. {
  137. #if EV_MULTIPLICITY
  138. return EV_AX == other.EV_AX;
  139. #else
  140. return true;
  141. #endif
  142. }
  143. bool operator != (const loop_ref &other) const throw ()
  144. {
  145. #if EV_MULTIPLICITY
  146. return ! (*this == other);
  147. #else
  148. return false;
  149. #endif
  150. }
  151. #if EV_MULTIPLICITY
  152. bool operator == (const EV_P) const throw ()
  153. {
  154. return this->EV_AX == EV_A;
  155. }
  156. bool operator != (const EV_P) const throw ()
  157. {
  158. return (*this == EV_A);
  159. }
  160. operator struct ev_loop * () const throw ()
  161. {
  162. return EV_AX;
  163. }
  164. operator const struct ev_loop * () const throw ()
  165. {
  166. return EV_AX;
  167. }
  168. bool is_default () const throw ()
  169. {
  170. return EV_AX == ev_default_loop (0);
  171. }
  172. #endif
  173. #if EV_COMPAT3
  174. void loop (int flags = 0)
  175. {
  176. ev_run (EV_AX_ flags);
  177. }
  178. void unloop (how_t how = ONE) throw ()
  179. {
  180. ev_break (EV_AX_ how);
  181. }
  182. #endif
  183. void run (int flags = 0)
  184. {
  185. ev_run (EV_AX_ flags);
  186. }
  187. void break_loop (how_t how = ONE) throw ()
  188. {
  189. ev_break (EV_AX_ how);
  190. }
  191. void post_fork () throw ()
  192. {
  193. ev_loop_fork (EV_AX);
  194. }
  195. unsigned int backend () const throw ()
  196. {
  197. return ev_backend (EV_AX);
  198. }
  199. tstamp now () const throw ()
  200. {
  201. return ev_now (EV_AX);
  202. }
  203. void ref () throw ()
  204. {
  205. ev_ref (EV_AX);
  206. }
  207. void unref () throw ()
  208. {
  209. ev_unref (EV_AX);
  210. }
  211. #if EV_FEATURE_API
  212. unsigned int iteration () const throw ()
  213. {
  214. return ev_iteration (EV_AX);
  215. }
  216. unsigned int depth () const throw ()
  217. {
  218. return ev_depth (EV_AX);
  219. }
  220. void set_io_collect_interval (tstamp interval) throw ()
  221. {
  222. ev_set_io_collect_interval (EV_AX_ interval);
  223. }
  224. void set_timeout_collect_interval (tstamp interval) throw ()
  225. {
  226. ev_set_timeout_collect_interval (EV_AX_ interval);
  227. }
  228. #endif
  229. // function callback
  230. void once (int fd, int events, tstamp timeout, void (*cb)(int, void *), void *arg = 0) throw ()
  231. {
  232. ev_once (EV_AX_ fd, events, timeout, cb, arg);
  233. }
  234. // method callback
  235. template<class K, void (K::*method)(int)>
  236. void once (int fd, int events, tstamp timeout, K *object) throw ()
  237. {
  238. once (fd, events, timeout, method_thunk<K, method>, object);
  239. }
  240. // default method == operator ()
  241. template<class K>
  242. void once (int fd, int events, tstamp timeout, K *object) throw ()
  243. {
  244. once (fd, events, timeout, method_thunk<K, &K::operator ()>, object);
  245. }
  246. template<class K, void (K::*method)(int)>
  247. static void method_thunk (int revents, void *arg)
  248. {
  249. (static_cast<K *>(arg)->*method)
  250. (revents);
  251. }
  252. // no-argument method callback
  253. template<class K, void (K::*method)()>
  254. void once (int fd, int events, tstamp timeout, K *object) throw ()
  255. {
  256. once (fd, events, timeout, method_noargs_thunk<K, method>, object);
  257. }
  258. template<class K, void (K::*method)()>
  259. static void method_noargs_thunk (int revents, void *arg)
  260. {
  261. (static_cast<K *>(arg)->*method)
  262. ();
  263. }
  264. // simpler function callback
  265. template<void (*cb)(int)>
  266. void once (int fd, int events, tstamp timeout) throw ()
  267. {
  268. once (fd, events, timeout, simpler_func_thunk<cb>);
  269. }
  270. template<void (*cb)(int)>
  271. static void simpler_func_thunk (int revents, void *arg)
  272. {
  273. (*cb)
  274. (revents);
  275. }
  276. // simplest function callback
  277. template<void (*cb)()>
  278. void once (int fd, int events, tstamp timeout) throw ()
  279. {
  280. once (fd, events, timeout, simplest_func_thunk<cb>);
  281. }
  282. template<void (*cb)()>
  283. static void simplest_func_thunk (int revents, void *arg)
  284. {
  285. (*cb)
  286. ();
  287. }
  288. void feed_fd_event (int fd, int revents) throw ()
  289. {
  290. ev_feed_fd_event (EV_AX_ fd, revents);
  291. }
  292. void feed_signal_event (int signum) throw ()
  293. {
  294. ev_feed_signal_event (EV_AX_ signum);
  295. }
  296. #if EV_MULTIPLICITY
  297. struct ev_loop* EV_AX;
  298. #endif
  299. };
  300. #if EV_MULTIPLICITY
  301. struct dynamic_loop : loop_ref
  302. {
  303. dynamic_loop (unsigned int flags = AUTO) throw (bad_loop)
  304. : loop_ref (ev_loop_new (flags))
  305. {
  306. if (!EV_AX)
  307. throw bad_loop ();
  308. }
  309. ~dynamic_loop () throw ()
  310. {
  311. ev_loop_destroy (EV_AX);
  312. EV_AX = 0;
  313. }
  314. private:
  315. dynamic_loop (const dynamic_loop &);
  316. dynamic_loop & operator= (const dynamic_loop &);
  317. };
  318. #endif
  319. struct default_loop : loop_ref
  320. {
  321. default_loop (unsigned int flags = AUTO) throw (bad_loop)
  322. #if EV_MULTIPLICITY
  323. : loop_ref (ev_default_loop (flags))
  324. #endif
  325. {
  326. if (
  327. #if EV_MULTIPLICITY
  328. !EV_AX
  329. #else
  330. !ev_default_loop (flags)
  331. #endif
  332. )
  333. throw bad_loop ();
  334. }
  335. private:
  336. default_loop (const default_loop &);
  337. default_loop &operator = (const default_loop &);
  338. };
  339. inline loop_ref get_default_loop () throw ()
  340. {
  341. #if EV_MULTIPLICITY
  342. return ev_default_loop (0);
  343. #else
  344. return loop_ref ();
  345. #endif
  346. }
  347. #undef EV_AX
  348. #undef EV_AX_
  349. #undef EV_PX
  350. #undef EV_PX_
  351. #if EV_MULTIPLICITY
  352. # define EV_PX loop_ref EV_A
  353. # define EV_PX_ loop_ref EV_A_
  354. #else
  355. # define EV_PX
  356. # define EV_PX_
  357. #endif
  358. template<class ev_watcher, class watcher>
  359. struct base : ev_watcher
  360. {
  361. #if EV_MULTIPLICITY
  362. EV_PX;
  363. // loop set
  364. void set (EV_P) throw ()
  365. {
  366. this->EV_A = EV_A;
  367. }
  368. #endif
  369. base (EV_PX) throw ()
  370. #if EV_MULTIPLICITY
  371. : EV_A (EV_A)
  372. #endif
  373. {
  374. ev_init (this, 0);
  375. }
  376. void set_ (const void *data, void (*cb)(EV_P_ ev_watcher *w, int revents)) throw ()
  377. {
  378. this->data = (void *)data;
  379. ev_set_cb (static_cast<ev_watcher *>(this), cb);
  380. }
  381. // function callback
  382. template<void (*function)(watcher &w, int)>
  383. void set (void *data = 0) throw ()
  384. {
  385. set_ (data, function_thunk<function>);
  386. }
  387. template<void (*function)(watcher &w, int)>
  388. static void function_thunk (EV_P_ ev_watcher *w, int revents)
  389. {
  390. function
  391. (*static_cast<watcher *>(w), revents);
  392. }
  393. // method callback
  394. template<class K, void (K::*method)(watcher &w, int)>
  395. void set (K *object) throw ()
  396. {
  397. set_ (object, method_thunk<K, method>);
  398. }
  399. // default method == operator ()
  400. template<class K>
  401. void set (K *object) throw ()
  402. {
  403. set_ (object, method_thunk<K, &K::operator ()>);
  404. }
  405. template<class K, void (K::*method)(watcher &w, int)>
  406. static void method_thunk (EV_P_ ev_watcher *w, int revents)
  407. {
  408. (static_cast<K *>(w->data)->*method)
  409. (*static_cast<watcher *>(w), revents);
  410. }
  411. // no-argument callback
  412. template<class K, void (K::*method)()>
  413. void set (K *object) throw ()
  414. {
  415. set_ (object, method_noargs_thunk<K, method>);
  416. }
  417. template<class K, void (K::*method)()>
  418. static void method_noargs_thunk (EV_P_ ev_watcher *w, int revents)
  419. {
  420. (static_cast<K *>(w->data)->*method)
  421. ();
  422. }
  423. void operator ()(int events = EV_UNDEF)
  424. {
  425. return
  426. ev_cb (static_cast<ev_watcher *>(this))
  427. (static_cast<ev_watcher *>(this), events);
  428. }
  429. bool is_active () const throw ()
  430. {
  431. return ev_is_active (static_cast<const ev_watcher *>(this));
  432. }
  433. bool is_pending () const throw ()
  434. {
  435. return ev_is_pending (static_cast<const ev_watcher *>(this));
  436. }
  437. void feed_event (int revents) throw ()
  438. {
  439. ev_feed_event (EV_A_ static_cast<ev_watcher *>(this), revents);
  440. }
  441. };
  442. inline tstamp now (EV_P) throw ()
  443. {
  444. return ev_now (EV_A);
  445. }
  446. inline void delay (tstamp interval) throw ()
  447. {
  448. ev_sleep (interval);
  449. }
  450. inline int version_major () throw ()
  451. {
  452. return ev_version_major ();
  453. }
  454. inline int version_minor () throw ()
  455. {
  456. return ev_version_minor ();
  457. }
  458. inline unsigned int supported_backends () throw ()
  459. {
  460. return ev_supported_backends ();
  461. }
  462. inline unsigned int recommended_backends () throw ()
  463. {
  464. return ev_recommended_backends ();
  465. }
  466. inline unsigned int embeddable_backends () throw ()
  467. {
  468. return ev_embeddable_backends ();
  469. }
  470. inline void set_allocator (void *(*cb)(void *ptr, long size) throw ()) throw ()
  471. {
  472. ev_set_allocator (cb);
  473. }
  474. inline void set_syserr_cb (void (*cb)(const char *msg) throw ()) throw ()
  475. {
  476. ev_set_syserr_cb (cb);
  477. }
  478. #if EV_MULTIPLICITY
  479. #define EV_CONSTRUCT(cppstem,cstem) \
  480. (EV_PX = get_default_loop ()) throw () \
  481. : base<ev_ ## cstem, cppstem> (EV_A) \
  482. { \
  483. }
  484. #else
  485. #define EV_CONSTRUCT(cppstem,cstem) \
  486. () throw () \
  487. { \
  488. }
  489. #endif
  490. /* using a template here would require quite a bit more lines,
  491. * so a macro solution was chosen */
  492. #define EV_BEGIN_WATCHER(cppstem,cstem) \
  493. \
  494. struct cppstem : base<ev_ ## cstem, cppstem> \
  495. { \
  496. void start () throw () \
  497. { \
  498. ev_ ## cstem ## _start (EV_A_ static_cast<ev_ ## cstem *>(this)); \
  499. } \
  500. \
  501. void stop () throw () \
  502. { \
  503. ev_ ## cstem ## _stop (EV_A_ static_cast<ev_ ## cstem *>(this)); \
  504. } \
  505. \
  506. cppstem EV_CONSTRUCT(cppstem,cstem) \
  507. \
  508. ~cppstem () throw () \
  509. { \
  510. stop (); \
  511. } \
  512. \
  513. using base<ev_ ## cstem, cppstem>::set; \
  514. \
  515. private: \
  516. \
  517. cppstem (const cppstem &o); \
  518. \
  519. cppstem &operator =(const cppstem &o); \
  520. \
  521. public:
  522. #define EV_END_WATCHER(cppstem,cstem) \
  523. };
  524. EV_BEGIN_WATCHER (io, io)
  525. void set (int fd, int events) throw ()
  526. {
  527. int active = is_active ();
  528. if (active) stop ();
  529. ev_io_set (static_cast<ev_io *>(this), fd, events);
  530. if (active) start ();
  531. }
  532. void set (int events) throw ()
  533. {
  534. int active = is_active ();
  535. if (active) stop ();
  536. ev_io_set (static_cast<ev_io *>(this), fd, events);
  537. if (active) start ();
  538. }
  539. void start (int fd, int events) throw ()
  540. {
  541. set (fd, events);
  542. start ();
  543. }
  544. EV_END_WATCHER (io, io)
  545. EV_BEGIN_WATCHER (timer, timer)
  546. void set (ev_tstamp after, ev_tstamp repeat = 0.) throw ()
  547. {
  548. int active = is_active ();
  549. if (active) stop ();
  550. ev_timer_set (static_cast<ev_timer *>(this), after, repeat);
  551. if (active) start ();
  552. }
  553. void start (ev_tstamp after, ev_tstamp repeat = 0.) throw ()
  554. {
  555. set (after, repeat);
  556. start ();
  557. }
  558. void again () throw ()
  559. {
  560. ev_timer_again (EV_A_ static_cast<ev_timer *>(this));
  561. }
  562. ev_tstamp remaining ()
  563. {
  564. return ev_timer_remaining (EV_A_ static_cast<ev_timer *>(this));
  565. }
  566. EV_END_WATCHER (timer, timer)
  567. #if EV_PERIODIC_ENABLE
  568. EV_BEGIN_WATCHER (periodic, periodic)
  569. void set (ev_tstamp at, ev_tstamp interval = 0.) throw ()
  570. {
  571. int active = is_active ();
  572. if (active) stop ();
  573. ev_periodic_set (static_cast<ev_periodic *>(this), at, interval, 0);
  574. if (active) start ();
  575. }
  576. void start (ev_tstamp at, ev_tstamp interval = 0.) throw ()
  577. {
  578. set (at, interval);
  579. start ();
  580. }
  581. void again () throw ()
  582. {
  583. ev_periodic_again (EV_A_ static_cast<ev_periodic *>(this));
  584. }
  585. EV_END_WATCHER (periodic, periodic)
  586. #endif
  587. #if EV_SIGNAL_ENABLE
  588. EV_BEGIN_WATCHER (sig, signal)
  589. void set (int signum) throw ()
  590. {
  591. int active = is_active ();
  592. if (active) stop ();
  593. ev_signal_set (static_cast<ev_signal *>(this), signum);
  594. if (active) start ();
  595. }
  596. void start (int signum) throw ()
  597. {
  598. set (signum);
  599. start ();
  600. }
  601. EV_END_WATCHER (sig, signal)
  602. #endif
  603. #if EV_CHILD_ENABLE
  604. EV_BEGIN_WATCHER (child, child)
  605. void set (int pid, int trace = 0) throw ()
  606. {
  607. int active = is_active ();
  608. if (active) stop ();
  609. ev_child_set (static_cast<ev_child *>(this), pid, trace);
  610. if (active) start ();
  611. }
  612. void start (int pid, int trace = 0) throw ()
  613. {
  614. set (pid, trace);
  615. start ();
  616. }
  617. EV_END_WATCHER (child, child)
  618. #endif
  619. #if EV_STAT_ENABLE
  620. EV_BEGIN_WATCHER (stat, stat)
  621. void set (const char *path, ev_tstamp interval = 0.) throw ()
  622. {
  623. int active = is_active ();
  624. if (active) stop ();
  625. ev_stat_set (static_cast<ev_stat *>(this), path, interval);
  626. if (active) start ();
  627. }
  628. void start (const char *path, ev_tstamp interval = 0.) throw ()
  629. {
  630. stop ();
  631. set (path, interval);
  632. start ();
  633. }
  634. void update () throw ()
  635. {
  636. ev_stat_stat (EV_A_ static_cast<ev_stat *>(this));
  637. }
  638. EV_END_WATCHER (stat, stat)
  639. #endif
  640. #if EV_IDLE_ENABLE
  641. EV_BEGIN_WATCHER (idle, idle)
  642. void set () throw () { }
  643. EV_END_WATCHER (idle, idle)
  644. #endif
  645. #if EV_PREPARE_ENABLE
  646. EV_BEGIN_WATCHER (prepare, prepare)
  647. void set () throw () { }
  648. EV_END_WATCHER (prepare, prepare)
  649. #endif
  650. #if EV_CHECK_ENABLE
  651. EV_BEGIN_WATCHER (check, check)
  652. void set () throw () { }
  653. EV_END_WATCHER (check, check)
  654. #endif
  655. #if EV_EMBED_ENABLE
  656. EV_BEGIN_WATCHER (embed, embed)
  657. void set_embed (struct ev_loop *embedded_loop) throw ()
  658. {
  659. int active = is_active ();
  660. if (active) stop ();
  661. ev_embed_set (static_cast<ev_embed *>(this), embedded_loop);
  662. if (active) start ();
  663. }
  664. void start (struct ev_loop *embedded_loop) throw ()
  665. {
  666. set (embedded_loop);
  667. start ();
  668. }
  669. void sweep ()
  670. {
  671. ev_embed_sweep (EV_A_ static_cast<ev_embed *>(this));
  672. }
  673. EV_END_WATCHER (embed, embed)
  674. #endif
  675. #if EV_FORK_ENABLE
  676. EV_BEGIN_WATCHER (fork, fork)
  677. void set () throw () { }
  678. EV_END_WATCHER (fork, fork)
  679. #endif
  680. #if EV_ASYNC_ENABLE
  681. EV_BEGIN_WATCHER (async, async)
  682. void send () throw ()
  683. {
  684. ev_async_send (EV_A_ static_cast<ev_async *>(this));
  685. }
  686. bool async_pending () throw ()
  687. {
  688. return ev_async_pending (static_cast<ev_async *>(this));
  689. }
  690. EV_END_WATCHER (async, async)
  691. #endif
  692. #undef EV_PX
  693. #undef EV_PX_
  694. #undef EV_CONSTRUCT
  695. #undef EV_BEGIN_WATCHER
  696. #undef EV_END_WATCHER
  697. }
  698. #endif