Skip to content

Commit

Permalink
Added synchronized access inside WeakSet and for global subscriptions (
Browse files Browse the repository at this point in the history
  • Loading branch information
jguz-pubnub authored Sep 13, 2024
1 parent 4952f41 commit a72d552
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 37 deletions.
9 changes: 7 additions & 2 deletions .pubnub.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
---
name: swift
scm: github.com/pubnub/swift
version: "7.3.2"
version: "7.3.3"
schema: 1
changelog:
- date: 2024-09-13
version: 7.3.3
changes:
- type: bug
text: "Added synchronized access inside `WeakSet` and for global subscriptions."
- date: 2024-07-22
version: 7.3.2
changes:
Expand Down Expand Up @@ -564,7 +569,7 @@ sdks:
- distribution-type: source
distribution-repository: GitHub release
package-name: PubNub
location: https://github.com/pubnub/swift/archive/refs/tags/7.3.2.zip
location: https://github.com/pubnub/swift/archive/refs/tags/7.3.3.zip
supported-platforms:
supported-operating-systems:
macOS:
Expand Down
16 changes: 8 additions & 8 deletions PubNub.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3847,7 +3847,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 7.3.2;
MARKETING_VERSION = 7.3.3;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
Expand Down Expand Up @@ -3898,7 +3898,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 7.3.2;
MARKETING_VERSION = 7.3.3;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
Expand Down Expand Up @@ -4006,7 +4006,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 7.3.2;
MARKETING_VERSION = 7.3.3;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
Expand Down Expand Up @@ -4059,7 +4059,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 7.3.2;
MARKETING_VERSION = 7.3.3;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
Expand Down Expand Up @@ -4180,7 +4180,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 7.3.2;
MARKETING_VERSION = 7.3.3;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
Expand Down Expand Up @@ -4232,7 +4232,7 @@
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 7.3.2;
MARKETING_VERSION = 7.3.3;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
Expand Down Expand Up @@ -4712,7 +4712,7 @@
"$(TOOLCHAIN_DIR)/usr/lib/swift/macosx",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 7.3.2;
MARKETING_VERSION = 7.3.3;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
Expand Down Expand Up @@ -4754,7 +4754,7 @@
"$(TOOLCHAIN_DIR)/usr/lib/swift/macosx",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 7.3.2;
MARKETING_VERSION = 7.3.3;
MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++14";
OTHER_CFLAGS = "$(inherited)";
OTHER_LDFLAGS = "$(inherited)";
Expand Down
2 changes: 1 addition & 1 deletion PubNubSwift.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'PubNubSwift'
s.version = '7.3.2'
s.version = '7.3.3'
s.homepage = 'https://github.com/pubnub/swift'
s.documentation_url = 'https://www.pubnub.com/docs/swift-native/pubnub-swift-sdk'
s.authors = { 'PubNub, Inc.' => '[email protected]' }
Expand Down
2 changes: 1 addition & 1 deletion Sources/PubNub/Helpers/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public enum Constant {

static let pubnubSwiftSDKName: String = "PubNubSwift"

static let pubnubSwiftSDKVersion: String = "7.3.2"
static let pubnubSwiftSDKVersion: String = "7.3.3"

static let appBundleId: String = {
if let info = Bundle.main.infoDictionary,
Expand Down
30 changes: 19 additions & 11 deletions Sources/PubNub/Helpers/WeakBox.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,43 +29,51 @@ final class WeakBox<Element>: Hashable where Element: AnyObject, Element: Hashab
}

struct WeakSet<Element> where Element: AnyObject, Element: Hashable {
private var elements: Set<WeakBox<Element>> = []
private var elements: Atomic<Set<WeakBox<Element>>> = Atomic([])

init(_ elements: [Element]) {
elements.forEach { self.elements.update(with: WeakBox($0)) }
self.elements.lockedWrite { [elements] currentValue in
elements.forEach { element in
currentValue.update(with: WeakBox(element))
}
}
}

// NSSet Operations
var allObjects: [Element] {
return elements.compactMap { $0.underlying }
return elements.lockedRead { $0.compactMap { $0.underlying } }
}

var count: Int {
return self.elements.count
elements.lockedRead { $0.count }
}

mutating func update(_ element: Element) {
elements.update(with: WeakBox(element))
elements.lockedWrite { [element] in
$0.update(with: WeakBox(element))
}
}

mutating func remove(_ element: Element) {
elements.remove(WeakBox(element))
elements.lockedWrite { [element] in
$0.remove(WeakBox(element))
}
}

mutating func removeAll() {
elements.removeAll()
elements.lockedWrite { $0 = Set<WeakBox<Element>>() }
}
}

extension WeakSet: Collection {
var startIndex: Set<WeakBox<Element>>.Index { return elements.startIndex }
var endIndex: Set<WeakBox<Element>>.Index { return elements.endIndex }
var startIndex: Set<WeakBox<Element>>.Index { return elements.lockedRead { $0.startIndex } }
var endIndex: Set<WeakBox<Element>>.Index { return elements.lockedRead { $0.endIndex } }

subscript(position: Set<WeakBox<Element>>.Index) -> Element? {
return elements[position].underlying
elements.lockedRead { $0[position].underlying }
}

func index(after index: Set<WeakBox<Element>>.Index) -> Set<WeakBox<Element>>.Index {
return elements.index(after: index)
elements.lockedRead { $0.index(after: index) }
}
}
51 changes: 37 additions & 14 deletions Sources/PubNub/Subscription/SubscriptionSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ class SubscriptionSession: EventEmitter, StatusEmitter {
return statusListener
}()

private var globalChannelSubscriptions: [String: Subscription] = [:]
private var globalGroupSubscriptions: [String: Subscription] = [:]
private var globalChannelSubscriptions: Atomic<[String: Subscription]> = Atomic([:])
private var globalGroupSubscriptions: Atomic<[String: Subscription]> = Atomic([:])
private let strategy: any SubscriptionSessionStrategy

init(
Expand Down Expand Up @@ -125,16 +125,29 @@ class SubscriptionSession: EventEmitter, StatusEmitter {
and: channelGroupSubscriptions,
at: cursor?.timetoken
)
for subscription in channelSubscriptions {
subscription.subscriptionNames.compactMap { $0 }.forEach {
globalChannelSubscriptions[$0] = subscription

let channelSubsToMerge = channelSubscriptions.reduce(
into: [String: Subscription]()
) { accumulatedValue, subscription in
subscription.subscriptionNames.forEach {
accumulatedValue[$0] = subscription
}
}
for subscription in channelGroupSubscriptions {
subscription.subscriptionNames.compactMap { $0 }.forEach {
globalGroupSubscriptions[$0] = subscription

let channelGroupSubsToMerge = channelGroupSubscriptions.reduce(
into: [String: Subscription]()
) { accumulatedValue, subscription in
subscription.subscriptionNames.forEach {
accumulatedValue[$0] = subscription
}
}

globalChannelSubscriptions.lockedWrite {
$0.merge(channelSubsToMerge) { _, new in new }
}
globalGroupSubscriptions.lockedWrite {
$0.merge(channelGroupSubsToMerge) { _, new in new }
}
}

// MARK: - Reconnect
Expand Down Expand Up @@ -163,15 +176,25 @@ class SubscriptionSession: EventEmitter, StatusEmitter {
presenceOnly ? [$0.presenceChannelName] : [$0, $0.presenceChannelName]
}
internalUnsubscribe(
from: globalChannelSubscriptions.compactMap { channelNamesToUnsubscribe.contains($0.key) ? $0.value : nil },
and: globalGroupSubscriptions.compactMap { groupNamesToUnsubscribe.contains($0.key) ? $0.value : nil },
from: globalChannelSubscriptions.lockedRead { $0.compactMap {
channelNamesToUnsubscribe.contains($0.key) ? $0.value : nil
} },
and: globalGroupSubscriptions.lockedRead { $0.compactMap {
groupNamesToUnsubscribe.contains($0.key) ? $0.value : nil
} },
presenceOnly: presenceOnly
)
channelNamesToUnsubscribe.forEach {
globalChannelSubscriptions.removeValue(forKey: $0)

globalChannelSubscriptions.lockedWrite { currentContainer in
channelNamesToUnsubscribe.forEach {
currentContainer.removeValue(forKey: $0)
}
}
groupNamesToUnsubscribe.forEach {
globalGroupSubscriptions.removeValue(forKey: $0)

globalGroupSubscriptions.lockedWrite { currentContainer in
groupNamesToUnsubscribe.forEach {
currentContainer.removeValue(forKey: $0)
}
}
}

Expand Down

0 comments on commit a72d552

Please sign in to comment.