Re: [RFC] extending ev++.h to add C++ loop wrappers.

2008-01-17 Thread Marc Lehmann
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.

2008-01-17 Thread Leandro Lucarella
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.

2008-01-17 Thread Leandro Lucarella
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.

2008-01-17 Thread Leandro Lucarella
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.

2008-01-17 Thread Leandro Lucarella
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.

2008-01-17 Thread Marc Lehmann
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.

2008-01-17 Thread Marc Lehmann
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.

2008-01-17 Thread Marc Lehmann
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