From d1d02ca0040b567cfc3081701b52b0361412a444 Mon Sep 17 00:00:00 2001 From: root Date: Sat, 10 Nov 2007 21:19:29 +0000 Subject: first rough cut at c++ interface --- ev++.h | 238 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 ev++.h (limited to 'ev++.h') diff --git a/ev++.h b/ev++.h new file mode 100644 index 0000000..95d0a76 --- /dev/null +++ b/ev++.h @@ -0,0 +1,238 @@ +#ifndef EVPP_H__ +#define EVPP_H__ + +/* work in progress, don't use unless you know what you are doing */ + +namespace ev { + + template + class callback + { + struct object { }; + + void *obj; + void (object::*meth)(watcher &, int); + + /* a proxy is a kind of recipe on how to call a specific class method */ + struct proxy_base { + virtual void call (void *obj, void (object::*meth)(watcher &, int), watcher &w, int) const = 0; + }; + template + struct proxy : proxy_base { + virtual void call (void *obj, void (object::*meth)(watcher &, int), watcher &w, int e) const + { + ((reinterpret_cast(obj)) ->* (reinterpret_cast(meth))) + (w, e); + } + }; + + proxy_base *prxy; + + public: + template + explicit callback (O1 *object, void (O2::*method)(watcher &, int)) + { + static proxy p; + obj = reinterpret_cast(object); + meth = reinterpret_cast(method); + prxy = &p; + } + + void call (watcher *w, int e) const + { + return prxy->call (obj, meth, *w, e); + } + }; + + #include "ev.h" + + typedef ev_tstamp tstamp; + + inline ev_tstamp now (EV_P) + { + return ev_now (EV_A); + } + + #if EV_MULTIPLICITY + + #define EV_CONSTRUCT(cppstem) \ + EV_P; \ + \ + void set (EV_P) \ + { \ + this->EV_A = EV_A; \ + } \ + \ + template \ + explicit cppstem (O1 *object, void (O2::*method)(cppstem &, int), EV_P = ev_default_loop (0)) \ + : callback (object, method), EV_A (EV_A) + + #else + + #define EV_CONSTRUCT(cppstem) \ + template \ + explicit cppstem (O1 *object, void (O2::*method)(cppstem &, int)) \ + : callback (object, method) + + #endif + + /* using a template here would require quite a bit more lines, + * so a macro solution was chosen */ + #define EV_DECLARE_WATCHER(cppstem,cstem) \ + \ + extern "C" void cb_ ## cppstem (struct ev_ ## cstem *w, int revents); \ + \ + struct cppstem : ev_ ## cstem, callback \ + { \ + EV_CONSTRUCT (cppstem) \ + { \ + ev_init (static_cast(this), cb_ ## cppstem); \ + } \ + \ + bool is_active () const \ + { \ + return ev_is_active (static_cast(this)); \ + } \ + \ + bool is_pending () const \ + { \ + return ev_is_pending (static_cast(this)); \ + } \ + \ + void start () \ + { \ + ev_ ## cstem ## _start (EV_A_ static_cast(this)); \ + } \ + \ + void stop () \ + { \ + ev_ ## cstem ## _stop (EV_A_ static_cast(this)); \ + } \ + \ + void operator ()(int events = EV_UNDEF) \ + { \ + return call (this, events); \ + } \ + \ + private: \ + \ + cppstem (const cppstem &o) \ + : callback (this, (void (cppstem::*)(cppstem &, int))0) \ + { /* disabled */ } \ + void operator =(const cppstem &o) { /* disabled */ } \ + \ + public: + + EV_DECLARE_WATCHER (io, io) + void set (int fd, int events) + { + int active = is_active (); + if (active) stop (); + ev_io_set (static_cast(this), fd, events); + if (active) start (); + } + + void set (int events) + { + int active = is_active (); + if (active) stop (); + ev_io_set (static_cast(this), fd, events); + if (active) start (); + } + + void start (int fd, int events) + { + set (fd, events); + start (); + } + }; + + EV_DECLARE_WATCHER (timer, timer) + void set (ev_tstamp after, ev_tstamp repeat = 0.) + { + int active = is_active (); + if (active) stop (); + ev_timer_set (static_cast(this), after, repeat); + if (active) start (); + } + + void start (ev_tstamp after, ev_tstamp repeat = 0.) + { + set (after, repeat); + start (); + } + + void again () + { + ev_timer_again (EV_A_ static_cast(this)); + } + }; + + EV_DECLARE_WATCHER (periodic, periodic) + void set (ev_tstamp at, ev_tstamp interval = 0.) + { + int active = is_active (); + if (active) stop (); + ev_periodic_set (static_cast(this), at, interval, 0); + if (active) start (); + } + + void start (ev_tstamp at, ev_tstamp interval = 0.) + { + set (at, interval); + start (); + } + + void again () + { + ev_periodic_again (EV_A_ static_cast(this)); + } + }; + + EV_DECLARE_WATCHER (idle, idle) + }; + + EV_DECLARE_WATCHER (prepare, prepare) + }; + + EV_DECLARE_WATCHER (check, check) + }; + + EV_DECLARE_WATCHER (sig, signal) + void set (int signum) + { + int active = is_active (); + if (active) stop (); + ev_signal_set (static_cast(this), signum); + if (active) start (); + } + + void start (int signum) + { + set (signum); + start (); + } + }; + + EV_DECLARE_WATCHER (child, child) + void set (int pid) + { + int active = is_active (); + if (active) stop (); + ev_child_set (static_cast(this), pid); + if (active) start (); + } + + void start (int pid) + { + set (pid); + start (); + } + }; + + #undef EV_CONSTRUCT + #undef EV_DECLARE_WATCHER +} + +#endif + -- cgit v1.2.3