Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should a `.barrier` on a concurrent queue become active immediately?

I'm not sure if this broke in xcode8 beta 5. Look at this code. Do you think it should print "A" first, or "B" first?

let q = DispatchQueue(label: "q", attributes: .concurrent)
q.async(flags: .barrier) {
  Thread.sleep(forTimeInterval: 0.25)
  print("A")
}
q.sync {
  print("B")
}

Because of the .barrier, I think it should block the concurrent queue and print "A", "B", but it does not in the latest xcode beta.

Bug? Misunderstanding of .barrier? What do you think?

please note: I know this would print in the expected order if I used a serial queue--this is a tiny part of a much larger system and I need to understand this behavior in isolation.

like image 636
SimplGy Avatar asked Aug 13 '16 16:08

SimplGy


People also ask

What is difference between serial and concurrent queue?

Serial queues (also known as private dispatch queues) execute one task at a time in the order in which they are added to the queue. Queues (also known as a type of global dispatch queue) execute one or more tasks concurrently, but tasks are still started in the order in which they were added to the queue.

Why is DispatchGroup used in certain situations?

DispatchGroup allows for aggregate synchronization of work. It can be used to submit multiple different work items or blocks and track when they all complete, even though they might run on different queues.

What is barrier flag in Swift?

barrier flag means that it will wait until every currently running block in the queue is finished executing before it executes. Other blocks will queue up behind it and be executed when the barrier dispatch is done. When the barrier is executing, it essentially acts as a serial queue.

WHAT IS barrier in iOS?

Overview. Use a barrier to synchronize the execution of one or more tasks in your dispatch queue. When you add a barrier to a concurrent dispatch queue, the queue delays the execution of the barrier block (and any tasks submitted after the barrier) until all previously submitted tasks finish executing.


1 Answers

This was a bug fixed in beta 6.

In beta 5, not only does it not behave the way you'd expect, but the .onQueueAsBarrier precondition fails, too. The problem would appear to be buried in async with the .barrier option, because if you perform it via equivalent Objective-C API, dispatch_barrier_async, it works fine, e.g.:

let q = DispatchQueue(label: "q", attributes: .concurrent)

BarrierExperiment.dispatchBarrierAsync(q) {
    dispatchPrecondition(condition: .onQueueAsBarrier(q))
    Thread.sleep(forTimeInterval: 0.25)
    print("A")
}

q.async() {
    print("B")
}

Where

@interface BarrierExperiment : NSObject

+ (void)dispatchBarrierAsync:(dispatch_queue_t)queue block:(void (^)())block;

@end

@implementation BarrierExperiment

+ (void)dispatchBarrierAsync:(dispatch_queue_t)queue block:(void (^)())block {
    dispatch_barrier_async(queue, block);
}

@end
like image 105
Rob Avatar answered Nov 15 '22 07:11

Rob