Browse Source

*** empty log message ***

master
Marc Alexander Lehmann 13 years ago
parent
commit
cacd28f5a7
  1. 70
      ev.h
  2. 101
      ev.pod

70
ev.h

@ -530,43 +530,43 @@ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revent
ev_set_cb ((ev), cb_); \
} while (0)
#define ev_io_set(ev,fd_,events_) do { (ev)->fd = (fd_); (ev)->events = (events_) | EV_IOFDSET; } while (0)
#define ev_timer_set(ev,after_,repeat_) do { ((ev_watcher_time *)(ev))->at = (after_); (ev)->repeat = (repeat_); } while (0)
#define ev_periodic_set(ev,ofs_,ival_,res_) do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb= (res_); } while (0)
#define ev_signal_set(ev,signum_) do { (ev)->signum = (signum_); } while (0)
#define ev_child_set(ev,pid_,trace_) do { (ev)->pid = (pid_); (ev)->flags = !!(trace_); } while (0)
#define ev_stat_set(ev,path_,interval_) do { (ev)->path = (path_); (ev)->interval = (interval_); (ev)->wd = -2; } while (0)
#define ev_idle_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_prepare_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_check_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_embed_set(ev,other_) do { (ev)->other = (other_); } while (0)
#define ev_fork_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_async_set(ev) do { (ev)->sent = 0; } while (0)
#define ev_io_init(ev,cb,fd,events) do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)
#define ev_timer_init(ev,cb,after,repeat) do { ev_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0)
#define ev_periodic_init(ev,cb,at,ival,res) do { ev_init ((ev), (cb)); ev_periodic_set ((ev),(at),(ival),(res)); } while (0)
#define ev_signal_init(ev,cb,signum) do { ev_init ((ev), (cb)); ev_signal_set ((ev), (signum)); } while (0)
#define ev_child_init(ev,cb,pid,trace) do { ev_init ((ev), (cb)); ev_child_set ((ev),(pid),(trace)); } while (0)
#define ev_stat_init(ev,cb,path,interval) do { ev_init ((ev), (cb)); ev_stat_set ((ev),(path),(interval)); } while (0)
#define ev_idle_init(ev,cb) do { ev_init ((ev), (cb)); ev_idle_set ((ev)); } while (0)
#define ev_prepare_init(ev,cb) do { ev_init ((ev), (cb)); ev_prepare_set ((ev)); } while (0)
#define ev_check_init(ev,cb) do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0)
#define ev_embed_init(ev,cb,other) do { ev_init ((ev), (cb)); ev_embed_set ((ev),(other)); } while (0)
#define ev_fork_init(ev,cb) do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0)
#define ev_async_init(ev,cb) do { ev_init ((ev), (cb)); ev_async_set ((ev)); } while (0)
#define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */
#define ev_is_active(ev) (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */
#define ev_priority(ev) ((((ev_watcher *)(void *)(ev))->priority) + 0)
#define ev_cb(ev) (ev)->cb /* rw */
#define ev_set_priority(ev,pri) ((ev_watcher *)(void *)(ev))->priority = (pri)
#define ev_periodic_at(ev) (((ev_watcher_time *)(ev))->at + 0.)
#define ev_io_set(ev,fd_,events_) do { (ev)->fd = (fd_); (ev)->events = (events_) | EV_IOFDSET; } while (0)
#define ev_timer_set(ev,after_,repeat_) do { ((ev_watcher_time *)(ev))->at = (after_); (ev)->repeat = (repeat_); } while (0)
#define ev_periodic_set(ev,ofs_,ival_,rcb_) do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb = (rcb_); } while (0)
#define ev_signal_set(ev,signum_) do { (ev)->signum = (signum_); } while (0)
#define ev_child_set(ev,pid_,trace_) do { (ev)->pid = (pid_); (ev)->flags = !!(trace_); } while (0)
#define ev_stat_set(ev,path_,interval_) do { (ev)->path = (path_); (ev)->interval = (interval_); (ev)->wd = -2; } while (0)
#define ev_idle_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_prepare_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_check_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_embed_set(ev,other_) do { (ev)->other = (other_); } while (0)
#define ev_fork_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_async_set(ev) do { (ev)->sent = 0; } while (0)
#define ev_io_init(ev,cb,fd,events) do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)
#define ev_timer_init(ev,cb,after,repeat) do { ev_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0)
#define ev_periodic_init(ev,cb,ofs,ival,rcb) do { ev_init ((ev), (cb)); ev_periodic_set ((ev),(ofs),(ival),(rcb)); } while (0)
#define ev_signal_init(ev,cb,signum) do { ev_init ((ev), (cb)); ev_signal_set ((ev), (signum)); } while (0)
#define ev_child_init(ev,cb,pid,trace) do { ev_init ((ev), (cb)); ev_child_set ((ev),(pid),(trace)); } while (0)
#define ev_stat_init(ev,cb,path,interval) do { ev_init ((ev), (cb)); ev_stat_set ((ev),(path),(interval)); } while (0)
#define ev_idle_init(ev,cb) do { ev_init ((ev), (cb)); ev_idle_set ((ev)); } while (0)
#define ev_prepare_init(ev,cb) do { ev_init ((ev), (cb)); ev_prepare_set ((ev)); } while (0)
#define ev_check_init(ev,cb) do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0)
#define ev_embed_init(ev,cb,other) do { ev_init ((ev), (cb)); ev_embed_set ((ev),(other)); } while (0)
#define ev_fork_init(ev,cb) do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0)
#define ev_async_init(ev,cb) do { ev_init ((ev), (cb)); ev_async_set ((ev)); } while (0)
#define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */
#define ev_is_active(ev) (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */
#define ev_priority(ev) ((((ev_watcher *)(void *)(ev))->priority) + 0)
#define ev_cb(ev) (ev)->cb /* rw */
#define ev_set_priority(ev,pri) ((ev_watcher *)(void *)(ev))->priority = (pri)
#define ev_periodic_at(ev) (((ev_watcher_time *)(ev))->at + 0.)
#ifndef ev_set_cb
# define ev_set_cb(ev,cb_) ev_cb (ev) = (cb_)
# define ev_set_cb(ev,cb_) ev_cb (ev) = (cb_)
#endif
/* stopping (enabling, adding) a watcher does nothing if it is already running */

101
ev.pod

@ -1598,52 +1598,62 @@ inactivity.
Periodic watchers are also timers of a kind, but they are very versatile
(and unfortunately a bit complex).
Unlike C<ev_timer>'s, they are not based on real time (or relative time)
but on wall clock time (absolute time). You can tell a periodic watcher
to trigger after some specific point in time. For example, if you tell a
periodic watcher to trigger in 10 seconds (by specifying e.g. C<ev_now ()
+ 10.>, that is, an absolute time not a delay) and then reset your system
clock to January of the previous year, then it will take more than year
to trigger the event (unlike an C<ev_timer>, which would still trigger
roughly 10 seconds later as it uses a relative timeout).
C<ev_periodic>s can also be used to implement vastly more complex timers,
such as triggering an event on each "midnight, local time", or other
complicated rules.
Unlike C<ev_timer>, periodic watchers are not based on real time (or
relative time, the physical time that passes) but on wall clock time
(absolute time, the thing you can read on your calender or clock). The
difference is that wall clock time can run faster or slower than real
time, and time jumps are not uncommon (e.g. when you adjust your
wrist-watch).
You can tell a periodic watcher to trigger after some specific point
in time: for example, if you tell a periodic watcher to trigger "in 10
seconds" (by specifying e.g. C<ev_now () + 10.>, that is, an absolute time
not a delay) and then reset your system clock to January of the previous
year, then it will take a year or more to trigger the event (unlike an
C<ev_timer>, which would still trigger roughly 10 seconds after starting
it, as it uses a relative timeout).
C<ev_periodic> watchers can also be used to implement vastly more complex
timers, such as triggering an event on each "midnight, local time", or
other complicated rules. This cannot be done with C<ev_timer> watchers, as
those cannot react to time jumps.
As with timers, the callback is guaranteed to be invoked only when the
time (C<at>) has passed, but if multiple periodic timers become ready
during the same loop iteration, then order of execution is undefined.
point in time where it is supposed to trigger has passed, but if multiple
periodic timers become ready during the same loop iteration, then order of
execution is undefined.
=head3 Watcher-Specific Functions and Data Members
=over 4
=item ev_periodic_init (ev_periodic *, callback, ev_tstamp at, ev_tstamp interval, reschedule_cb)
=item ev_periodic_init (ev_periodic *, callback, ev_tstamp offset, ev_tstamp interval, reschedule_cb)
=item ev_periodic_set (ev_periodic *, ev_tstamp at, ev_tstamp interval, reschedule_cb)
=item ev_periodic_set (ev_periodic *, ev_tstamp offset, ev_tstamp interval, reschedule_cb)
Lots of arguments, lets sort it out... There are basically three modes of
Lots of arguments, let's sort it out... There are basically three modes of
operation, and we will explain them from simplest to most complex:
=over 4
=item * absolute timer (at = time, interval = reschedule_cb = 0)
=item * absolute timer (offset = absolute time, interval = 0, reschedule_cb = 0)
In this configuration the watcher triggers an event after the wall clock
time C<at> has passed. It will not repeat and will not adjust when a time
jump occurs, that is, if it is to be run at January 1st 2011 then it will
only run when the system clock reaches or surpasses this time.
time C<offset> has passed. It will not repeat and will not adjust when a
time jump occurs, that is, if it is to be run at January 1st 2011 then it
will be stopped and invoked when the system clock reaches or surpasses
this point in time.
=item * repeating interval timer (at = offset, interval > 0, reschedule_cb = 0)
=item * repeating interval timer (offset = offset within interval, interval > 0, reschedule_cb = 0)
In this mode the watcher will always be scheduled to time out at the next
C<at + N * interval> time (for some integer N, which can also be negative)
and then repeat, regardless of any time jumps.
C<offset + N * interval> time (for some integer N, which can also be
negative) and then repeat, regardless of any time jumps. The C<offset>
argument is merely an offset into the C<interval> periods.
This can be used to create timers that do not drift with respect to the
system clock, for example, here is a C<ev_periodic> that triggers each
hour, on the hour:
system clock, for example, here is an C<ev_periodic> that triggers each
hour, on the hour (with respect to UTC):
ev_periodic_set (&periodic, 0., 3600., 0);
@ -1654,9 +1664,9 @@ by 3600.
Another way to think about it (for the mathematically inclined) is that
C<ev_periodic> will try to run the callback in this mode at the next possible
time where C<time = at (mod interval)>, regardless of any time jumps.
time where C<time = offset (mod interval)>, regardless of any time jumps.
For numerical stability it is preferable that the C<at> value is near
For numerical stability it is preferable that the C<offset> value is near
C<ev_now ()> (the current time), but there is no range requirement for
this value, and in fact is often specified as zero.
@ -1665,15 +1675,16 @@ speed for example), so if C<interval> is very small then timing stability
will of course deteriorate. Libev itself tries to be exact to be about one
millisecond (if the OS supports it and the machine is fast enough).
=item * manual reschedule mode (at and interval ignored, reschedule_cb = callback)
=item * manual reschedule mode (offset ignored, interval ignored, reschedule_cb = callback)
In this mode the values for C<interval> and C<at> are both being
In this mode the values for C<interval> and C<offset> are both being
ignored. Instead, each time the periodic watcher gets scheduled, the
reschedule callback will be called with the watcher as first, and the
current time as second argument.
NOTE: I<This callback MUST NOT stop or destroy any periodic watcher,
ever, or make ANY other event loop modifications whatsoever>.
NOTE: I<This callback MUST NOT stop or destroy any periodic watcher, ever,
or make ANY other event loop modifications whatsoever, unless explicitly
allowed by documentation here>.
If you need to stop it, return C<now + 1e30> (or so, fudge fudge) and stop
it afterwards (e.g. by starting an C<ev_prepare> watcher, which is the
@ -1713,13 +1724,16 @@ program when the crontabs have changed).
=item ev_tstamp ev_periodic_at (ev_periodic *)
When active, returns the absolute time that the watcher is supposed to
trigger next.
When active, returns the absolute time that the watcher is supposed
to trigger next. This is not the same as the C<offset> argument to
C<ev_periodic_set>, but indeed works even in interval and manual
rescheduling modes.
=item ev_tstamp offset [read-write]
When repeating, this contains the offset value, otherwise this is the
absolute point in time (the C<at> value passed to C<ev_periodic_set>).
absolute point in time (the C<offset> value passed to C<ev_periodic_set>,
although libev might modify this value for better numerical stability).
Can be modified any time, but changes only take effect when the periodic
timer fires or C<ev_periodic_again> is being called.
@ -2684,9 +2698,14 @@ C<ev_feed_event>, this call is safe to do from other threads, signal or
similar contexts (see the discussion of C<EV_ATOMIC_T> in the embedding
section below on what exactly this means).
This call incurs the overhead of a system call only once per loop iteration,
so while the overhead might be noticeable, it doesn't apply to repeated
calls to C<ev_async_send>.
Note that, as with other watchers in libev, multiple events might get
compressed into a single callback invocation (another way to look at this
is that C<ev_async> watchers are level-triggered, set on C<ev_async_send>,
reset when the event loop detects that).
This call incurs the overhead of a system call only once per event loop
iteration, so while the overhead might be noticeable, it doesn't apply to
repeated calls to C<ev_async_send> for the same event loop.
=item bool = ev_async_pending (ev_async *)
@ -2699,8 +2718,10 @@ the loop iterates next and checks for the watcher to have become active,
it will reset the flag again. C<ev_async_pending> can be used to very
quickly check whether invoking the loop might be a good idea.
Not that this does I<not> check whether the watcher itself is pending, only
whether it has been requested to make this watcher pending.
Not that this does I<not> check whether the watcher itself is pending,
only whether it has been requested to make this watcher pending: there
is a time window between the event loop checking and resetting the async
notification, and the callback being invoked.
=back

Loading…
Cancel
Save