0

So I am reading Facebook's awesome AsyncDisplayKit source code. Specifically, I am reading the implementation behind ASDealloc2MainObject. One thing caught my eye.

In _AS-objc-internal.h, line 423 to 424, there is the programmer dispatching some task onto the main queue.

        dispatch_barrier_async_f(dispatch_get_main_queue(), self,           \
            _objc_deallocOnMainThreadHelper);                               \

As is the case of other dispatch barrier functions, the barrier logic from dispatch_barrier_async_f()only makes sense if it's dealing with a custom concurrent queue. For global concurrent queues and the main queue, it'll act just like dispatch_async_f() with the barrier having no effect.

So why using barrier here?

Di Wu
  • 6,436
  • 3
  • 35
  • 51
  • In my view, using 'barrier' with the main queue isn't relevant because a serial queue executes one operation at a time anyway. 'Dispatch_async' should be enough to get the same result. – XLE_22 Mar 20 '18 at 09:32

2 Answers2

2

That looks like a mistake to me. At best, they're trying to signal intent and remind the programmer "hey, this thing is serial", but that seems pretty dubious.

Catfish_Man
  • 41,261
  • 11
  • 67
  • 84
  • 1
    I'm inclined to agree. – ipmcc Dec 11 '14 at 15:27
  • From Apple's gcd source code I found a possible explanation. Please see my answer. I'm still not quite sure though. – Di Wu Dec 12 '14 at 05:58
  • 2
    on a serial queue, every item is a barrier item and dispatch_barrier_async_f() and dispatch_async_f() are equivalent. – das Dec 15 '14 at 03:55
0

So I have found a possible explanation: dispatch_async_f() calls dispatch_barrier_async_f() under the hood if the queue passed in has the width of concurrency set to 1.

The implementation of dispatch_async_f() looks like this:

DISPATCH_NOINLINE
    void
    dispatch_async_f(dispatch_queue_t dq, void *ctxt, dispatch_function_t func)
    {
            dispatch_continuation_t dc;

            // No fastpath/slowpath hint because we simply don't know
            if (dq->dq_width == 1) {
                    return dispatch_barrier_async_f(dq, ctxt, func);
            }

            dc = fastpath(_dispatch_continuation_alloc_cacheonly());
            if (!dc) {
                    return _dispatch_async_f_slow(dq, ctxt, func);
            }

            dc->do_vtable = (void *)DISPATCH_OBJ_ASYNC_BIT;
            dc->dc_func = func;
            dc->dc_ctxt = ctxt;

            // No fastpath/slowpath hint because we simply don't know
            if (dq->do_targetq) {
                    return _dispatch_async_f2(dq, dc);
            }

            _dispatch_queue_push(dq, dc);
    }
Di Wu
  • 6,436
  • 3
  • 35
  • 51