# HG changeset patch # User Bill Welliver # Date 1324612732 18000 # Node ID b391e02c134c500e18cfaabd7b026b097d056343 # Parent 317c241f917ed998d3ebb3d8a7c84d2f6531be87 fixes to work with CFRunLoop based backends, that might cause code to run on a different runloop thread diff -r 317c241f917ed998d3ebb3d8a7c84d2f6531be87 -r b391e02c134c500e18cfaabd7b026b097d056343 CHANGES --- a/CHANGES Thu Dec 22 21:57:28 2011 -0500 +++ b/CHANGES Thu Dec 22 22:58:52 2011 -0500 @@ -0,0 +1,1 @@ +- now works with PollDeviceBackend based on CFRunLoop diff -r 317c241f917ed998d3ebb3d8a7c84d2f6531be87 -r b391e02c134c500e18cfaabd7b026b097d056343 fsevents.cmod --- a/fsevents.cmod Thu Dec 22 21:57:28 2011 -0500 +++ b/fsevents.cmod Thu Dec 22 22:58:52 2011 -0500 @@ -27,6 +27,13 @@ void low_stop(); struct pike_string * string_from_cfstring(CFStringRef cfString); +static void do_event_callback(ConstFSEventStreamRef streamRef, + void *clientCallBackInfo, + size_t numEvents, + void *eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]); + static void event_callback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, @@ -179,6 +186,7 @@ if(CFArrayGetCount(THIS->_paths)) { THIS->runLoop = CFRunLoopGetCurrent(); + CFRetain(THIS->runLoop); context.version = 0; context.info = THIS; @@ -192,7 +200,7 @@ Pike_error("no startdate.\n"); if(!THIS->_latency) Pike_error("no latency.\n"); -printf("creating stream.\n"); +//printf("creating stream.\n"); THIS->stream = FSEventStreamCreate(kCFAllocatorDefault, &event_callback, @@ -203,7 +211,7 @@ THIS->_flags | kFSEventStreamCreateFlagUseCFTypes ); - printf("created.\n"); + //printf("created.\n"); THIS->isRunning = 1; FSEventStreamScheduleWithRunLoop(THIS->stream, THIS->runLoop, kCFRunLoopDefaultMode); FSEventStreamStart(THIS->stream); @@ -227,6 +235,7 @@ FSEventStreamUnscheduleFromRunLoop(THIS->stream, THIS->runLoop, kCFRunLoopDefaultMode); FSEventStreamInvalidate(THIS->stream); FSEventStreamRelease(THIS->stream); + CFRelease(THIS->runLoop); THIS->isRunning = 0; } } @@ -274,7 +283,7 @@ { EXIT; low_stop(); - if(THIS->_paths) CFRelease(THIS->_paths); + if(THIS->_paths) CFRelease(THIS->_paths); } } @@ -294,7 +303,6 @@ * @param eventIds An array of IDs associated with the events */ - static void event_callback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, size_t numEvents, @@ -302,7 +310,69 @@ const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[]) { + struct thread_state *state; + + if((state = thread_state_for_id(th_self()))!=NULL) + { + /* This is a pike thread. Do we have the interpreter lock? */ + if(!state->swapped) + { + /* Yes. Go for it... */ + do_event_callback(streamRef, clientCallBackInfo, numEvents, eventPaths, eventFlags, eventIds); + } + else + { + /* Nope, let's get it... */ + mt_lock_interpreter(); + SWAP_IN_THREAD(state); + + do_event_callback(streamRef, clientCallBackInfo, numEvents, eventPaths, eventFlags, eventIds); + + /* Restore */ + SWAP_OUT_THREAD(state); + mt_unlock_interpreter(); + } + } + else + { + /* Not a pike thread. Create a temporary thread_id... */ + struct object *thread_obj; +// printf("creating a temporary thread.\n"); + mt_lock_interpreter(); +// printf("got the lock.\n"); + init_interpreter(); + Pike_interpreter.stack_top=((char *)&state)+ (thread_stack_size-16384) * STACK_DIRECTION; + Pike_interpreter.recoveries = NULL; + thread_obj = fast_clone_object(thread_id_prog); + INIT_THREAD_STATE((struct thread_state *)(thread_obj->storage + + thread_storage_offset)); + num_threads++; + thread_table_insert(Pike_interpreter.thread_state); + + do_event_callback(streamRef, clientCallBackInfo, numEvents, eventPaths, eventFlags, eventIds); + + cleanup_interpret(); /* Must be done before EXIT_THREAD_STATE */ + Pike_interpreter.thread_state->status=THREAD_EXITED; + co_signal(&Pike_interpreter.thread_state->status_change); + thread_table_delete(Pike_interpreter.thread_state); + EXIT_THREAD_STATE(Pike_interpreter.thread_state); + Pike_interpreter.thread_state=NULL; + free_object(thread_obj); + thread_obj = NULL; + num_threads--; + mt_unlock_interpreter(); + } + +} +static void do_event_callback(ConstFSEventStreamRef streamRef, + void *clientCallBackInfo, + size_t numEvents, + void *eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]) +{ size_t cnt = 0; + for(cnt = 0; cnt < numEvents; cnt++) { CFStringRef eventPath;