Leandro Lucarella, el 14 de enero a las 15:37 me escribiste:
> Hi, following the "C++ APIs" thread [1], I came to the conclusion that I
> didn't like the "whole new wrapper" approach, because it didn't provide
> anything ev++.h have (or it would be too hard to implement, and I didn't
> thought it worth the effort, because there were too little benefit).
>
> I tried the full wrapper approach, with the goal of making a "C++
> binding", trying to hide all the C API (including ev.h only in the cpp
> files) but it didn't worked, and add another lib to link to, and lost the
> embedding capabilities.
>
> So I decided to improve ev++.h, at least as I see it =)
>
> Attached it a *rough* patch, that can be used as in the example file
> test.cpp. There are a few issues I'm not happy about, so I want to know
> 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 =)
>
> What I'm not crazy about is:
> 1) Storing a ev_loop* in the watchers, instead of a loop_ref. But I'm
> affraid that not doing so could break some existing code. This leads to
> the ugly "ev::loop_ref (w.loop).stop (ev::ALL);" in the example (if a
> loop_ref could be stored, it looked like "w.loop.stop (ev::ALL);")
To implement this point, 2) is necessary if we don't want to be needed to
explicitly set every watcher's loop, because the lack of a "standard" way
to get the default loop.
> 2) The default loop handling. Now a default loop has to be instantiated,
> and a simple check is done to ensure just one default loop exists, but
> with an ugly hack (via de default_loop_created() function) to avoid the
> need of object code (a class static variable would need it).
> This model is a little different to the C API, because you can't get
> the default loop from anywhere (at least not in the same way, but you
> can do it with something like loop_ref(ev_default_loop(0)), but it's
> not very nice). The easiest way to do that is making the default_loop a
> global variable, but it's a "userspace" hack.
> I thought of making a more singleton-approach (using a function to
> get/create the loop object if it doesn't exist, for example
> "get_default_loop(int flags = 0) { static default_loop* l = 0; if (!l) l =
> new default_loop(flags); return l; }" but this way you have to
> explicitly free the default loop). Now that I see this, maybe it could
> be "elegantly" solved using a reference:
> default_loop&
> get_default_loop(int flags = 0)
> {
> static default_loop l(flags);
> return l;
> }
> (class names could be rearranged to name this funtion default_loop()
> and the class loop_default, for example, to be more C API-consistent)
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.
--
Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/
----------------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------------
PADRES DENUNCIAN QUE SU HIJA SE ESCAPO CON UN PARAGUAYITO
-- Crónica TV
Author: Leandro Lucarella <[EMAIL PROTECTED]>
Date: Mon Jan 14 14:15:16 2008 -0200
Enforce singleton-ness of the default loop by using a function to access it.
diff --git a/ev++.h b/ev++.h
index 51051fb..282fcf0 100644
--- a/ev++.h
+++ b/ev++.h
@@ -82,12 +82,6 @@ namespace ev {
: std::runtime_error("loop can't be initialized") {}
};
- struct already_created: std::logic_error
- {
- bad_loop()
- : std::runtime_error("there's already a default loop instantiated") {}
- };
-
extern "C"
{
extern struct ev_loop *ev_default_loop_ptr;
@@ -186,61 +180,66 @@ namespace ev {
};
#if EV_MULTIPLICITY
- struct simple_loop: loop_ref
+ struct loop_simple: loop_ref
{
- simple_loop (unsigned int flags = AUTO) throw (bad_loop)
+ loop_simple (unsigned int flags = AUTO) throw (bad_loop)
: loop_ref (ev_loop_new (flags))
{
}
- ~simple_loop () throw ()
+ ~loop_simple () throw ()
{
ev_loop_destroy (EV_A);
}
private:
- simple_loop (const simple_loop &);
+ loop_simple (const loop_simple &);
- simple_loop & operator= (const simple_loop &);
+ loop_simple & operator= (const loop_simple &);
};
#endif
- bool default_loop_created (int created = -1)
- {
- static bool is_created = false;
- if (created != -1)
- is_created = created;
- return is_created;
- }
+ struct loop_default;
+
+ loop_default&
+ default_loop (int flags = 0);
- struct default_loop: loop_ref
+ struct loop_default: loop_ref
{
- default_loop (unsigned int flags = AUTO) throw (bad_loop, already_created)
- : loop_ref (ev_default_loop (flags))
+ ~loop_default () throw ()
{
- if (default_loop_created ())
- throw already_created ();
- default_loop_created (true);
+ ev_default_destroy ();
}
- ~default_loop () throw ()
+ private:
+
+ loop_default (unsigned int flags = AUTO) throw (bad_loop)
+ : loop_ref (ev_default_loop (flags))
{
- default_loop_created (false);
- ev_default_destroy ();
}
- private:
+ loop_default ();
- default_loop (const default_loop &);
+ loop_default (const loop_default &);
- default_loop & operator= (const default_loop &);
+ loop_default & operator= (const loop_default &);
+
+ friend loop_default& default_loop (int flags);
};
+ inline
+ loop_default&
+ default_loop (int flags)
+ {
+ static loop_default l (flags);
+ return l;
+ }
+
template<class ev_watcher, class watcher>
struct base : ev_watcher
{
#include <ev++.h>
#include <stdio.h>
#include <unistd.h>
/* called when data readable on stdin */
struct myclass
{
void io_cb (ev::io &w, int revents)
{
char buff[BUFSIZ];
int r = read (w.fd, buff, BUFSIZ);
printf ("stdin ready, %d bytes read: %s", r, buff);
w.stop (); /* just a syntax example */
//ev::loop_ref (w.loop).stop (ev::ALL); /* leave all loop calls */
ev::default_loop ().stop (); // just to demostrate the usage
// of the free function a la C-API.
}
};
int
main (void)
{
// Needs explicit initialization via a function call which is not as
// clear as an object instantiation IMHO
ev::default_loop ();
myclass obj;
ev::io iow;
iow.set <myclass, &myclass::io_cb> (&obj);
/* start watching fd 0 for reading (default) */
iow.start (/*STDIN_FILENO*/ 0);
/* loop till timeout or data ready */
ev::default_loop ().start ();
return 0;
}
_______________________________________________
libev mailing list
[email protected]
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev