Ken Thomases : winemac: Don' t use the main dispatch queue to implement OnMainThread() for a thread with no event queue.
Alexandre Julliard
julliard at winehq.org
Wed Oct 30 13:11:04 CDT 2013
Module: wine
Branch: master
Commit: 2f68e47167925993947ac07e360e9fa251c50979
URL: http://source.winehq.org/git/wine.git/?a=commit;h=2f68e47167925993947ac07e360e9fa251c50979
Author: Ken Thomases <ken at 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];
}
More information about the wine-cvs
mailing list