Re: [RFC] extending ev++.h to add C++ loop wrappers.
On Wed, Jan 16, 2008 at 05:20:06PM -0200, Leandro Lucarella <[EMAIL PROTECTED]> wrote: > > (like watchers? but since they are radically different methods, maybe the > > must be called otherwise). Maybe just loop -> do_loop? > > Even more, if we call it loop, then we can't name the internal base > watcher variable "loop" either :S Yeah.. of course.. but... ev::loop might be worse than ev::loop_ref (or maybe not, not sure). I would expect programs to use ev::loop_dynamic sometimes, ev::loop_default more often and accessing the loop itself by name very rarely, i.e. // expected: watcher.loop->unloop (); // unexpected ev::loop_something l = watcher.loop; l.unloop (); The othe rhting is that most people do not really copy references around, it makes little sense (there is no value semantics), so a loop * would do fine as well. -- The choice of a Deliantra, the free code+content MORPG -==- _GNU_ http://www.deliantra.net ==-- _ generation ---==---(_)__ __ __ Marc Lehmann --==---/ / _ \/ // /\ \/ / [EMAIL PROTECTED] -=/_/_//_/\_,_/ /_/\_\ ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: [RFC] extending ev++.h to add C++ loop wrappers.
Marc Lehmann, el 17 de enero a las 08:57 me escribiste: > On Wed, Jan 16, 2008 at 04:12:02PM -0200, Leandro Lucarella <[EMAIL > PROTECTED]> wrote: > > Marc Lehmann, el 16 de enero a las 05:43 me escribiste: > > I'm trying to go back to this design, but I'm starting to need the loop to > > be virtual again because, I can't put ev_xxx_destroy () call in the > > destructor in the ev::loop (to follow the proposed names above). > > Ah, because you shouldn't, you can just put the relevant destructor into > loop_dynamic and loop_default, as a mere loop will not destruct the loop, it > will be merely a container for the loop pointer. > > > if ~loop () is empty and each destructor has it own ev_xxx_destroy () > > call, then when using a loop pointer, you can't destroy the loop > > because of the lack of virtualness: > > Thats fine, a virtual destructor isn't really neecssary for a thin > interface. think about it: you *need* to use the right type to construct, > and you should use the same type when deleting, i.e. the problem will only > come up when you: > >loop_dynamic *l = new loop_dynamic; >delete (loop *)l; > > That is pretty dumb to begin with. No, the problem is, for example: void cb (ev::io &w, int revents) { w.loop->unloop(); delete w.loop; } This would be strange anyways, because you probably will know beforehand that *that* loop is really a dynamic or default loop. OTOH if w.lopp is a loop_ref instead of a ev_loop*, you can't even do the delete w.loop because it's a value type. You should do something like w.loop.destroy (), but that destroy have to be virtual, unless ev_loop_destroy () can destroy both type of loops (which I think I could be nice and avoid some problems). > Besides, I would expect most loops not to be dynamically allocated at all, > but just be static global objects, or members of some other object. I do > not see the reason for a dynamically allocating a loop itself. Agree, but you never know :) > So... I don't really see the need for a virtual destructor (again, just > because this is suppused to be a very thin interface). Ok. Can I rely on ev_loop_{fork,destroy} accepting default loops when EV_MULTIPLICITY is set? -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) Vaporeso, al verse enfundado por la depresión, decide dar fin a su vida tomando Chinato Garda mezclado con kerosene al 50%. Ante el duro trance pierde la movilidad en sus miembros derechos: inferior y superior. En ese momento es considerado como el hombre líder del movimiento de izquierda de Occidente. ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: [RFC] extending ev++.h to add C++ loop wrappers.
Marc Lehmann, el 16 de enero a las 05:43 me escribiste: > Not if you are convinced its what people predominantly want. I have as > much data on that as you (i.e. mostly my own: I have more READ than write > watchers, but I don't see why it should be the default. Think readability: > >start (fd); // waits for read events > > this doesn't look intuitive when I remove the comment). BTW, I noticed you can already do this: ev::io w; w.set (READ); // In a galaxy far, far away from the previous code: w.start (fd); // woops! not that intuitive ;) I will remove the default anyways because I'm a pythonic guy and I should remember that explicit is better than implicit ;) -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) Si por el chancho fuera, se autocomería con chimichurri Worshestershire! ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
New iteration over the ev++ improvement patch.
Well, after all the talking and thinking, this is what I came up with. Main changes: * The use of exceptions is now optional (configurable via EV_CXX_EXCEPTIONS). I don't know if: #define throw(exception) throw (exception) is valid preprocesor code though =) It could be easily changed to EV_THROW or something but I wanted to keep the syntax highlight ;) * All the macro constant -> enum translation is moved to the top. * Back to a loop_ref + dynamic_loop + default_loop scheme. - loop_ref has value semantics and is just a pointer wrapper (but with reference syntax ;). You can change a ev_loop* and a loop_ref without notice. You can create (or asign) a loop_ref from a ev_loop* and you can cast a loop_ref to a ev_loop*. You can check for equality between loop_refs and ev_loop pointers. - dynamic_loop and default_loop have both reference semantics (they are non-copiable and non-assignable), and provide automatic destruction. - No check is done when creating a default_loop to see if one is already created (could be trouble if ev_default_destroy() is called more than once?). * loop_ref::is_default() is provided using ev_default_loop in the meantime to implement fork() and destroy() in loop_ref (waiting to see if ev_loop_{fork,destroy} would accept a default or dynamic loop indistinctly). * A new function ev::get_default_loop () is provided to get a loop_ref to the default loop. Once again, no check is done to ensure this function wont get called before actually creating the default loop. * loop_ref::fork() is now named loop_ref::fix_fork(). * ev::time() is now named ev::now(). * ev::sleep() is now named ev::delay() (stolen from SDL ;). * Watchers now store a loop_ref. Since you can assign a ev_loop* to a loop_ref, everybody should be happy now. Patch and example attached. Documentation still missing (I'll do that when the patch gets a technical OK =). I'll probably split the patch in smaller, incremental changes. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) - i bet microsoft's developers were on diet when they had to do win95 - microsoft has developers? ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: New iteration over the ev++ improvement patch.
Leandro Lucarella, el 17 de enero a las 17:08 me escribiste: > Patch and example attached. Documentation still missing (I'll do that when > the patch gets a technical OK =). I'll probably split the patch in > smaller, incremental changes. I think not many people undestand the invisible diff format, so I'll attach it again in unified diff format =P -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) Novocaine for the soul you better give me something to fill the hole before I sputter out diff --git a/ev++.h b/ev++.h index e447998..5cdf326 100644 --- a/ev++.h +++ b/ev++.h @@ -43,24 +43,404 @@ #ifdef EV_H # include EV_H #else -# include +# include "ev.h" +#endif + +#ifndef EV_CXX_EXCEPTIONS +#define EV_CXX_EXCEPTIONS 1 +#endif + +#undef throw +#if EV_CXX_EXCEPTIONS +# include +# define throw(exception) throw (exception) +#else +# define throw(exception) #endif namespace ev { + typedef ev_tstamp tstamp; + + enum { +UNDEF= EV_UNDEF, +NONE = EV_NONE, +READ = EV_READ, +WRITE= EV_WRITE, +TIMEOUT = EV_TIMEOUT, +PERIODIC = EV_PERIODIC, +SIGNAL = EV_SIGNAL, +CHILD= EV_CHILD, +STAT = EV_STAT, +IDLE = EV_IDLE, +CHECK= EV_CHECK, +PREPARE = EV_PREPARE, +FORK = EV_FORK, +EMBED= EV_EMBED, +ERROR= EV_ERROR, + }; + + enum + { +AUTO = EVFLAG_AUTO, +NOENV = EVFLAG_NOENV, +FORKCHECK = EVFLAG_FORKCHECK, +SELECT = EVBACKEND_SELECT, +POLL = EVBACKEND_POLL, +EPOLL = EVBACKEND_EPOLL, +KQUEUE = EVBACKEND_KQUEUE, +DEVPOLL = EVBACKEND_DEVPOLL, +PORT = EVBACKEND_PORT + }; + + enum + { +NONBLOCK = EVLOOP_NONBLOCK, +ONESHOT = EVLOOP_ONESHOT + }; + + enum how_t + { +ONE = EVUNLOOP_ONE, +ALL = EVUNLOOP_ALL + }; + + +#if EV_CXX_EXCEPTIONS + struct bad_loop: std::runtime_error + { +bad_loop() + : std::runtime_error("loop can't be initialized") {} + }; +#endif + +#ifdef EV_AX +# undef EV_AX +#endif + +#ifdef EV_AX_ +# undef EV_AX_ +#endif + +#if EV_MULTIPLICITY +# define EV_AX raw_loop +# define EV_AX_ raw_loop, +#else +# define EV_AX +# define EV_AX_ +#endif + +#if 0 // XXX EV_MULTIPLICITY + extern "C" + { + extern struct ev_loop* default_loop_ptr; + } +#endif + + struct loop_ref + { + +loop_ref (EV_P) throw (bad_loop) +#if EV_MULTIPLICITY + : EV_AX (EV_A) +#endif +{ +#if EV_CXX_EXCEPTIONS + if (!EV_A) +throw bad_loop (); +#endif +} + +bool operator== (const loop_ref &other) const throw () +{ +#if EV_MULTIPLICITY + return this->EV_AX == other.EV_AX; +#else + return true; +#endif +} + +bool operator!= (const loop_ref &other) const throw () +{ +#if EV_MULTIPLICITY + return ! (*this == other); +#else + return false; +#endif +} + +#if EV_MULTIPLICITY +bool operator== (struct ev_loop *other) const throw () +{ + return this->EV_AX == other; +} + +bool operator!= (struct ev_loop *other) const throw () +{ + return ! (*this == other); +} + +bool operator== (const struct ev_loop *other) const throw () +{ + return this->EV_AX == other; +} + +bool operator!= (const struct ev_loop *other) const throw () +{ + return (*this == other); +} + +operator struct ev_loop * () const throw () +{ + return EV_AX; +} + +operator const struct ev_loop * () const throw () +{ + return EV_AX; +} + +bool is_default () const throw () +{ + return EV_AX == ev_default_loop (0); // XXX default_loop_ptr; +} +#endif + +void loop (int flags = 0) throw () +{ + ev_loop (EV_AX_ flags); +} + +void unloop (how_t how = ONE) throw () +{ + ev_unloop (EV_AX_ how); +} + +// XXX should be protected? Since if we call it by hand and then called +// automatically by the destructor, it could blow... +void destroy () throw () +{ +#if EV_MULTIPLICITY + if (!is_default ()) +ev_loop_destroy (EV_AX); + else +#endif +ev_default_destroy (); + EV_AX = 0; +} + +void fix_fork () throw () +{ +#if EV_MULTIPLICITY + if (!is_default ()) +ev_loop_fork (EV_AX); + else +#endif +ev_default_fork (); +} + +unsigned int count () const throw () +{ + return ev_loop_count (EV_AX); +} + +unsigned int backend () const throw () +{ + return ev_backend (EV_AX); +} + +tstamp now () const throw () +{ + return ev_now (EV_AX); +} + +void ref () throw () +{ + ev_ref (EV_AX); +} + +void unref () throw () +{ + ev_unref (EV_AX); +} + +void set_io_collect_interval (tstamp i
Re: New iteration over the ev++ improvement patch.
On Thu, Jan 17, 2008 at 05:08:16PM -0200, Leandro Lucarella <[EMAIL PROTECTED]> wrote: > Well, after all the talking and thinking, this is what I came up with. > > Main changes: > * The use of exceptions is now optional (configurable via > EV_CXX_EXCEPTIONS). I don't know if: > #define throw(exception) throw (exception) > is valid preprocesor code though =) the "recursion" is fine, overriding throw isn't, because: a) you sometimes use a zero-argument form of throw() b) overriding throw isn't really legal c) never override stuff the uer validly might have overridden herself already > * Back to a loop_ref + dynamic_loop + default_loop scheme. Sounds good. Time will tell wether it was the right decision :) > - dynamic_loop and default_loop have both reference semantics (they are > non-copiable and non-assignable), and provide automatic destruction. very good. > - No check is done when creating a default_loop to see if one is already > created (could be trouble if ev_default_destroy() is called more than > once?). right now, calling ev_default_destroy twice is a bug. this is safe, however: ev_default_init (0); ev_default_destroy () I think at first we should do it that way, we can simplify later, together with changing ev_default_* into aliases to the ev_loop functions internally. > * loop_ref::is_default() is provided using ev_default_loop in the meantime > to implement fork() and destroy() in loop_ref (waiting to see if > ev_loop_{fork,destroy} would accept a default or dynamic loop > indistinctly). Lets keep it thsi way till it works and then optimise :) > * A new function ev::get_default_loop () is provided to get a loop_ref to > the default loop. Once again, no check is done to ensure this function > wont get called before actually creating the default loop. Can't help it, I still am not sure we should provide an actual default loop wrapper, as I think the default loop is a shared resource that is not controlled by any one instance. > * loop_ref::fork() is now named loop_ref::fix_fork(). try post_fork, it doesn't really fix any fork thing :) > * ev::time() is now named ev::now(). bad idea, now "now" means something for C, and something else for C++. I would expect ev::now() to do mostly the same as ev_now (). > * ev::sleep() is now named ev::delay() (stolen from SDL ;). ah well :) I wonder wether we shouldn't use some prefix instead instead of renaming all symbols. > Patch and example attached. Documentation still missing (I'll do that when > the patch gets a technical OK =). I'll probably split the patch in > smaller, incremental changes. You can just apply it yourself in one go. We can then change it from that point. -- The choice of a Deliantra, the free code+content MORPG -==- _GNU_ http://www.deliantra.net ==-- _ generation ---==---(_)__ __ __ Marc Lehmann --==---/ / _ \/ // /\ \/ / [EMAIL PROTECTED] -=/_/_//_/\_,_/ /_/\_\ ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: [RFC] extending ev++.h to add C++ loop wrappers.
On Wed, Jan 16, 2008 at 03:37:12PM -0200, Leandro Lucarella <[EMAIL PROTECTED]> wrote: > > Well, I think its a wonderful idea, its a loop, it should be called loop :) > > If we call it loop, then the loop() method has to be called other way, > that's why I didn't call it loop. Maybe loop -> start, unloop -> stop > (like watchers? but since they are radically different methods, maybe the > must be called otherwise). Maybe just loop -> do_loop? loop::run () // flags=0 loop::one_iteration () // once loop::sweep () // nonblock would be possible :) Or even: loop (); :-> the reason it is called ev_loop is caused by a limitation in C's object orientation, and I think we can get away with renaming it here (it actually is taken mostly from libevent, and today I think maybe its not that good an interface). I am not saying we should rename it, its basically the question wether we want to use something ugly like loop_ref and a loop_ref::loop, or a loop, and a renamed (nut nice) loop::run (). -- The choice of a Deliantra, the free code+content MORPG -==- _GNU_ http://www.deliantra.net ==-- _ generation ---==---(_)__ __ __ Marc Lehmann --==---/ / _ \/ // /\ \/ / [EMAIL PROTECTED] -=/_/_//_/\_,_/ /_/\_\ ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: [RFC] extending ev++.h to add C++ loop wrappers.
On Thu, Jan 17, 2008 at 10:28:16AM -0200, Leandro Lucarella <[EMAIL PROTECTED]> wrote: > > Bause I don't: I changed ->stat to ->update already and it sucks. The > > obvious method would be to call them ev_sleep etc. (haha). > > do_/get_xxx? do_fork, do_sleep, get_time? > > fix_fork? go_sleep? now? (note that the now that gets the loop time is in > the loop object in ev:: =) I frankly don't know. (as for now, I think then libev should have ev_now => ev_time, and ev_now => ev_loop_now, but thats ugly). The prefix method, however ugly, is at leats consistent between C and C++. But of course do_ is about the worst possible prefix. I can't come up with anything better, sorry. I guess the total rename is mostly the way to go then, i.e. deviate as much as neccessary from the C API. > > Another option would be to #undef sleep in the header file. Thats rather > > drastic however and some people will hate us for it. > > Yeah, I think that would be pretty hardcore... Says the guy who redefined throw(). On Thu, Jan 17, 2008 at 10:46:52AM -0200, Leandro Lucarella <[EMAIL PROTECTED]> wrote: > > That is pretty dumb to begin with. > > No, the problem is, for example: > > void cb (ev::io &w, int revents) > { > w.loop->unloop(); > delete w.loop; > } Thats pretty dumb to begin with, yes: deleting a loop that is actively running in ev_loop *is* pretty dumb, and undefined behaviour will be the punishment. > This would be strange anyways, because you probably will know beforehand > that *that* loop is really a dynamic or default loop. Not just that, you are likely executing the callback form within ev_loop, and freeing its memory while its still bein accessed is not going to work, ever. > OTOH if w.lopp is a loop_ref instead of a ev_loop*, you can't even do the > delete w.loop because it's a value type. You should do something like > w.loop.destroy (), but that destroy have to be virtual, unless > ev_loop_destroy () can destroy both type of loops (which I think I could > be nice and avoid some problems). I think onyl the default destructor should destroy the loop. That practically ensures that it works (and you already implemneted it that way :) > Can I rely on ev_loop_{fork,destroy} accepting default loops when > EV_MULTIPLICITY is set? Definitely not, we should work aroundt hat way, even if inefficient, at the moment, and later redesign those functions and optimise the ev++.h use. -- The choice of a Deliantra, the free code+content MORPG -==- _GNU_ http://www.deliantra.net ==-- _ generation ---==---(_)__ __ __ Marc Lehmann --==---/ / _ \/ // /\ \/ / [EMAIL PROTECTED] -=/_/_//_/\_,_/ /_/\_\ ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev