[libdispatch-changes] [156] trunk/src/queue.c

source_changes at macosforge.org source_changes at macosforge.org
Sat Nov 14 15:58:57 PST 2009


Revision: 156
          http://trac.macosforge.org/projects/libdispatch/changeset/156
Author:   kvv at apple.com
Date:     2009-11-14 15:58:57 -0800 (Sat, 14 Nov 2009)
Log Message:
-----------
10.6.2: Always run dispatch_sync blocks on the current thread to better support
the thread-local garbage collector. <rdar://problem/7181849>

Modified Paths:
--------------
    trunk/src/queue.c

Modified: trunk/src/queue.c
===================================================================
--- trunk/src/queue.c	2009-11-14 23:53:59 UTC (rev 155)
+++ trunk/src/queue.c	2009-11-14 23:58:57 UTC (rev 156)
@@ -716,8 +716,9 @@
 }
 
 struct dispatch_barrier_sync_slow2_s {
+	dispatch_queue_t dbss2_dq;
 	dispatch_function_t dbss2_func;
-	dispatch_function_t dbss2_ctxt;
+	dispatch_function_t dbss2_ctxt;	
 	dispatch_semaphore_t dbss2_sema;
 };
 
@@ -726,7 +727,13 @@
 {
 	struct dispatch_barrier_sync_slow2_s *dbss2 = ctxt;
 
-	dbss2->dbss2_func(dbss2->dbss2_ctxt);
+	dispatch_assert(dbss2->dbss2_dq == dispatch_get_current_queue());
+	// ALL blocks on the main queue, must be run on the main thread
+	if (dbss2->dbss2_dq == dispatch_get_main_queue()) {
+		dbss2->dbss2_func(dbss2->dbss2_ctxt);
+	} else {
+		dispatch_suspend(dbss2->dbss2_dq);
+	}
 	dispatch_semaphore_signal(dbss2->dbss2_sema);
 }
 
@@ -734,9 +741,15 @@
 static void
 _dispatch_barrier_sync_f_slow(dispatch_queue_t dq, void *ctxt, dispatch_function_t func)
 {
+	
+	// It's preferred to execute synchronous blocks on the current thread
+	// due to thread-local side effects, garbage collection, etc. However,
+	// blocks submitted to the main thread MUST be run on the main thread
+	
 	struct dispatch_barrier_sync_slow2_s dbss2 = {
+		.dbss2_dq = dq,
 		.dbss2_func = func,
-		.dbss2_ctxt = ctxt,
+		.dbss2_ctxt = ctxt,		
 		.dbss2_sema = _dispatch_get_thread_semaphore(),
 	};
 	struct dispatch_barrier_sync_slow_s {
@@ -746,17 +759,17 @@
 		.dc_func = _dispatch_barrier_sync_f_slow_invoke,
 		.dc_ctxt = &dbss2,
 	};
-
+	
+	dispatch_queue_t old_dq = _dispatch_thread_getspecific(dispatch_queue_key);
 	_dispatch_queue_push(dq, (void *)&dbss);
+	dispatch_semaphore_wait(dbss2.dbss2_sema, DISPATCH_TIME_FOREVER);
 
-	while (dispatch_semaphore_wait(dbss2.dbss2_sema, dispatch_time(0, 3ull * NSEC_PER_SEC))) {
-		if (DISPATCH_OBJECT_SUSPENDED(dq)) {
-			continue;
-		}
-		if (_dispatch_queue_trylock(dq)) {
-			_dispatch_queue_drain(dq);
-			_dispatch_queue_unlock(dq);
-		}
+	if (dq != dispatch_get_main_queue()) {
+		_dispatch_thread_setspecific(dispatch_queue_key, dq);
+		func(ctxt);
+		_dispatch_workitem_inc();
+		_dispatch_thread_setspecific(dispatch_queue_key, old_dq);
+		dispatch_resume(dq);
 	}
 	_dispatch_put_thread_semaphore(dbss2.dbss2_sema);
 }
@@ -765,6 +778,13 @@
 void
 dispatch_barrier_sync(dispatch_queue_t dq, void (^work)(void))
 {
+	// Blocks submitted to the main queue MUST be run on the main thread,
+	// therefore we must Block_copy in order to notify the thread-local
+	// garbage collector that the objects are transferring to the main thread
+	if (dq == dispatch_get_main_queue()) {
+		dispatch_block_t block = Block_copy(work);
+		return dispatch_barrier_sync_f(dq, block, _dispatch_call_block_and_release);
+	}	
 	struct Block_basic *bb = (void *)work;
 
 	dispatch_barrier_sync_f(dq, work, (dispatch_function_t)bb->Block_invoke);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/libdispatch-changes/attachments/20091114/35db99cf/attachment-0001.html>


More information about the libdispatch-changes mailing list