Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions ext/cool.io/stat_watcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ static void Coolio_StatWatcher_libev_callback(struct ev_loop *ev_loop, struct ev
static void Coolio_StatWatcher_dispatch_callback(VALUE self, int revents);

/*
* Coolio::StatWatcher lets you create either one-shot or periodic stats which
* run within Coolio's event loop. It's useful for creating timeouts or
* events which fire periodically.
* Coolio::StatWatcher monitors a path and calls on_change when its stat
* attributes change.
**/
void Init_coolio_stat_watcher()
{
Expand Down Expand Up @@ -77,10 +76,18 @@ void Init_coolio_stat_watcher()
* specified how often in seconds the path should be polled for changes.
* Setting interval to zero uses an "automatic" value (typically around 5
* seconds) which optimizes performance. Otherwise, values less than
* 0.1 are not particularly meaningful. Where available (on Linux and Windows),
* high performance file monitoring interfaces are used. On Windows, polling
* remains necessary because notification timing is not guaranteed. An attached
* Windows watcher may also prevent renaming an ancestor directory until detached.
* 0.1 are not particularly meaningful. Where available (on Linux, macOS and
Comment thread
ashie marked this conversation as resolved.
Resolved
* Windows), high performance file monitoring interfaces are used. On macOS
* and Windows, polling remains enabled for changes native notifications may
* miss. An attached Windows watcher may also prevent renaming an ancestor
* directory until detached.
*
* On macOS, each registered watcher uses one file descriptor for the path or
* an ancestor directory, plus one shared kqueue descriptor per loop. If the
* descriptor limit is reached, watchers fall back to polling.
*
* On macOS, construct the loop with :fork_check => true when continuing to
* use attached watchers in a forked child.
*/
static VALUE Coolio_StatWatcher_initialize(int argc, VALUE *argv, VALUE self)
{
Expand Down
39 changes: 39 additions & 0 deletions ext/libev/ev.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,14 @@
# endif
#endif

#ifndef EV_USE_KQUEUE_STAT
# if EV_USE_KQUEUE && EV_STAT_ENABLE && defined __APPLE__ && defined __MACH__
# define EV_USE_KQUEUE_STAT 1
# else
# define EV_USE_KQUEUE_STAT 0
# endif
#endif

#ifndef EV_PID_HASHSIZE
# define EV_PID_HASHSIZE EV_FEATURE_DATA ? 16 : 1
#endif
Expand Down Expand Up @@ -1863,6 +1871,10 @@ typedef struct
#if defined(_WIN32) && EV_STAT_ENABLE && EV_ASYNC_ENABLE
static void win32_fs_destroy (EV_P);
#endif
#if EV_USE_KQUEUE_STAT
static void kq_stat_fork (EV_P);
static void kq_stat_destroy (EV_P);
#endif

#if EV_FEATURE_API
# define EV_RELEASE_CB if (expect_false (release_cb)) release_cb (EV_A)
Expand Down Expand Up @@ -2937,6 +2949,10 @@ loop_init (EV_P_ unsigned int flags) EV_THROW
win32_fs = 0;
win32_fs_disabled = (flags & EVFLAG_NOINOTIFY) != 0;
#endif
#if EV_USE_KQUEUE_STAT
kq_stat = 0;
kq_stat_disabled = (flags & EVFLAG_NOINOTIFY) != 0;
#endif
#if EV_USE_INOTIFY
fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2;
#endif
Expand Down Expand Up @@ -3008,6 +3024,9 @@ ev_loop_destroy (EV_P)
#if defined(_WIN32) && EV_STAT_ENABLE && EV_ASYNC_ENABLE
win32_fs_destroy (EV_A);
#endif
#if EV_USE_KQUEUE_STAT
kq_stat_destroy (EV_A);
#endif

if (ev_is_active (&pipe_w))
{
Expand Down Expand Up @@ -3110,6 +3129,9 @@ loop_fork (EV_P)
#if EV_USE_INOTIFY
infy_fork (EV_A);
#endif
#if EV_USE_KQUEUE_STAT
kq_stat_fork (EV_A);
#endif

#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
if (ev_is_active (&pipe_w) && postfork != 2)
Expand Down Expand Up @@ -4366,6 +4388,9 @@ noinline static void stat_timer_cb (EV_P_ ev_timer *w_, int revents);
#if defined(_WIN32) && EV_ASYNC_ENABLE
# include "ev_win32_stat.c"
#endif
#if EV_USE_KQUEUE_STAT
# include "ev_kqueue_stat.c"
#endif

#if EV_USE_INOTIFY

Expand Down Expand Up @@ -4648,6 +4673,10 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
win32_fs_add (EV_A_ w, 1); /* retry missing parents or failed directory handles */
#endif

#if EV_USE_KQUEUE_STAT
kq_stat_poll (EV_A_ w, revents);
Comment thread
ashie marked this conversation as resolved.
Resolved
#endif

ev_statdata prev = w->attr;
ev_stat_stat (EV_A_ w);

Expand Down Expand Up @@ -4685,6 +4714,10 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
}
#endif

#if EV_USE_KQUEUE_STAT
kq_stat_refresh (EV_A_ w);
#endif

ev_feed_event (EV_A_ w, EV_STAT);
}
}
Expand Down Expand Up @@ -4721,6 +4754,9 @@ ev_stat_start (EV_P_ ev_stat *w) EV_THROW
win32_fs_add (EV_A_ w, 0);
stat_timer_cb (EV_A_ &w->timer, 0); /* close the stat/registration race */
#endif
#if EV_USE_KQUEUE_STAT
kq_stat_start (EV_A_ w);
#endif

EV_FREQUENT_CHECK;
}
Expand All @@ -4737,6 +4773,9 @@ ev_stat_stop (EV_P_ ev_stat *w) EV_THROW
#if defined(_WIN32) && EV_ASYNC_ENABLE
win32_fs_del (EV_A_ w);
#endif
#if EV_USE_KQUEUE_STAT
kq_stat_del (EV_A_ w);
#endif

#if EV_USE_INOTIFY
infy_del (EV_A_ w);
Expand Down
Loading
Loading