]> git.llucax.com Git - software/libev.git/commitdiff
document c++ callbacks!
authorroot <root>
Fri, 7 Dec 2007 20:13:08 +0000 (20:13 +0000)
committerroot <root>
Fri, 7 Dec 2007 20:13:08 +0000 (20:13 +0000)
ev++.h
ev.3
ev.html
ev.pod

diff --git a/ev++.h b/ev++.h
index d7b4502bde8d06bc5db233a428705286e0afa1e1..fea0ac170ee85850d318d50d643a8ee5acbf14f9 100644 (file)
--- a/ev++.h
+++ b/ev++.h
@@ -56,10 +56,10 @@ namespace ev {
       (obj->*method) (*self, revents);
     }
 
-    template<void (*function)(watcher &w, int)>
+    template<void (*function)(watcher &w, int), void *data = 0>
     void set ()
     {
-      set_ (0, function_thunk<function>);
+      set_ (data, function_thunk<function>);
     }
 
     template<void (*function)(watcher &w, int)>
diff --git a/ev.3 b/ev.3
index dad4e52daa173fe868b9a7bc3267f84a4334f6b3..4f0017992a9fdfe6828e28351907e5d0f7ac457e 100644 (file)
--- a/ev.3
+++ b/ev.3
@@ -1896,12 +1896,21 @@ To use it,
 \&  #include <ev++.h>
 .Ve
 .PP
-(it is not installed by default). This automatically includes \fIev.h\fR
-and puts all of its definitions (many of them macros) into the global
-namespace. All \*(C+ specific things are put into the \f(CW\*(C`ev\*(C'\fR namespace.
-.PP
-It should support all the same embedding options as \fIev.h\fR, most notably
-\&\f(CW\*(C`EV_MULTIPLICITY\*(C'\fR.
+This automatically includes \fIev.h\fR and puts all of its definitions (many
+of them macros) into the global namespace. All \*(C+ specific things are
+put into the \f(CW\*(C`ev\*(C'\fR namespace. It should support all the same embedding
+options as \fIev.h\fR, most notably \f(CW\*(C`EV_MULTIPLICITY\*(C'\fR.
+.PP
+Care has been taken to keep the overhead low. The only data member added
+to the C\-style watchers is the event loop the watcher is associated with
+(or no additional members at all if you disable \f(CW\*(C`EV_MULTIPLICITY\*(C'\fR when
+embedding libev).
+.PP
+Currently, functions and static and non-static member functions can be
+used as callbacks. Other types should be easy to add as long as they only
+need one additional pointer for context. If you need support for other
+types of functors please contact the author (preferably after implementing
+it).
 .PP
 Here is a list of things available in the \f(CW\*(C`ev\*(C'\fR namespace:
 .ie n .IP """ev::READ""\fR, \f(CW""ev::WRITE"" etc." 4
@@ -1923,21 +1932,61 @@ defines by many implementations.
 .Sp
 All of those classes have these methods:
 .RS 4
-.IP "ev::TYPE::TYPE (object *, object::method *)" 4
-.IX Item "ev::TYPE::TYPE (object *, object::method *)"
+.IP "ev::TYPE::TYPE ()" 4
+.IX Item "ev::TYPE::TYPE ()"
 .PD 0
-.IP "ev::TYPE::TYPE (object *, object::method *, struct ev_loop *)" 4
-.IX Item "ev::TYPE::TYPE (object *, object::method *, struct ev_loop *)"
+.IP "ev::TYPE::TYPE (struct ev_loop *)" 4
+.IX Item "ev::TYPE::TYPE (struct ev_loop *)"
 .IP "ev::TYPE::~TYPE" 4
 .IX Item "ev::TYPE::~TYPE"
 .PD
-The constructor takes a pointer to an object and a method pointer to
-the event handler callback to call in this class. The constructor calls
-\&\f(CW\*(C`ev_init\*(C'\fR for you, which means you have to call the \f(CW\*(C`set\*(C'\fR method
-before starting it. If you do not specify a loop then the constructor
-automatically associates the default loop with this watcher.
+The constructor (optionally) takes an event loop to associate the watcher
+with. If it is omitted, it will use \f(CW\*(C`EV_DEFAULT\*(C'\fR.
+.Sp
+The constructor calls \f(CW\*(C`ev_init\*(C'\fR for you, which means you have to call the
+\&\f(CW\*(C`set\*(C'\fR method before starting it.
+.Sp
+It will not set a callback, however: You have to call the templated \f(CW\*(C`set\*(C'\fR
+method to set a callback before you can start the watcher.
+.Sp
+(The reason why you have to use a method is a limitation in \*(C+ which does
+not allow explicit template arguments for constructors).
 .Sp
 The destructor automatically stops the watcher if it is active.
+.IP "w\->set<class, &class::method> (object *)" 4
+.IX Item "w->set<class, &class::method> (object *)"
+This method sets the callback method to call. The method has to have a
+signature of \f(CW\*(C`void (*)(ev_TYPE &, int)\*(C'\fR, it receives the watcher as
+first argument and the \f(CW\*(C`revents\*(C'\fR as second. The object must be given as
+parameter and is stored in the \f(CW\*(C`data\*(C'\fR member of the watcher.
+.Sp
+This method synthesizes efficient thunking code to call your method from
+the C callback that libev requires. If your compiler can inline your
+callback (i.e. it is visible to it at the place of the \f(CW\*(C`set\*(C'\fR call and
+your compiler is good :), then the method will be fully inlined into the
+thunking function, making it as fast as a direct C callback.
+.Sp
+Example: simple class declaration and watcher initialisation
+.Sp
+.Vb 4
+\&  struct myclass
+\&  {
+\&    void io_cb (ev::io &w, int revents) { }
+\&  }
+.Ve
+.Sp
+.Vb 3
+\&  myclass obj;
+\&  ev::io iow;
+\&  iow.set <myclass, &myclass::io_cb> (&obj);
+.Ve
+.IP "w\->set (void (*function)(watcher &w, int), void *data = 0)" 4
+.IX Item "w->set (void (*function)(watcher &w, int), void *data = 0)"
+Also sets a callback, but uses a static method or plain function as
+callback. The optional \f(CW\*(C`data\*(C'\fR argument will be stored in the watcher's
+\&\f(CW\*(C`data\*(C'\fR member and is free for you to use.
+.Sp
+See the method\-\f(CW\*(C`set\*(C'\fR above for more details.
 .IP "w\->set (struct ev_loop *)" 4
 .IX Item "w->set (struct ev_loop *)"
 Associates a different \f(CW\*(C`struct ev_loop\*(C'\fR with this watcher. You can only
@@ -1945,12 +1994,13 @@ do this when the watcher is inactive (and not pending either).
 .IP "w\->set ([args])" 4
 .IX Item "w->set ([args])"
 Basically the same as \f(CW\*(C`ev_TYPE_set\*(C'\fR, with the same args. Must be
-called at least once.  Unlike the C counterpart, an active watcher gets
-automatically stopped and restarted.
+called at least once. Unlike the C counterpart, an active watcher gets
+automatically stopped and restarted when reconfiguring it with this
+method.
 .IP "w\->start ()" 4
 .IX Item "w->start ()"
-Starts the watcher. Note that there is no \f(CW\*(C`loop\*(C'\fR argument as the
-constructor already takes the loop.
+Starts the watcher. Note that there is no \f(CW\*(C`loop\*(C'\fR argument, as the
+constructor already stores the event loop.
 .IP "w\->stop ()" 4
 .IX Item "w->stop ()"
 Stops the watcher if it is active. Again, no \f(CW\*(C`loop\*(C'\fR argument.
@@ -1986,11 +2036,14 @@ the constructor.
 \&  }
 .Ve
 .PP
-.Vb 6
+.Vb 4
 \&  myclass::myclass (int fd)
-\&  : io   (this, &myclass::io_cb),
-\&    idle (this, &myclass::idle_cb)
 \&  {
+\&    io  .set <myclass, &myclass::io_cb  > (this);
+\&    idle.set <myclass, &myclass::idle_cb> (this);
+.Ve
+.PP
+.Vb 2
 \&    io.start (fd, ev::READ);
 \&  }
 .Ve
diff --git a/ev.html b/ev.html
index 63ddf3b8988edf00afd61acd21c248d79d9d8c29..efd79daabadbde8eca31359ef91273b07847fca9 100644 (file)
--- a/ev.html
+++ b/ev.html
@@ -6,7 +6,7 @@
        <meta name="description" content="Pod documentation for libev" />
        <meta name="inputfile" content="&lt;standard input&gt;" />
        <meta name="outputfile" content="&lt;standard output&gt;" />
-       <meta name="created" content="Fri Dec  7 20:23:46 2007" />
+       <meta name="created" content="Fri Dec  7 21:13:07 2007" />
        <meta name="generator" content="Pod::Xhtml 1.57" />
 <link rel="stylesheet" href="http://res.tst.eu/pod.css"/></head>
 <body>
@@ -1738,11 +1738,19 @@ the callback model to a model using method callbacks on objects.</p>
 <pre>  #include &lt;ev++.h&gt;
 
 </pre>
-<p>(it is not installed by default). This automatically includes <cite>ev.h</cite>
-and puts all of its definitions (many of them macros) into the global
-namespace. All C++ specific things are put into the <code>ev</code> namespace.</p>
-<p>It should support all the same embedding options as <cite>ev.h</cite>, most notably
-<code>EV_MULTIPLICITY</code>.</p>
+<p>This automatically includes <cite>ev.h</cite> and puts all of its definitions (many
+of them macros) into the global namespace. All C++ specific things are
+put into the <code>ev</code> namespace. It should support all the same embedding
+options as <cite>ev.h</cite>, most notably <code>EV_MULTIPLICITY</code>.</p>
+<p>Care has been taken to keep the overhead low. The only data member added
+to the C-style watchers is the event loop the watcher is associated with
+(or no additional members at all if you disable <code>EV_MULTIPLICITY</code> when
+embedding libev).</p>
+<p>Currently, functions and static and non-static member functions can be
+used as callbacks. Other types should be easy to add as long as they only
+need one additional pointer for context. If you need support for other
+types of functors please contact the author (preferably after implementing
+it).</p>
 <p>Here is a list of things available in the <code>ev</code> namespace:</p>
 <dl>
        <dt><code>ev::READ</code>, <code>ev::WRITE</code> etc.</dt>
@@ -1763,17 +1771,50 @@ defines by many implementations.</p>
                <p>All of those classes have these methods:</p>
                <p>
                        <dl>
-                               <dt>ev::TYPE::TYPE (object *, object::method *)</dt>
-                               <dt>ev::TYPE::TYPE (object *, object::method *, struct ev_loop *)</dt>
+                               <dt>ev::TYPE::TYPE ()</dt>
+                               <dt>ev::TYPE::TYPE (struct ev_loop *)</dt>
                                <dt>ev::TYPE::~TYPE</dt>
                                <dd>
-                                       <p>The constructor takes a pointer to an object and a method pointer to
-the event handler callback to call in this class. The constructor calls
-<code>ev_init</code> for you, which means you have to call the <code>set</code> method
-before starting it. If you do not specify a loop then the constructor
-automatically associates the default loop with this watcher.</p>
+                                       <p>The constructor (optionally) takes an event loop to associate the watcher
+with. If it is omitted, it will use <code>EV_DEFAULT</code>.</p>
+                                       <p>The constructor calls <code>ev_init</code> for you, which means you have to call the
+<code>set</code> method before starting it.</p>
+                                       <p>It will not set a callback, however: You have to call the templated <code>set</code>
+method to set a callback before you can start the watcher.</p>
+                                       <p>(The reason why you have to use a method is a limitation in C++ which does
+not allow explicit template arguments for constructors).</p>
                                        <p>The destructor automatically stops the watcher if it is active.</p>
                                </dd>
+                               <dt>w-&gt;set&lt;class, &amp;class::method&gt; (object *)</dt>
+                               <dd>
+                                       <p>This method sets the callback method to call. The method has to have a
+signature of <code>void (*)(ev_TYPE &amp;, int)</code>, it receives the watcher as
+first argument and the <code>revents</code> as second. The object must be given as
+parameter and is stored in the <code>data</code> member of the watcher.</p>
+                                       <p>This method synthesizes efficient thunking code to call your method from
+the C callback that libev requires. If your compiler can inline your
+callback (i.e. it is visible to it at the place of the <code>set</code> call and
+your compiler is good :), then the method will be fully inlined into the
+thunking function, making it as fast as a direct C callback.</p>
+                                       <p>Example: simple class declaration and watcher initialisation</p>
+<pre>  struct myclass
+  {
+    void io_cb (ev::io &amp;w, int revents) { }
+  }
+
+  myclass obj;
+  ev::io iow;
+  iow.set &lt;myclass, &amp;myclass::io_cb&gt; (&amp;obj);
+
+</pre>
+                               </dd>
+                               <dt>w-&gt;set (void (*function)(watcher &amp;w, int), void *data = 0)</dt>
+                               <dd>
+                                       <p>Also sets a callback, but uses a static method or plain function as
+callback. The optional <code>data</code> argument will be stored in the watcher's
+<code>data</code> member and is free for you to use.</p>
+                                       <p>See the method-<code>set</code> above for more details.</p>
+                               </dd>
                                <dt>w-&gt;set (struct ev_loop *)</dt>
                                <dd>
                                        <p>Associates a different <code>struct ev_loop</code> with this watcher. You can only
@@ -1782,13 +1823,14 @@ do this when the watcher is inactive (and not pending either).</p>
                                <dt>w-&gt;set ([args])</dt>
                                <dd>
                                        <p>Basically the same as <code>ev_TYPE_set</code>, with the same args. Must be
-called at least once.  Unlike the C counterpart, an active watcher gets
-automatically stopped and restarted.</p>
+called at least once. Unlike the C counterpart, an active watcher gets
+automatically stopped and restarted when reconfiguring it with this
+method.</p>
                                </dd>
                                <dt>w-&gt;start ()</dt>
                                <dd>
-                                       <p>Starts the watcher. Note that there is no <code>loop</code> argument as the
-constructor already takes the loop.</p>
+                                       <p>Starts the watcher. Note that there is no <code>loop</code> argument, as the
+constructor already stores the event loop.</p>
                                </dd>
                                <dt>w-&gt;stop ()</dt>
                                <dd>
@@ -1822,9 +1864,10 @@ the constructor.</p>
   }
 
   myclass::myclass (int fd)
-  : io   (this, &amp;myclass::io_cb),
-    idle (this, &amp;myclass::idle_cb)
   {
+    io  .set &lt;myclass, &amp;myclass::io_cb  &gt; (this);
+    idle.set &lt;myclass, &amp;myclass::idle_cb&gt; (this);
+
     io.start (fd, ev::READ);
   }
 
diff --git a/ev.pod b/ev.pod
index 14999b34e04047b688ad10593adfeb0cf818e8a3..c02aca2d2775754190cbe205c5e5217327edbfa8 100644 (file)
--- a/ev.pod
+++ b/ev.pod
@@ -1746,12 +1746,21 @@ To use it,
    
   #include <ev++.h>
 
-(it is not installed by default). This automatically includes F<ev.h>
-and puts all of its definitions (many of them macros) into the global
-namespace. All C++ specific things are put into the C<ev> namespace.
-
-It should support all the same embedding options as F<ev.h>, most notably
-C<EV_MULTIPLICITY>.
+This automatically includes F<ev.h> and puts all of its definitions (many
+of them macros) into the global namespace. All C++ specific things are
+put into the C<ev> namespace. It should support all the same embedding
+options as F<ev.h>, most notably C<EV_MULTIPLICITY>.
+
+Care has been taken to keep the overhead low. The only data member added
+to the C-style watchers is the event loop the watcher is associated with
+(or no additional members at all if you disable C<EV_MULTIPLICITY> when
+embedding libev).
+
+Currently, functions and static and non-static member functions can be
+used as callbacks. Other types should be easy to add as long as they only
+need one additional pointer for context. If you need support for other
+types of functors please contact the author (preferably after implementing
+it).
 
 Here is a list of things available in the C<ev> namespace:
 
@@ -1777,20 +1786,58 @@ All of those classes have these methods:
 
 =over 4
 
-=item ev::TYPE::TYPE (object *, object::method *)
+=item ev::TYPE::TYPE ()
 
-=item ev::TYPE::TYPE (object *, object::method *, struct ev_loop *)
+=item ev::TYPE::TYPE (struct ev_loop *)
 
 =item ev::TYPE::~TYPE
 
-The constructor takes a pointer to an object and a method pointer to
-the event handler callback to call in this class. The constructor calls
-C<ev_init> for you, which means you have to call the C<set> method
-before starting it. If you do not specify a loop then the constructor
-automatically associates the default loop with this watcher.
+The constructor (optionally) takes an event loop to associate the watcher
+with. If it is omitted, it will use C<EV_DEFAULT>.
+
+The constructor calls C<ev_init> for you, which means you have to call the
+C<set> method before starting it.
+
+It will not set a callback, however: You have to call the templated C<set>
+method to set a callback before you can start the watcher.
+
+(The reason why you have to use a method is a limitation in C++ which does
+not allow explicit template arguments for constructors).
 
 The destructor automatically stops the watcher if it is active.
 
+=item w->set<class, &class::method> (object *)
+
+This method sets the callback method to call. The method has to have a
+signature of C<void (*)(ev_TYPE &, int)>, it receives the watcher as
+first argument and the C<revents> as second. The object must be given as
+parameter and is stored in the C<data> member of the watcher.
+
+This method synthesizes efficient thunking code to call your method from
+the C callback that libev requires. If your compiler can inline your
+callback (i.e. it is visible to it at the place of the C<set> call and
+your compiler is good :), then the method will be fully inlined into the
+thunking function, making it as fast as a direct C callback.
+
+Example: simple class declaration and watcher initialisation
+
+  struct myclass
+  {
+    void io_cb (ev::io &w, int revents) { }
+  }
+
+  myclass obj;
+  ev::io iow;
+  iow.set <myclass, &myclass::io_cb> (&obj);
+
+=item w->set (void (*function)(watcher &w, int), void *data = 0)
+
+Also sets a callback, but uses a static method or plain function as
+callback. The optional C<data> argument will be stored in the watcher's
+C<data> member and is free for you to use.
+
+See the method-C<set> above for more details.
+
 =item w->set (struct ev_loop *)
 
 Associates a different C<struct ev_loop> with this watcher. You can only
@@ -1799,13 +1846,14 @@ do this when the watcher is inactive (and not pending either).
 =item w->set ([args])
 
 Basically the same as C<ev_TYPE_set>, with the same args. Must be
-called at least once.  Unlike the C counterpart, an active watcher gets
-automatically stopped and restarted.
+called at least once. Unlike the C counterpart, an active watcher gets
+automatically stopped and restarted when reconfiguring it with this
+method.
 
 =item w->start ()
 
-Starts the watcher. Note that there is no C<loop> argument as the
-constructor already takes the loop.
+Starts the watcher. Note that there is no C<loop> argument, as the
+constructor already stores the event loop.
 
 =item w->stop ()
 
@@ -1840,9 +1888,10 @@ the constructor.
   }
 
   myclass::myclass (int fd)
-  : io   (this, &myclass::io_cb),
-    idle (this, &myclass::idle_cb)
   {
+    io  .set <myclass, &myclass::io_cb  > (this);
+    idle.set <myclass, &myclass::idle_cb> (this);
+
     io.start (fd, ev::READ);
   }