diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2019-12-03 17:04:16 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2019-12-04 11:50:55 +0100 |
| commit | be52f38567de1680025fffbc8a5b023c440a201e (patch) | |
| tree | 3d8242e2e5ea243a1cad05f76adc89b8ae5cc5ad | |
| parent | 1cee8ea368e6b25bac96c9ceac36b6b8ada3df8b (diff) | |
| download | mullvadvpn-be52f38567de1680025fffbc8a5b023c440a201e.tar.xz mullvadvpn-be52f38567de1680025fffbc8a5b023c440a201e.zip | |
Add MutuallyExclusive publisher
| -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 |
