summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changes6
-rw-r--r--ev.322
-rw-r--r--ev.c6
-rw-r--r--ev.h2
-rw-r--r--ev.pod12
-rw-r--r--event.c33
-rw-r--r--event.h11
7 files changed, 68 insertions, 24 deletions
diff --git a/Changes b/Changes
index f07ecdd..34d7080 100644
--- a/Changes
+++ b/Changes
@@ -7,7 +7,11 @@ TODO: document WSA_EV_USE_SOCKET in win32 part
TODO: ^ OR use WSASend/WSARecv on the handle, which always works
TODO: use __OPTIMIZE__ or __OPTIMIZE_SIZE__?
-TODO: Jeff Davey libev patch
+ - fix event_base_loop return code, add event_get_callback, event_base_new,
+ event_base_get_method calls to improve libevent 1.x emulation and add
+ some libevent 2.x funcitonality (based on a patch by Jeff Davey).
+ - ev_run now returns a boolean status (true meaning watchers are
+ still active).
- ev_once: undef EV_ERROR in ev_kqueue.c, to avoid clashing with
libev's EV_ERROR (reported by 191919).
- (ecb) add memory fence support for xlC (Darin McBride).
diff --git a/ev.3 b/ev.3
index 2721ca3..36a39b5 100644
--- a/ev.3
+++ b/ev.3
@@ -124,7 +124,7 @@
.\" ========================================================================
.\"
.IX Title "LIBEV 3"
-.TH LIBEV 3 "2012-03-23" "libev-4.11" "libev - high performance full featured event loop"
+.TH LIBEV 3 "2012-04-03" "libev-4.11" "libev - high performance full featured event loop"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@@ -687,9 +687,9 @@ It scales in the same way as the epoll backend, but the interface to the
kernel is more efficient (which says nothing about its actual speed, of
course). While stopping, setting and starting an I/O watcher does never
cause an extra system call as with \f(CW\*(C`EVBACKEND_EPOLL\*(C'\fR, it still adds up to
-two event changes per incident. Support for \f(CW\*(C`fork ()\*(C'\fR is very bad (but
-sane, unlike epoll) and it drops fds silently in similarly hard-to-detect
-cases
+two event changes per incident. Support for \f(CW\*(C`fork ()\*(C'\fR is very bad (you
+might have to leak fd's on fork, but it's more sane than epoll) and it
+drops fds silently in similarly hard-to-detect cases
.Sp
This backend usually performs well under most conditions.
.Sp
@@ -911,18 +911,22 @@ without a previous call to \f(CW\*(C`ev_suspend\*(C'\fR.
.Sp
Calling \f(CW\*(C`ev_suspend\*(C'\fR/\f(CW\*(C`ev_resume\*(C'\fR has the side effect of updating the
event loop time (see \f(CW\*(C`ev_now_update\*(C'\fR).
-.IP "ev_run (loop, int flags)" 4
-.IX Item "ev_run (loop, int flags)"
+.IP "bool ev_run (loop, int flags)" 4
+.IX Item "bool ev_run (loop, int flags)"
Finally, this is it, the event handler. This function usually is called
after you have initialised all your watchers and you want to start
handling events. It will ask the operating system for any new events, call
-the watcher callbacks, an then repeat the whole process indefinitely: This
+the watcher callbacks, and then repeat the whole process indefinitely: This
is why event loops are called \fIloops\fR.
.Sp
If the flags argument is specified as \f(CW0\fR, it will keep handling events
until either no event watchers are active anymore or \f(CW\*(C`ev_break\*(C'\fR was
called.
.Sp
+The return value is false if there are no more active watchers (which
+usually means \*(L"all jobs done\*(R" or \*(L"deadlock\*(R"), and true in all other cases
+(which usually means " you should call \f(CW\*(C`ev_run\*(C'\fR again").
+.Sp
Please note that an explicit \f(CW\*(C`ev_break\*(C'\fR is usually better than
relying on all watchers to be stopped when deciding when a program has
finished (especially in interactive programs), but having a program
@@ -930,8 +934,8 @@ that automatically loops as long as it has to and no longer by virtue
of relying on its watchers stopping correctly, that is truly a thing of
beauty.
.Sp
-This function is also \fImostly\fR exception-safe \- you can break out of
-a \f(CW\*(C`ev_run\*(C'\fR call by calling \f(CW\*(C`longjmp\*(C'\fR in a callback, throwing a \*(C+
+This function is \fImostly\fR exception-safe \- you can break out of a
+\&\f(CW\*(C`ev_run\*(C'\fR call by calling \f(CW\*(C`longjmp\*(C'\fR in a callback, throwing a \*(C+
exception and so on. This does not decrement the \f(CW\*(C`ev_depth\*(C'\fR value, nor
will it clear any outstanding \f(CW\*(C`EVBREAK_ONE\*(C'\fR breaks.
.Sp
diff --git a/ev.c b/ev.c
index d61180b..15c58d5 100644
--- a/ev.c
+++ b/ev.c
@@ -1,7 +1,7 @@
/*
* libev event processing core, watcher management
*
- * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
+ * Copyright (c) 2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
@@ -2932,7 +2932,7 @@ time_update (EV_P_ ev_tstamp max_block)
}
}
-void
+int
ev_run (EV_P_ int flags)
{
#if EV_FEATURE_API
@@ -3099,6 +3099,8 @@ ev_run (EV_P_ int flags)
#if EV_FEATURE_API
--loop_depth;
#endif
+
+ return activecnt;
}
void
diff --git a/ev.h b/ev.h
index 54b4f00..335e341 100644
--- a/ev.h
+++ b/ev.h
@@ -624,7 +624,7 @@ enum {
};
#if EV_PROTOTYPES
-EV_API_DECL void ev_run (EV_P_ int flags EV_CPP (= 0));
+EV_API_DECL int ev_run (EV_P_ int flags EV_CPP (= 0));
EV_API_DECL void ev_break (EV_P_ int how EV_CPP (= EVBREAK_ONE)); /* break out of the loop */
/*
diff --git a/ev.pod b/ev.pod
index 9ea2cd6..e185fa5 100644
--- a/ev.pod
+++ b/ev.pod
@@ -794,18 +794,22 @@ without a previous call to C<ev_suspend>.
Calling C<ev_suspend>/C<ev_resume> has the side effect of updating the
event loop time (see C<ev_now_update>).
-=item ev_run (loop, int flags)
+=item bool ev_run (loop, int flags)
Finally, this is it, the event handler. This function usually is called
after you have initialised all your watchers and you want to start
handling events. It will ask the operating system for any new events, call
-the watcher callbacks, an then repeat the whole process indefinitely: This
+the watcher callbacks, and then repeat the whole process indefinitely: This
is why event loops are called I<loops>.
If the flags argument is specified as C<0>, it will keep handling events
until either no event watchers are active anymore or C<ev_break> was
called.
+The return value is false if there are no more active watchers (which
+usually means "all jobs done" or "deadlock"), and true in all other cases
+(which usually means " you should call C<ev_run> again").
+
Please note that an explicit C<ev_break> is usually better than
relying on all watchers to be stopped when deciding when a program has
finished (especially in interactive programs), but having a program
@@ -813,8 +817,8 @@ that automatically loops as long as it has to and no longer by virtue
of relying on its watchers stopping correctly, that is truly a thing of
beauty.
-This function is also I<mostly> exception-safe - you can break out of
-a C<ev_run> call by calling C<longjmp> in a callback, throwing a C++
+This function is I<mostly> exception-safe - you can break out of a
+C<ev_run> call by calling C<longjmp> in a callback, throwing a C++
exception and so on. This does not decrement the C<ev_depth> value, nor
will it clear any outstanding C<EVBREAK_ONE> breaks.
diff --git a/event.c b/event.c
index 97b4cbe..5586cd3 100644
--- a/event.c
+++ b/event.c
@@ -78,13 +78,15 @@ ev_tv_get (struct timeval *tv)
#define EVENT_STRINGIFY(s) # s
#define EVENT_VERSION(a,b) EVENT_STRINGIFY (a) "." EVENT_STRINGIFY (b)
-const char *event_get_version (void)
+const char *
+event_get_version (void)
{
/* returns ABI, not API or library, version */
return EVENT_VERSION (EV_VERSION_MAJOR, EV_VERSION_MINOR);
}
-const char *event_get_method (void)
+const char *
+event_get_method (void)
{
return "libev";
}
@@ -105,6 +107,23 @@ void *event_init (void)
return ev_x_cur;
}
+const char *
+event_base_get_method (const struct event_base *base)
+{
+ return "libev";
+}
+
+struct event_base *
+event_base_new (void)
+{
+#if EV_MULTIPLICITY
+ return (struct event_base *)ev_loop_new (EVFLAG_AUTO);
+#else
+ assert (("libev: multiple event bases not supported when not compiled with EV_MULTIPLICITY"));
+ return NULL;
+#endif
+}
+
void event_base_free (struct event_base *base)
{
dLOOPbase;
@@ -137,6 +156,12 @@ int event_loopexit (struct timeval *tv)
return event_base_loopexit (ev_x_cur, tv);
}
+event_callback_fn event_get_callback
+(const struct event *ev)
+{
+ return ev->ev_callback;
+}
+
static void
ev_x_cb (struct event *ev, int revents)
{
@@ -332,9 +357,7 @@ int event_base_loop (struct event_base *base, int flags)
{
dLOOPbase;
- ev_run (EV_A_ flags);
-
- return 0;
+ return !ev_run (EV_A_ flags);
}
int event_base_dispatch (struct event_base *base)
diff --git a/event.h b/event.h
index 10ff05a..aa81928 100644
--- a/event.h
+++ b/event.h
@@ -1,7 +1,7 @@
/*
* libevent compatibility header, only core events supported
*
- * Copyright (c) 2007,2008,2010 Marc Alexander Lehmann <libev@schmorp.de>
+ * Copyright (c) 2007,2008,2010,2012 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
@@ -75,6 +75,8 @@ struct event_base;
#define EVLIST_INTERNAL 0x10
#define EVLIST_INIT 0x80
+typedef void (*event_callback_fn)(int, short, void *);
+
struct event
{
/* libev watchers we map onto */
@@ -86,7 +88,7 @@ struct event
/* compatibility slots */
struct event_base *ev_base;
- void (*ev_callback)(int, short, void *arg);
+ event_callback_fn ev_callback;
void *ev_arg;
int ev_fd;
int ev_pri;
@@ -95,9 +97,12 @@ struct event
short ev_events;
};
+event_callback_fn event_get_callback (const struct event *ev);
+
#define EV_READ EV_READ
#define EV_WRITE EV_WRITE
#define EV_PERSIST 0x10
+#define EV_ET 0x20 /* nop */
#define EVENT_SIGNAL(ev) ((int) (ev)->ev_fd)
#define EVENT_FD(ev) ((int) (ev)->ev_fd)
@@ -152,6 +157,8 @@ int event_pending (struct event *ev, short, struct timeval *tv);
int event_priority_init (int npri);
int event_priority_set (struct event *ev, int pri);
+struct event_base *event_base_new (void);
+const char *event_base_get_method (const struct event_base *);
int event_base_set (struct event_base *base, struct event *ev);
int event_base_loop (struct event_base *base, int);
int event_base_loopexit (struct event_base *base, struct timeval *tv);