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