IOS Operations Synchronization Task

I have 3 steps: A

, B

, C

.

  • A

    , B

    can be processed simultaneously
  • If it C

    works A

    and B

    must wait
  • if A

    or B

    works C

    must wait

I would solve it with a dispatch group and a semaphore:

public var dgLoadMain = dispatch_group_create()
public var semaLoadMain = dispatch_semaphore_create(1)

      

A

, B

Will look like this:

dispatch_group_enter(dgLoadMain)
dispatch_semaphore_wait(semaLoadMain, DISPATCH_TIME_FOREVER)
dispatch_semaphore_signal(semaLoadMain) //maybe odd, but right after wait, it signals, it just check wether C is in critical section, if not, release semaphore, and let other B or A continue too
//..
dispatch_group_leave(dgLoadMain)

      

C

will look like this:

dispatch_group_wait(dgLoadMain, DISPATCH_TIME_FOREVER)
dispatch_semaphore_wait(semaLoadMain, DISPATCH_TIME_FOREVER)
//..
dispatch_semaphore_signal(semaLoadMain)

      

Do you think everything is okay?

+3


source to share


2 answers


dispatch_barrier_async

more difficult. Take a look at this code. It's Objective-C, but the same concept works great in Swift.

#import <Foundation/Foundation.h>

void A()
{
    NSLog(@"A begin");
    sleep(1);
    NSLog(@"A end");
}

void B()
{
    NSLog(@"B begin");
    sleep(1);
    NSLog(@"B end");
}

void C()
{
    NSLog(@"C begin");
    sleep(1);
    NSLog(@"C end");
}

int main()
{
    dispatch_queue_t q = dispatch_queue_create("ABC", DISPATCH_QUEUE_CONCURRENT);

    dispatch_queue_t qA = dispatch_queue_create("A", DISPATCH_QUEUE_SERIAL);
    dispatch_set_target_queue(qA, q);

    dispatch_queue_t qB = dispatch_queue_create("B", DISPATCH_QUEUE_SERIAL);
    dispatch_set_target_queue(qB, q);

    dispatch_barrier_async(q, ^{C();});
    dispatch_async(qA, ^{A();});
    dispatch_async(qA, ^{A();});
    dispatch_async(qB, ^{B();});
    dispatch_barrier_async(q, ^{C();});
    dispatch_async(qB, ^{B();});
    dispatch_barrier_async(q, ^{C();});
    dispatch_async(qA, ^{A();});

    dispatch_main();
    return 0;
}

      



Result.

C begin
C end
A begin
B begin
A end
B end
B begin
A begin
B end
A end
A begin
A end
C begin
C end
C begin
C end

      

+1


source


Your solution probably works, but reasoning about it was painful. I came up with what I thought was a cleaner solution. It uses 2 semaphores. It basically combines task A and task B and treats them as one task. And then it uses the timeout property to check if Task A or Task B has been executed previously and is passed to the first semaphore accordingly. Here's the code:



let semaphore = dispatch_semaphore_create(1);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
let ABSema = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
    print("A")
    if !Bool(dispatch_semaphore_wait(ABSema, DISPATCH_TIME_NOW))
    {
        dispatch_semaphore_signal(ABSema)
    }
    else
    {
        dispatch_semaphore_signal(semaphore)
    }

})
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
    print("B")
    if !Bool(dispatch_semaphore_wait(ABSema, DISPATCH_TIME_NOW))
    {
        dispatch_semaphore_signal(ABSema)
    }
    else
    {
        dispatch_semaphore_signal(semaphore)
    }
})


dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
    print("C")
    dispatch_semaphore_signal(semaphore)
})

      

0


source







All Articles