Module: wine Branch: master Commit: 2f68e47167925993947ac07e360e9fa251c50979 URL: http://source.winehq.org/git/wine.git/?a=commit;h=2f68e47167925993947ac07e36...
Author: Ken Thomases ken@codeweavers.com Date: Wed Oct 30 05:52:58 2013 -0500
winemac: Don't use the main dispatch queue to implement OnMainThread() for a thread with no event queue.
The main dispatch queue is a serial queue and is a shared resource. If we submit a long-running task to it, then no other tasks, including those submitted by the system frameworks, can run until it completes.
---
dlls/winemac.drv/cocoa_event.m | 49 +++++++++++++++++++++++++-------------- 1 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_event.m b/dlls/winemac.drv/cocoa_event.m index 3b35576..13f9695 100644 --- a/dlls/winemac.drv/cocoa_event.m +++ b/dlls/winemac.drv/cocoa_event.m @@ -460,42 +460,55 @@ void OnMainThread(dispatch_block_t block) NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary]; WineEventQueue* queue = [threadDict objectForKey:WineEventQueueThreadDictionaryKey]; + dispatch_semaphore_t semaphore; __block BOOL finished;
if (!queue) { - /* Fall back to synchronous dispatch without handling query events. */ - dispatch_sync(dispatch_get_main_queue(), block); - [pool release]; - return; + semaphore = dispatch_semaphore_create(0); + dispatch_retain(semaphore); }
finished = FALSE; OnMainThreadAsync(^{ block(); finished = TRUE; - [queue signalEventAvailable]; + if (queue) + [queue signalEventAvailable]; + else + { + dispatch_semaphore_signal(semaphore); + dispatch_release(semaphore); + } });
- while (!finished) + if (queue) { - MacDrvEvent* macDrvEvent; - struct kevent kev; - - while (!finished && - (macDrvEvent = [queue getEventMatchingMask:event_mask_for_type(QUERY_EVENT)])) + while (!finished) { - queue->event_handler(macDrvEvent->event); - } + MacDrvEvent* macDrvEvent; + struct kevent kev;
- if (!finished) - { - [pool release]; - pool = [[NSAutoreleasePool alloc] init]; + while (!finished && + (macDrvEvent = [queue getEventMatchingMask:event_mask_for_type(QUERY_EVENT)])) + { + queue->event_handler(macDrvEvent->event); + } + + if (!finished) + { + [pool release]; + pool = [[NSAutoreleasePool alloc] init];
- kevent(queue->kq, NULL, 0, &kev, 1, NULL); + kevent(queue->kq, NULL, 0, &kev, 1, NULL); + } } } + else + { + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + dispatch_release(semaphore); + }
[pool release]; }