1

Given the creation of queue2 with target of queue1 (queue2 = dispatch_queue_create_with_target(name, attr, queue1))...

If both queues are concurrent, does dispatch_barrier_async on queue2 only wait on queue2 to be empty, or does it also wait for the target queue? When both queues have respective barrier blocks queued, does queue2's barrier block take priority?

xtravar
  • 1,321
  • 11
  • 24

1 Answers1

3

A barrier on queue does not affect its target queue.

This is most easily demonstrated empirically. For example:

- (void)experiment {
    dispatch_queue_t queue1 = dispatch_queue_create("1", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t queue2 = dispatch_queue_create_with_target("2", DISPATCH_QUEUE_CONCURRENT, queue1);

    dispatch_async(queue1, ^{
        [self taskOnQueue:1 taskNumber:1 color:1];
    });
    dispatch_async(queue2, ^{
        [self taskOnQueue:2 taskNumber:2 color:0];
    });
    dispatch_barrier_async(queue2, ^{
        [self taskOnQueue:2 taskNumber:3 color:0];
    });

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        dispatch_async(queue2, ^{
            [self taskOnQueue:2 taskNumber:4 color:0];
        });
        dispatch_async(queue1, ^{
            [self taskOnQueue:1 taskNumber:5 color:1];
        });
    });
}

Tasks 1-3 are immediately dispatched, and tasks 4 and 5 are dispatched 0.5 seconds later. Task 3 is using a barrier. Tasks 1 and 5 are on queue1, and tasks 2-4 are on queue2. All tasks take one second each.

That results in the following. (I manually highlighted those task numbers to make this more clear.)

enter image description here

You can see that task #5 on queue 1 starts as soon as it's queued, even though (a) it was the last task queued, and (b) queue 2 has a barrier on task #3. The second queue respects the barrier on task 3, though.

FYI, this these are the utility methods that generate those points of interest ranges:

- (void)taskOnQueue:(uint32_t)code taskNumber:(uint32_t)arg1 color:(uint32_t)arg4 {
    [self pointOfInterest:code arg1:arg1 color:arg4 block:^{
        [NSThread sleepForTimeInterval:1];
    }];
}

- (void)pointOfInterest:(uint32_t)code arg1:(uint32_t)arg1 color:(uint32_t)arg4 block:(void (^)(void))block {
    kdebug_signpost_start(code, arg1, 0, 0, arg4);
    block();
    kdebug_signpost_end(code, arg1, 0, 0, arg4);
}

NB: The converse is a completely different issue. Queues will be affected if their target queue has a barrier. If the target queue is blocked (for example, if you change task 3 to run with a barrier on the target queue, queue1, instead), then tasks on the second queue will wait for its target queue to free up:

- (void)experiment2 {
    dispatch_queue_t queue1 = dispatch_queue_create("1", DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t queue2 = dispatch_queue_create_with_target("2", DISPATCH_QUEUE_CONCURRENT, queue1);

    dispatch_async(queue1, ^{
        [self taskOnQueue:1 taskNumber:1 color:1];
    });
    dispatch_async(queue2, ^{
        [self taskOnQueue:2 taskNumber:2 color:0];
    });
    dispatch_barrier_async(queue1, ^{              // changed to queue 1
        [self taskOnQueue:1 taskNumber:3 color:1];
    });

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        dispatch_async(queue2, ^{
            [self taskOnQueue:2 taskNumber:4 color:0];
        });
        dispatch_async(queue1, ^{
            [self taskOnQueue:1 taskNumber:5 color:1];
        });
    });
}

That will result in:

enter image description here

Here, task 3 was dispatched with a barrier (where that first Ⓢ signpost is), and not only did it not start until task 1 was done on the target queue, but task 4 (running on the second queue) on the second queue (dispatched where that second Ⓢ signpost is) waited for that barrier on its queue's target queue, too, just like task 5 did.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • 1
    You really went the extra mile.Thank you. I only recently started playing with concurrent queues and find the documentation slightly lacking, though this is intuitive behavior. – xtravar Dec 26 '18 at 06:36