Re: [PATCH] Only compile ev::now() if EV_MULTIPLICITY is defined.
Marc Lehmann, el 15 de enero a las 04:13 me escribiste: > On Mon, Jan 14, 2008 at 01:35:22PM -0200, Leandro Lucarella <[EMAIL > PROTECTED]> wrote: > > Since ev_now() not available if EV_MULTIPLICITY is not defined, it has not > > much sense having a ev::now() that calls an inexistent ev_now() ;) > > not sure what you mean, ev_now is available regardless of any value for > EV_MULTIPLICITY? I mean, in ev.h says: # if EV_MULTIPLICITY /* ... */ ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after each poll */ #else /* ... */ But in ev++.h there was no conditional compilation for ev::now(), that uses ev_now(). -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) Bulletproof... I Wish I Was ___ 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 15 de enero a las 08:06 me escribiste: > > your opinion before deciding what to do with them, and of course, I want > > to know if there is any interest in merging this to the official libev > > distribution =) > > Yes, there is. Two things are required for inclusion: > > a) it should be sound (i.e. required, within the goals, i.e. relatively lean) > b) somebody needs to maintain it > > a) is probably given (I haven't had a thorough look :), and would you > commit to do b)? Sure. > > Here's patch that implement this scheme (over the original patch). Even if > > it's nice to stay close to the C API and to avoid the posibility of > > instantiating 2 default loops from the root, I think the usage is a little > > less intuitive in a C++ environment. > > libev already enforces the singleton approach for us, the loop_default > objects can exist manyfold without us having to worry about it. > > On Mon, Jan 14, 2008 at 06:40:08PM -0200, Leandro Lucarella <[EMAIL > PROTECTED]> wrote: > > * is_default was removed from loop_base, since now the class matches the > > type of loop (is_default == dynamic_cast< loop_default* >(loop_ptr)). > > Hmm, the loops are not polymorphic, so the dynamic_cast will not be helpful. > In any case, is_default == (loop_ == ev_default_loop (0)). They are in the patch I sent =) Just for the fork() and destructors. > > + enum > > + { > > +AUTO = EVFLAG_AUTO, > > +NOENV = EVFLAG_NOENV, > > +FORKCHECK = EVFLAG_FORKCHECK, > > putting all the constants into the ev:: namespace was my original goal > (when I hoped to keep most of the C api outside the global namespace), but > I gave up on this. > > In any case, I think there should either be ALL of the symbols available or > none (or they shouldn't be announced), as remembering whats in ev:: and whats > not is tedious. > > That was the reason I originally kept out most of the functions outside it, > too (ev::now is the exception, and it doesn't look well). > > If everything *is* inside ev:: that would be fine, but its quite a bit of > work. Otherwise, I have no hard feelings either way. Is not that hard, is a bit of work done once (and it's already done in the patch ;). So, it's ok for you to expose the entire API in the ev namespace? > > + enum how_t > > + { > > +ONE = EVUNLOOP_ONE, > > +ALL = EVUNLOOP_ALL > > Thats different, this way we do gain a bit of type-safety :) =) > > +#if EV_MULTIPLICITY > > +# define EV_AX _loop > > +# define EV_AX_ _loop, > > +#else > > +# define EV_AX > > +# define EV_AX_ , > > Both EV_AX and EV_AX_ should be empty here, no? Yeap. > > +#if EV_MULTIPLICITY > > +operator struct ev_loop * () const throw () > > +{ > > + return _loop; > > for various reasons, I would prefer the "_" at the end, but again, I don't > care much :) I'm use to the "_" as a prefix, but I don't care much either and is you lib, so, I'll use the suffix form ;) > I wonder why it cannot be simply "loop"? Does it collide with anything? Yes, with loop_base& loop(). I didn't expose the pointer directly because I like references when the "ownership" of the pointer is not transfered. When you receive a reference, you are positive that you can't free it, when you receive a pointer, you have to check the documentation =) But if you think is too much trouble, I cant expose the loop (without "_") pointer directly. > > +virtual void fork () throw () = 0; > > fork () might be a global symbol that would collide with this declaration > (no idea if it atcually causes a problem on existing systems, though). That would only be true if fork can be a macro symbol. I don't know if this is actually done by any OS but the POSIX standard don't say anything about fork() being a macro (or even if it's implementation defined) [1] as it does with other symbols (FD_XXX for instance [2]). [1] http://www.opengroup.org/onlinepubs/95399/functions/fork.html [2] http://www.opengroup.org/onlinepubs/95399/functions/select.html > > +void set_io_collect_interval (tstamp interval) throw () > > +void set_timeout_collect_interval (tstamp interval) throw () > > Looks quite complete already :) > > > +// method callback > > +template > > +void once (int fd, int events, tstamp timeout, K *object) > > pure fun! > > > +// simpler function callback > > +template > > +void once (int fd, int events, tstamp timeout) > > +{ > > + once (fd, events, timeout, simpler_func_thunk); > > +} > > Fascinating, shouldn't we add this to the watcher base, too? > > I do wonder how useful it is, I wondered about it myself, but I tend to > always need the watcher in any real-world callback. > > > +~loop_simple () throw () > > Maybe loop_simpel should rarlly be "loop" if we can get away with it > without collisions. Yes, I thought about it too, but with all that "loop" everywhere I didn't thought it was a great idea (exactly because the high probability of
Re: Bug with signal delivery after fork.
On Tue, Jan 15, 2008 at 05:06:27AM +0100, Marc Lehmann wrote: > On Mon, Jan 14, 2008 at 10:56:54AM -0500, Chris Shoemaker <[EMAIL PROTECTED]> > wrote: > > I believe the attached program demonstrates some bug related to signal > > delivery after a fork. > > Oh, what you see is that ev_default_fork only sets a flag for the next run > of ev_loop. You will have to run ev_loop to reinitialise the kernel state > after a fork (e.g. ev_loop (EVLOOP_NONBLOCK) will do). > > The documentation will point this out in the next release (and it will > contain other things required by kqueue, which makes it less flexible). Adding: ev_loop(loop, EVLOOP_NONBLOCK); immediately after the call to ev_default_fork() did not noticeably change the behavior of the program. It still hangs about about 10% of the time. -chris ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: Disabling the SIGCHLD handler
On Tue, Jan 15, 2008 at 04:38:54AM +0100, Marc Lehmann wrote: > On Mon, Jan 14, 2008 at 10:38:51AM -0500, Chris Shoemaker <[EMAIL PROTECTED]> > wrote: > > On Mon, Jan 14, 2008 at 03:06:41AM +0100, Marc Lehmann wrote: > > Notice that nothing prevents the waitpid from reaping any child at all. > > Right, thats how it was designed. > > > All that is then required is for someone to start a ev_child for the > > child we just reaped. That event will never trigger. > > If you start the ev_child handler _after_ handling child events, thats > true. You need to start it before. But you do not need to start the child > handler before creating the process, or before the process exits, only > before you poll for more events. I'm glad we finally agree, in practice at least. I do appreciate that there is a case in which libev _can_ provide the exit status of a child that exited before the child_ev was started - when the default event loop has never run between the exiting of the child and the starting of the ev_child. In my opinion, this is a rather special and uninteresting exception to the general rule that running the default event loop will eagerly reap the exit status of children, even before an ev_child has started. > > ev_loop(loop, EVLOOP_NONBLOCK); > > Well, you run the loop before doing that, obviously, you have to start your > child handler before doing that. In my case, I may not know that I even care to start an ev_child until a long, lomg time after the child has exited. And, when I do eventually care, I won't know whether the child has exited or not. Obviously, I can't avoid running the default loop indefinitely. > There really is no other sensible way to do it, and you can always structure > your program to make it work. I suppose you mean by using my own sigchld handler. > > If I understand what you're claiming, then that program should print the > > exit status 99, and then terminate. In fact, it does neither. > > I am not claiming anything. You were claiming that you cnanot catch the exit > status of a process that exited before startign an ev_child watcher, and that > was and is simply untrue. > > example quote: "it does force an application to choose between either: > a) not having access to the exit status of children that exited before a > ev_child was started, OR b)" [...] > > And this claim is untrue. You deleted an important part: "b) not being able to use ev_signal" That would require running the default event loop. We agree that a) is only true if the default event loop is run. Thus, the two options are exclusive. I never claimed A, I claimed A XOR B. > This works perfectly well: > > pid = fork () > // child exits here > cw.pid = pid; > ev_child_start (&cw); > > > Notice that the child (21046) has been reaped, with exit status 99, > > _before_ the ev_child has been started. > > In *some* cases this is true, but not in general. Please note that > registering a watcher "too late" is a problem for all other methods, too: > every method will fail if you register interest in it too late. Fair enough. You could say I'm expecting too much, to be able to get the exit status of a child that died long before I started an ev_child. But, as POSIX allows the waitpid caller to get the exit status long after the child has died, and as I must offer the POSIX semantics, I must also allow this. > > And as a matter of fact, this is the same reason why it would prevent my > > own waitpid from finding the already-reaped child. > > I cannot comment on your waitpid, but libev certainly allows you to > register child watchers after the child exited, but before the exit status > was fetched. This is true for *all* methods, even the one you outlined > before. > > > I don't follow, really, but here's basically how I would do it: > > thats very slow and causes high overhead. the basic promise of libev is > that it is efficient, not that it makes dozens/hundreds/thousands of > syscalls to reap a signal child. It's O(N) in the number of child watchers, and runs only upon SIGCHLD. Is that really so bad? I'd love to know of a more efficient way, but efficiency is secondard to correctness, so even if this handler is less efficicient than libev's, I need it because it doesn't reap the children eagerly. > > Perhaps you wanted to avoid handling the ECHILD, but I would need it, > > and using rpid == -1 seems rather like waitpid returning -1. > > libev handles ECHILD just fine, what makes you think it doesn't > handle this case? I meant acutally generating an event for ECHLD, which libev doesn't do, but which I prefer. > > Now, I realize that this might not offer the behavior you desire in terms > > of multiple ev_childs registering for the same pid. But this is ok for > > me, since I'm fine with the POSIX waitpid semantics of each child only > > unblocking one waitpid, and other waitpids getting ECHILD. I don't want > > it to appear like the child died more than once, even
Re: Bug with signal delivery after fork.
On Tue, Jan 15, 2008 at 10:50:34AM -0500, Chris Shoemaker wrote: > On Tue, Jan 15, 2008 at 05:06:27AM +0100, Marc Lehmann wrote: > > On Mon, Jan 14, 2008 at 10:56:54AM -0500, Chris Shoemaker <[EMAIL > > PROTECTED]> wrote: > > > I believe the attached program demonstrates some bug related to signal > > > delivery after a fork. > > > > Oh, what you see is that ev_default_fork only sets a flag for the next run > > of ev_loop. You will have to run ev_loop to reinitialise the kernel state > > after a fork (e.g. ev_loop (EVLOOP_NONBLOCK) will do). > > > > The documentation will point this out in the next release (and it will > > contain other things required by kqueue, which makes it less flexible). > > Adding: > > ev_loop(loop, EVLOOP_NONBLOCK); > > immediately after the call to ev_default_fork() did not noticeably > change the behavior of the program. It still hangs about about 10% of > the time. I've narrowed this down considerably by tracing both good and bad executions and comparing. I'll comment the differences in the code: ** if ((pid = fork()) == 0) { close(pdes[0]); ev_default_fork(); ev_loop(loop, EVLOOP_NONBLOCK); ev_signal_init (&signal_watcher, signal_cb, SIGHUP); ev_signal_start (loop, &signal_watcher); write(pdes[1], "baz", 4); close(pdes[1]); /* In a good run, the child will enter the ev_loop and block before receiving the SIGHUP. Then it notifies the watcher correctly. In a bad run, the child receives the SIGHUP before this ev_loop blocks, notices the SIGHUP, but never wakes the watcher. */ ev_loop(loop, 0); exit(99); } else { close(pdes[1]); read(pdes[0], buf, 4); /* After this point, the ev_signal has started */ close(pdes[0]); kill(pid, SIGHUP); res = waitpid(pid, &status, 0); printf("Result = %d, ExitStatus = %d\n", res, WEXITSTATUS(status)); } Looking at ev.c, it seems there is a race between the first active watcher and the delayed fork-fixup function. Ah, yes, there it is. The following patch fixes it, and my test program no longer hangs. -chris diff --git a/shotgun/external_libs/libev/ev.c b/shotgun/external_libs/libev/ev.c index b21b1a4..f8357b8 100644 --- a/shotgun/external_libs/libev/ev.c +++ b/shotgun/external_libs/libev/ev.c @@ -1534,13 +1534,13 @@ ev_loop (EV_P_ int flags) call_pending (EV_A); } - if (expect_false (!activecnt)) -break; - /* we might have forked, so reify kernel state if necessary */ if (expect_false (postfork)) loop_fork (EV_A); + if (expect_false (!activecnt)) +break; + /* update fd-related kernel structures */ fd_reify (EV_A); ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: Bug with signal delivery after fork.
On Tue, Jan 15, 2008 at 12:54:59PM -0500, Chris Shoemaker <[EMAIL PROTECTED]> wrote: > I've narrowed this down considerably by tracing both good and bad > executions and comparing. I'll comment the differences in the code: Your test program is still buggy: > ev_default_fork(); > ev_loop(loop, EVLOOP_NONBLOCK); > ev_signal_init (&signal_watcher, signal_cb, SIGHUP); > ev_signal_start (loop, &signal_watcher); You have to start your watcher before looping, otherwise it does return when no other watchers are active. -- 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: Disabling the SIGCHLD handler
On Tue, Jan 15, 2008 at 10:47:33AM -0500, Chris Shoemaker <[EMAIL PROTECTED]> wrote: > > handler before creating the process, or before the process exits, only > > before you poll for more events. > > I'm glad we finally agree, in practice at least. No, we don't. Your claim was wrong and is wrong. We do not agree the least. I don't understand why you cannot accept that. > In my opinion, this is a rather special and uninteresting exception to > the general rule that running the default event loop will eagerly reap > the exit status of children, even before an ev_child has started. Despite your opinion, it is by far the most common and important case. Your case, on the other hand, is very uncommon, and pessimising that a bit in favor of providing good and simple support for the common case makes sense (simple things should be simple, complex ones possible). > > Well, you run the loop before doing that, obviously, you have to start your > > child handler before doing that. > > In my case, I may not know that I even care to start an ev_child until a > long, lomg time after the child has exited. And, when I do eventually care, > I won't know whether the child has exited or not. Obviously, I can't > avoid running the default loop indefinitely. As this is a rather marginal and untypical case, I would suggest the simplest solution is to provide your own sigchld handler. > > There really is no other sensible way to do it, and you can always structure > > your program to make it work. > > I suppose you mean by using my own sigchld handler. No, but that is the simplest solution. > > > If I understand what you're claiming, then that program should print the > > > exit status 99, and then terminate. In fact, it does neither. > > > > I am not claiming anything. You were claiming that you cnanot catch the exit > > status of a process that exited before startign an ev_child watcher, and > > that > > was and is simply untrue. > > > > example quote: "it does force an application to choose between either: > > a) not having access to the exit status of children that exited before a > > ev_child was started, OR b)" [...] > > > > And this claim is untrue. > > You deleted an important part: "b) not being able to use ev_signal" No, it is not important. You can use ev_signal handlers and have access to the exit status of children etc. etc. > That would require running the default event loop. Yes. > We agree that a) is only true if the default event loop is run. No, a) is not true at all, regardless of which loop you run, as I have explained a number of times. Please understand that I will ignore your repetitions of this wrong claim, it doesn't get any truer. > Thus, the two options are exclusive. I never claimed A, I claimed A XOR > B. And your claim was and is wrong, as I explained (and you chose to ignore) a number of times. > Fair enough. You could say I'm expecting too much, to be able to get > the exit status of a child that died long before I started an > ev_child. Yes. > But, as POSIX allows the waitpid caller to get the exit status long > after the child has died, and as I must offer the POSIX semantics, I > must also allow this. Yes, libev does not do posix emulation, it is a higher-level interface, anything else would be pointless. The important point is thta libev doesn't preclude you from doing it differently. > It's O(N) in the number of child watchers, and runs only upon SIGCHLD. > Is that really so bad? The same could be said about select: It's O(n) in the number of fds and runs only when the process has nothing better to do, is that really so bad? The answer is, yes, sometimes it is. > I'd love to know of a more efficient way, but efficiency is secondard to > correctness, so even if this handler is less efficicient than libev's, I > need it because it doesn't reap the children eagerly. And youc na provide it without any problems. > > libev handles ECHILD just fine, what makes you think it doesn't > > handle this case? > > I meant acutally generating an event for ECHLD, which libev doesn't > do, but which I prefer. And which makes no sense in an event-based Program, as it would be a bug in the application. Your application isn't event-based, and this isn't well-supported by libev indeed, but libev doesn't try to support non-event-based programming styles, for obvious reasons. > > libev doesn't make it as if a child died more than once, even if there are > > multiple ev_child watchers. this isn't possible with the unix semantics. > > Eh?! Sometimes I wonder if we're reading the same code. Of course it does! > Two watchers for the same pid. How many get triggered? Both. > TWO! It had better be so, because that's exactly what the code does: Indeed. > It loops over ev_childs, feeding all the events. Remember?: I know my code well, thank you very much. Please stop insulting me. > why I warned you that my patch changed that.) Understand, I'm not > criticizing the de
Re: [PATCH] Only compile ev::now() if EV_MULTIPLICITY is defined.
On Tue, Jan 15, 2008 at 10:06:32AM -0200, Leandro Lucarella <[EMAIL PROTECTED]> wrote: > Marc Lehmann, el 15 de enero a las 04:13 me escribiste: > > On Mon, Jan 14, 2008 at 01:35:22PM -0200, Leandro Lucarella <[EMAIL > > PROTECTED]> wrote: > > > Since ev_now() not available if EV_MULTIPLICITY is not defined, it has not > > > much sense having a ev::now() that calls an inexistent ev_now() ;) > > > > not sure what you mean, ev_now is available regardless of any value for > > EV_MULTIPLICITY? > > I mean, in ev.h says: > # if EV_MULTIPLICITY > /* ... */ > ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated > after each poll */ Look at the #else part, ev_now is available nevertheless (my apps use it, I am quite sure it is there :) > But in ev++.h there was no conditional compilation for ev::now(), that > uses ev_now(). And quite correctly so, as ev_now () is supported regardless of EV_MULTIPLICITY :) -- 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: Disabling the SIGCHLD handler
On Jan 15, 2008 8:17 PM, Marc Lehmann <[EMAIL PROTECTED]> wrote: > On Tue, Jan 15, 2008 at 10:47:33AM -0500, Chris Shoemaker < > [EMAIL PROTECTED]> wrote: > > > handler before creating the process, or before the process exits, only > > > before you poll for more events. > > > > I'm glad we finally agree, in practice at least. > > No, we don't. Your claim was wrong and is wrong. We do not agree the > least. I don't understand why you cannot accept that. > Not to jump into the middle of the conversation here, but I think this is an area where code counts a lot more than discussion. Marc, could you check out the Rubinius code? I know when you looked at Rev you spotted some obvious problems right away. If there's a problem with the way Rubinius is doing SIGCHLD maybe you could correct it and move it on to ev_child. Or, perhaps you'll discover some irreconcilable or otherwise difficult problem. -- Tony Arcieri ClickCaster, Inc. [EMAIL PROTECTED] ___ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev
Re: Disabling the SIGCHLD handler
On Tue, Jan 15, 2008 at 10:47:33AM -0500, Chris Shoemaker <[EMAIL PROTECTED]> wrote: > It's O(N) in the number of child watchers, and runs only upon SIGCHLD. Also, it just occured to me that this is totally misleading: Your algorithm is O(c²) where c is the number of children in the number of waitpid calls, where libev is O(c). If you take into account the number of watchers, then your approach is O(w c²) where w is the number of watchers, while libev's approach is O(w c) with a much smaller constant factor due to the hashing. As an example, with just 50 children, in the worst case, you require over 1200 waitpid calls where libev only requires 100, and each waitpid call, if implemented correctly, would have to check all active watchers in your case (leading to over 3 iterations overall), and only the potentially matching ones with libev (leading to roughly 150 iterations overall). Performance quickly degrades from that point on. It makes sense to implement it that way for you because you are required to emulate a non-event-based API (waitpid) and there is little to do, but punishing programs written in an event-based way makes no sense to me, especially in an event-library: It is only natural that non-event-based approaches might require less efficient algorithms. Sure, 50 children is not typical, but it happens with some regularity, just as 1000 or more file descriptors is not typical, but it happens with some regularity. > Is that really so bad? I'd love to know of a more efficient way, but > efficiency is secondard to correctness, libev *is* correct, it just isn't suitable for emulating waitpid, as it is a generic event library. When talking about correctness, I'd say the correct approach is to deliver data to the registered watchers, and not just some of them. (thinking about all this, I might be able to reduce the number of waitpid calls further). In any case, libev is commited to support event-based programing efficiently, it is not meant to emulate the traditional UNIX api in a different way: if you want waitpid, you know where to find it. -- 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: Disabling the SIGCHLD handler
On Tue, Jan 15, 2008 at 08:28:34PM -0700, Tony Arcieri <[EMAIL PROTECTED]> wrote: > Marc, could you check out the Rubinius code? I know when you looked at Rev > you spotted some obvious problems right away. If there's a problem with the > way Rubinius is doing SIGCHLD maybe you could correct it and move it on to > ev_child. Or, perhaps you'll discover some irreconcilable or otherwise > difficult problem. I do not think I have the time for that: this has nothing to do with libev, so my personal interest is low, and I am very low on time in general. Sorry. (I only looked at Rev to see how one would do that in ruby, out of interest, and because seeing bugs might hint at what could be improved, for example, in the documentation). -- 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 Tue, Jan 15, 2008 at 11:34:41AM -0200, Leandro Lucarella <[EMAIL PROTECTED]> wrote: > > Hmm, the loops are not polymorphic, so the dynamic_cast will not be helpful. > > In any case, is_default == (loop_ == ev_default_loop (0)). > > They are in the patch I sent =) > Just for the fork() and destructors. Oh, horrible. Would it be possible to get rid of that with an explicit (non-dynamic-cast) is_default check? In fact, I could document and commit to ev_loop_fork and ev_loop_destroy working on the default loop as well (they don't at the moment, but its easy to do that), so no polymorphism is needed and all the ideas about loops being as efficient as ev_loop pointers would then become true :) > > If everything *is* inside ev:: that would be fine, but its quite a bit of > > work. Otherwise, I have no hard feelings either way. > > Is not that hard, is a bit of work done once (and it's already done in the > patch ;). So, it's ok for you to expose the entire API in the ev namespace? Absolutely. If you could fine a nice way to hide it from the default namespace this would be even better, but ev.h defines so many macros... > > for various reasons, I would prefer the "_" at the end, but again, I don't > > care much :) > > I'm use to the "_" as a prefix, but I don't care much either and is you > lib, so, I'll use the suffix form ;) Well, the reason is that that the _-namespace is not completely usable by apps and it is easy to stumble over reserved namespace that way, which cannot happen with a trailing _. It doesn't matter in that case, it just explains my general prefernce to do it that way always. > > I wonder why it cannot be simply "loop"? Does it collide with anything? > > Yes, with loop_base& loop(). How about get_loop? I am not being funny, because I would expect loop to be either a mutator (which optionally sets it and this becoems equivalent with a variable), or separate get/set methods. In the end, I'd simply prefer it to be exposed, however, I am not a friend of making getters and setters that are trivial (in my experience, either you have a language that makes variabkles syntactically equivalent to methods (self, javascript...) or you will not want to take the speed hit of a nontrivial setter anyways and thus change caller code on any changes). I cna be convinced otherwise, though, these are just my thoughts. > But if you think is too much trouble, I cant expose the loop (without "_") > pointer directly. I am mostly fine with it, if I cannot convince you with my arguments above, we will do it as you said. > That would only be true if fork can be a macro symbol. I don't know if > this is actually done by any OS but the POSIX standard don't say anything > about fork() being a macro (or even if it's implementation defined) [1] as > it does with other symbols (FD_XXX for instance [2]). Ha! Quoting posix on me! :) http://www.opengroup.org/onlinepubs/95399/functions/xsh_chap02_01.html Any function declared in a header may also be implemented as a macro defined in the header... > > Maybe loop_simpel should rarlly be "loop" if we can get away with it > > without collisions. > > Yes, I thought about it too, but with all that "loop" everywhere I didn't > thought it was a great idea (exactly because the high probability of > colission ;). But once the patch is stabilized I can try to rename it to > loop and see what happens... Well, I think its a wonderful idea, its a loop, it should be called loop :) I dtetes loop_base, if we would need a seperate ype, it should probably be loop_t (which is immensely ugly), so why not settle for "class loop" in conflicts? :) (See above for going with you if this isn't convincing) > > > + inline > > > + loop_default& > > > + default_loop (int flags) > > > + { > > > +static loop_default l (flags); > > > +return l; > > > + } > > > > I my, I am scared at how horrible code that will generate in each > > translation unit (I know, the same thing is done in ev.h, but its still > > ugly :). Maybe leave it up to the user to declare her own loop_default > > object? Or maybe not. > > The problem with that is the lack of a "standard" mechanism to access to > that default loop (for instance, in the watchers contructors to use it as > a default argument). Oh right, the default loop would detroy itself in the destructor. Maybe we shouldn't do that (destroying the default loop, a singleton object, is deeply anti-OO, maybe the right thing is to not do it?) > > > #if EV_MULTIPLICITY > > > - EV_P; > > > + loop_base *_loop; > > > > Thats the only negative thing, as it creates a need to use the ev++.h loop > > wrappers. > > And that is wrong because? I think if you are using ev++.h you'll be > glad to use the loop wrapper =) Sure, but its less flexible, and breaks all my C++ code :) If we could do both, that would certainly be better, no? :) > The problem is not uglier code in watchers. The problem is when you store > an