summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ev.c12
-rw-r--r--ev.h1
-rw-r--r--ev.pod17
3 files changed, 26 insertions, 4 deletions
diff --git a/ev.c b/ev.c
index 82de10f..a6f414f 100644
--- a/ev.c
+++ b/ev.c
@@ -1842,6 +1842,18 @@ ev_invoke (EV_P_ void *w, int revents)
EV_CB_INVOKE ((W)w, revents);
}
+unsigned int
+ev_pending_count (EV_P)
+{
+ int pri;
+ unsigned int count = 0;
+
+ for (pri = NUMPRI; pri--; )
+ count += pendingcnt [pri];
+
+ return count;
+}
+
void noinline
ev_invoke_pending (EV_P)
{
diff --git a/ev.h b/ev.h
index a40528c..0d00f0b 100644
--- a/ev.h
+++ b/ev.h
@@ -553,6 +553,7 @@ void *ev_userdata (EV_P);
void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P));
void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P));
+unsigned int ev_pending_count (EV_P); /* number of pending events, if any */
void ev_invoke_pending (EV_P); /* invoke all pending watchers */
/*
diff --git a/ev.pod b/ev.pod
index 0e32388..ec747e8 100644
--- a/ev.pod
+++ b/ev.pod
@@ -864,6 +864,11 @@ This call will simply invoke all pending watchers while resetting their
pending state. Normally, C<ev_loop> does this automatically when required,
but when overriding the invoke callback this call comes handy.
+=item int ev_pending_count (loop)
+
+Returns the number of pending watchers - zero indicates that no watchers
+are pending.
+
=item ev_set_invoke_pending_cb (loop, void (*invoke_pending_cb)(EV_P))
This overrides the invoke pending functionality of the loop: Instead of
@@ -4030,16 +4035,20 @@ into C<ev_loop>:
Instead of invoking all pending watchers, the C<l_invoke> callback will
signal the main thread via some unspecified mechanism (signals? pipe
writes? C<Async::Interrupt>?) and then waits until all pending watchers
-have been called:
+have been called (in a while loop because a) spurious wakeups are possible
+and b) skipping inter-thread-communication when there are no pending
+watchers is very beneficial):
static void
l_invoke (EV_P)
{
userdata *u = ev_userdata (EV_A);
- wake_up_other_thread_in_some_magic_or_not_so_magic_way ();
-
- pthread_cond_wait (&u->invoke_cv, &u->lock);
+ while (ev_pending_count (EV_A))
+ {
+ wake_up_other_thread_in_some_magic_or_not_so_magic_way ();
+ pthread_cond_wait (&u->invoke_cv, &u->lock);
+ }
}
Now, whenever the main thread gets told to invoke pending watchers, it