diff options
author | Timothy J Fontaine <tjfontaine@gmail.com> | 2013-08-21 11:15:21 -0700 |
---|---|---|
committer | Timothy J Fontaine <tjfontaine@gmail.com> | 2013-08-21 11:15:21 -0700 |
commit | a784abaff631449533d44846987c1537c080e03d (patch) | |
tree | 0982d9a92450edb9e46ba683d75eb7822ea004b3 /deps/uv/src/unix/fsevents.c | |
parent | 41f55dc59b423b8b76e6f7971fd8f3a326a6fbad (diff) | |
download | android-node-v8-a784abaff631449533d44846987c1537c080e03d.tar.gz android-node-v8-a784abaff631449533d44846987c1537c080e03d.tar.bz2 android-node-v8-a784abaff631449533d44846987c1537c080e03d.zip |
uv: Upgrade to v0.11.8
Diffstat (limited to 'deps/uv/src/unix/fsevents.c')
-rw-r--r-- | deps/uv/src/unix/fsevents.c | 267 |
1 files changed, 233 insertions, 34 deletions
diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c index ef9a352b7f..79ad198bae 100644 --- a/deps/uv/src/unix/fsevents.c +++ b/deps/uv/src/unix/fsevents.c @@ -34,13 +34,28 @@ int uv__fsevents_close(uv_fs_event_t* handle) { return 0; } + +void uv__fsevents_loop_delete(uv_loop_t* loop) { +} + #else /* TARGET_OS_IPHONE */ #include <assert.h> #include <stdlib.h> +#include <pthread.h> + +#include <CoreFoundation/CFRunLoop.h> #include <CoreServices/CoreServices.h> typedef struct uv__fsevents_event_s uv__fsevents_event_t; +typedef struct uv__cf_loop_signal_s uv__cf_loop_signal_t; +typedef void (*cf_loop_signal_cb)(void* arg); + +struct uv__cf_loop_signal_s { + cf_loop_signal_cb cb; + QUEUE member; + void* arg; +}; struct uv__fsevents_event_s { int events; @@ -48,6 +63,12 @@ struct uv__fsevents_event_s { char path[1]; }; +/* Forward declarations */ +static void uv__cf_loop_cb(void* arg); +static void* uv__cf_loop_runner(void* arg); +static void uv__cf_loop_signal(uv_loop_t* loop, + cf_loop_signal_cb cb, + void* arg); #define UV__FSEVENTS_WALK(handle, block) \ { \ @@ -75,7 +96,7 @@ struct uv__fsevents_event_s { } -void uv__fsevents_cb(uv_async_t* cb, int status) { +static void uv__fsevents_cb(uv_async_t* cb, int status) { uv_fs_event_t* handle; handle = cb->data; @@ -92,12 +113,12 @@ void uv__fsevents_cb(uv_async_t* cb, int status) { } -void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, - void* info, - size_t numEvents, - void* eventPaths, - const FSEventStreamEventFlags eventFlags[], - const FSEventStreamEventId eventIds[]) { +static void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, + void* info, + size_t numEvents, + void* eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]) { size_t i; int len; char** paths; @@ -190,19 +211,8 @@ void uv__fsevents_event_cb(ConstFSEventStreamRef streamRef, } -void uv__fsevents_schedule(void* arg) { +static void uv__fsevents_schedule(void* arg) { uv_fs_event_t* handle; - - handle = arg; - FSEventStreamScheduleWithRunLoop(handle->cf_eventstream, - handle->loop->cf_loop, - kCFRunLoopDefaultMode); - FSEventStreamStart(handle->cf_eventstream); - uv_sem_post(&handle->cf_sem); -} - - -int uv__fsevents_init(uv_fs_event_t* handle) { FSEventStreamContext ctx; FSEventStreamRef ref; CFStringRef path; @@ -210,6 +220,8 @@ int uv__fsevents_init(uv_fs_event_t* handle) { CFAbsoluteTime latency; FSEventStreamCreateFlags flags; + handle = arg; + /* Initialize context */ ctx.version = 0; ctx.info = handle; @@ -217,16 +229,13 @@ int uv__fsevents_init(uv_fs_event_t* handle) { ctx.release = NULL; ctx.copyDescription = NULL; - /* Get absolute path to file */ - handle->realpath = realpath(handle->filename, NULL); - if (handle->realpath != NULL) - handle->realpath_len = strlen(handle->realpath); - /* Initialize paths array */ path = CFStringCreateWithCString(NULL, handle->filename, CFStringGetSystemEncoding()); + assert(path != NULL); paths = CFArrayCreate(NULL, (const void**)&path, 1, NULL); + assert(paths != NULL); latency = 0.15; @@ -240,8 +249,203 @@ int uv__fsevents_init(uv_fs_event_t* handle) { kFSEventStreamEventIdSinceNow, latency, flags); + assert(ref != NULL); handle->cf_eventstream = ref; + FSEventStreamScheduleWithRunLoop(handle->cf_eventstream, + handle->loop->cf_loop, + kCFRunLoopDefaultMode); + if (!FSEventStreamStart(handle->cf_eventstream)) + abort(); +} + + +static void uv__fsevents_unschedule(void* arg) { + uv_fs_event_t* handle; + + handle = arg; + + /* Stop emitting events */ + FSEventStreamStop(handle->cf_eventstream); + + /* Release stream */ + FSEventStreamInvalidate(handle->cf_eventstream); + FSEventStreamRelease(handle->cf_eventstream); + handle->cf_eventstream = NULL; + + /* Notify main thread that we're done here */ + uv_sem_post(&handle->cf_sem); +} + + +static int uv__fsevents_loop_init(uv_loop_t* loop) { + CFRunLoopSourceContext ctx; + pthread_attr_t attr_storage; + pthread_attr_t* attr; + int err; + + if (loop->cf_loop != NULL) + return 0; + + err = uv_mutex_init(&loop->cf_mutex); + if (err) + return err; + + err = uv_sem_init(&loop->cf_sem, 0); + if (err) + goto fail_sem_init; + + QUEUE_INIT(&loop->cf_signals); + memset(&ctx, 0, sizeof(ctx)); + ctx.info = loop; + ctx.perform = uv__cf_loop_cb; + loop->cf_cb = CFRunLoopSourceCreate(NULL, 0, &ctx); + + /* In the unlikely event that pthread_attr_init() fails, create the thread + * with the default stack size. We'll use a little more address space but + * that in itself is not a fatal error. + */ + attr = &attr_storage; + if (pthread_attr_init(attr)) + attr = NULL; + + if (attr != NULL) + if (pthread_attr_setstacksize(attr, 3 * PTHREAD_STACK_MIN)) + abort(); + + /* uv_thread_t is an alias for pthread_t. */ + err = -pthread_create(&loop->cf_thread, attr, uv__cf_loop_runner, loop); + + if (attr != NULL) + pthread_attr_destroy(attr); + + if (err) + goto fail_thread_create; + + /* Synchronize threads */ + uv_sem_wait(&loop->cf_sem); + assert(loop->cf_loop != NULL); + return 0; + +fail_thread_create: + uv_sem_destroy(&loop->cf_sem); + +fail_sem_init: + uv_mutex_destroy(&loop->cf_mutex); + return err; +} + + +void uv__fsevents_loop_delete(uv_loop_t* loop) { + uv__cf_loop_signal_t* s; + QUEUE* q; + + if (loop->cf_loop == NULL) + return; + + uv__cf_loop_signal(loop, NULL, NULL); + uv_thread_join(&loop->cf_thread); + uv_sem_destroy(&loop->cf_sem); + uv_mutex_destroy(&loop->cf_mutex); + + /* Free any remaining data */ + while (!QUEUE_EMPTY(&loop->cf_signals)) { + q = QUEUE_HEAD(&loop->cf_signals); + s = QUEUE_DATA(q, uv__cf_loop_signal_t, member); + QUEUE_REMOVE(q); + free(s); + } +} + + +static void* uv__cf_loop_runner(void* arg) { + uv_loop_t* loop; + + loop = arg; + loop->cf_loop = CFRunLoopGetCurrent(); + + CFRunLoopAddSource(loop->cf_loop, + loop->cf_cb, + kCFRunLoopDefaultMode); + + uv_sem_post(&loop->cf_sem); + + CFRunLoopRun(); + CFRunLoopRemoveSource(loop->cf_loop, + loop->cf_cb, + kCFRunLoopDefaultMode); + + return NULL; +} + + +static void uv__cf_loop_cb(void* arg) { + uv_loop_t* loop; + QUEUE* item; + QUEUE split_head; + uv__cf_loop_signal_t* s; + + loop = arg; + + uv_mutex_lock(&loop->cf_mutex); + QUEUE_INIT(&split_head); + if (!QUEUE_EMPTY(&loop->cf_signals)) { + QUEUE* split_pos = QUEUE_HEAD(&loop->cf_signals); + QUEUE_SPLIT(&loop->cf_signals, split_pos, &split_head); + } + uv_mutex_unlock(&loop->cf_mutex); + + while (!QUEUE_EMPTY(&split_head)) { + item = QUEUE_HEAD(&split_head); + + s = QUEUE_DATA(item, uv__cf_loop_signal_t, member); + + /* This was a termination signal */ + if (s->cb == NULL) + CFRunLoopStop(loop->cf_loop); + else + s->cb(s->arg); + + QUEUE_REMOVE(item); + free(s); + } +} + + +void uv__cf_loop_signal(uv_loop_t* loop, cf_loop_signal_cb cb, void* arg) { + uv__cf_loop_signal_t* item; + + item = malloc(sizeof(*item)); + /* XXX: Fail */ + if (item == NULL) + abort(); + + item->arg = arg; + item->cb = cb; + + uv_mutex_lock(&loop->cf_mutex); + QUEUE_INSERT_TAIL(&loop->cf_signals, &item->member); + uv_mutex_unlock(&loop->cf_mutex); + + assert(loop->cf_loop != NULL); + CFRunLoopSourceSignal(loop->cf_cb); + CFRunLoopWakeUp(loop->cf_loop); +} + + +int uv__fsevents_init(uv_fs_event_t* handle) { + int err; + + err = uv__fsevents_loop_init(handle->loop); + if (err) + return err; + + /* Get absolute path to file */ + handle->realpath = realpath(handle->filename, NULL); + if (handle->realpath != NULL) + handle->realpath_len = strlen(handle->realpath); + + handle->cf_eventstream = NULL; /* * Events will occur in other thread. * Initialize callback for getting them back into event loop's thread @@ -266,21 +470,16 @@ int uv__fsevents_init(uv_fs_event_t* handle) { int uv__fsevents_close(uv_fs_event_t* handle) { - if (handle->cf_eventstream == NULL) + if (handle->cf_cb == NULL) return -EINVAL; - /* Ensure that event stream was scheduled */ - uv_sem_wait(&handle->cf_sem); - - /* Stop emitting events */ - FSEventStreamStop(handle->cf_eventstream); + uv__cf_loop_signal(handle->loop, uv__fsevents_unschedule, handle); - /* Release stream */ - FSEventStreamInvalidate(handle->cf_eventstream); - FSEventStreamRelease(handle->cf_eventstream); - handle->cf_eventstream = NULL; + /* Wait for deinitialization */ + uv_sem_wait(&handle->cf_sem); uv_close((uv_handle_t*) handle->cf_cb, (uv_close_cb) free); + handle->cf_cb = NULL; /* Free data in queue */ UV__FSEVENTS_WALK(handle, { |