[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