diff options
Diffstat (limited to 'ios')
| -rw-r--r-- | ios/MullvadVPN/MutuallyExclusive.swift | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/ios/MullvadVPN/MutuallyExclusive.swift b/ios/MullvadVPN/MutuallyExclusive.swift new file mode 100644 index 0000000000..cb3803805a --- /dev/null +++ b/ios/MullvadVPN/MutuallyExclusive.swift @@ -0,0 +1,58 @@ +// +// MutuallyExclusive.swift +// MullvadVPN +// +// Created by pronebird on 24/10/2019. +// Copyright © 2019 Amagicom AB. All rights reserved. +// + +import Combine +import Foundation + +extension Publishers { + + /// A publisher that blocks the given DispatchQueue until the produced publisher reported the + /// completion. + final class MutuallyExclusive<PublisherType, Context>: Publisher where PublisherType: Publisher, Context: Scheduler { + + typealias Output = PublisherType.Output + typealias Failure = PublisherType.Failure + + typealias MakePublisherBlock = () -> PublisherType + + private let exclusivityQueue: Context + private let executionQueue: Context + + private let createPublisher: MakePublisherBlock + + init(exclusivityQueue: Context, executionQueue: Context, createPublisher: @escaping MakePublisherBlock) { + self.exclusivityQueue = exclusivityQueue + self.executionQueue = executionQueue + self.createPublisher = createPublisher + } + + func receive<S>(subscriber: S) where S : Subscriber, S.Failure == Failure, S.Input == Output { + exclusivityQueue.schedule { + let sema = DispatchSemaphore(value: 0) + let releaseLock = { + _ = sema.signal() + } + + self.executionQueue.schedule { + self.createPublisher() + .handleEvents(receiveCompletion: { _ in + releaseLock() + }, receiveCancel: { + releaseLock() + }) + .subscribe(subscriber) + } + + sema.wait() + } + } + } + +} + +typealias MutuallyExclusive = Publishers.MutuallyExclusive |
