Michael Ozeryansky
Michael Ozeryansky

Reputation: 8043

What happens if my DispatchGroup never finishes

I have many asynchronous tasks that need to all be completed before I can move on, so I'm using a DispatchGroup. However, I am able to tell if one of the tasks fails early, and I would usually call a completion handler.

If I leave the scope of the function by calling a completion handler, what happens to the DispatchGroup?

Is the memory allocated forever? Is it possible that if leave is called enough times eventually (maybe due to a bug) that the notify block can still be called?

Example:

func example(completion: @escaping (Bool) - Void) {
    let group = DispatchGroup()

    group.enter()
    asyncFunction1 {
        if result == false {
            completion(false)
        } else {
            group.leave()
        }
    }

    group.enter()
    asyncFunction2 { result in
        if result == true {
            group.leave()
        }
    }

    group.notify(queue: .main) {
        completion(true)
    }
}

In the example above I have two asynchronous functions. The first function might call completion(false), and the second function only calls leave on success. While it might not be the best example of code, these conditions are possible. What happens to the notify block?

Upvotes: 3

Views: 3147

Answers (3)

Michael Ozeryansky
Michael Ozeryansky

Reputation: 8043

From the swift's source on GCD: https://github.com/apple/swift-corelibs-libdispatch/blob/master/src/semaphore.c

It seems the block will be allocated and never released. Meaning, the memory the block retains will also never be released.

Upvotes: 5

matt
matt

Reputation: 534958

I'm wondering what happens when leave is never called. Just because it must be called, doesn't mean it always will be called.

Well, don't "never call" it. You must arrange your code so that leave is called by every possible exit path. If you can't, don't use dispatch groups.

If necessary, you can pass the dispatch group itself into the completion handler so that it can call leave for you. But one way or another, call leave.

Upvotes: -1

zisoft
zisoft

Reputation: 23078

The dispatchgroup must be notified whenever a code block enters the group as well as whenever a codeblock leaves the group.

That means, dispatchGroup.leave() must be called regardless of success or failure of your function.

When all blocks are finished, the dispatchgroup gets notified.

Upvotes: 1

Related Questions