From ccf4bb676f802cc7db354fc2aa5a398a072f5151 Mon Sep 17 00:00:00 2001 From: Pravin Prakash Kumar Date: Wed, 19 May 2021 13:52:25 -0700 Subject: [PATCH] [MOB-14325] - Adding few more essential API to ThreadSafePrimitives (#629) * Making the Webview of fullscreen message public * [MOB-14325] - Adding more essential API to ThreadSafePrimitives * [AMSDK-14325] - Fix warnings * [AMSDK-14325] - Better unittest * [MOB-14325] - run swift format --- .../Sources/utility/ThreadSafeArray.swift | 13 ++++++++++- .../utility/ThreadSafeDictionary.swift | 5 ++++ .../Tests/utility/ThreadSafeArrayTests.swift | 23 +++++++++++++++++++ .../utility/ThreadSafeDictionaryTests.swift | 14 +++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) diff --git a/AEPServices/Sources/utility/ThreadSafeArray.swift b/AEPServices/Sources/utility/ThreadSafeArray.swift index 49db1c022..eee634ae5 100644 --- a/AEPServices/Sources/utility/ThreadSafeArray.swift +++ b/AEPServices/Sources/utility/ThreadSafeArray.swift @@ -22,7 +22,7 @@ public final class ThreadSafeArray { queue = DispatchQueue(label: identifier) } - /// Appends a new element safetly to the array + /// Appends a new element to the thread safe array public func append(_ newElement: T) { queue.async { self.array.append(newElement) @@ -36,6 +36,17 @@ public final class ThreadSafeArray { } } + /// Removes and returns the first element of the thread safe array. + /// Returns nil if the array is empty + public func removeFirst() -> T? { + queue.sync { + if array.isEmpty { + return nil + } + return self.array.removeFirst() + } + } + /// Returns if the array is empty or not public var isEmpty: Bool { return queue.sync { return self.array.isEmpty } diff --git a/AEPServices/Sources/utility/ThreadSafeDictionary.swift b/AEPServices/Sources/utility/ThreadSafeDictionary.swift index a3f020742..581f7c4e3 100644 --- a/AEPServices/Sources/utility/ThreadSafeDictionary.swift +++ b/AEPServices/Sources/utility/ThreadSafeDictionary.swift @@ -29,6 +29,11 @@ public final class ThreadSafeDictionary { return queue.sync { return self.dictionary.keys.count } } + /// A collection containing just the keys of the dictionary. + public var keys: [K] { + return queue.sync { return Array(self.dictionary.keys) } + } + // Gets a non-thread-safe shallow copy of the backing dictionary public var shallowCopy: [K: V] { return queue.sync { diff --git a/AEPServices/Tests/utility/ThreadSafeArrayTests.swift b/AEPServices/Tests/utility/ThreadSafeArrayTests.swift index c9b27b414..8ae8ae1d2 100644 --- a/AEPServices/Tests/utility/ThreadSafeArrayTests.swift +++ b/AEPServices/Tests/utility/ThreadSafeArrayTests.swift @@ -198,6 +198,29 @@ class ThreadSafeArrayTests: XCTestCase { XCTAssertEqual(tsArray.count, 0) } + + // Tests that removes first item from an array + func testRemoveFirst() { + let tsArray = ThreadSafeArray() + + // test removeFirst on empty array + XCTAssertNil(tsArray.removeFirst()) + + // setup + tsArray.append("One") + tsArray.append("Two") + + // test + XCTAssertEqual(tsArray.removeFirst(), "One") + XCTAssertEqual(tsArray.count, 1) + + // test + XCTAssertEqual(tsArray.removeFirst(), "Two") + XCTAssertEqual(tsArray.count, 0) + + + } + // Tests that the .shallowCopy functionality doesn't deadlock against the backing array func testShallowCopyNoDeadlock() { let count = 1000 diff --git a/AEPServices/Tests/utility/ThreadSafeDictionaryTests.swift b/AEPServices/Tests/utility/ThreadSafeDictionaryTests.swift index ad6bcdce7..c7814e4f3 100644 --- a/AEPServices/Tests/utility/ThreadSafeDictionaryTests.swift +++ b/AEPServices/Tests/utility/ThreadSafeDictionaryTests.swift @@ -139,6 +139,20 @@ class ThreadSafeDictionaryTests: XCTestCase { } } + func testGetKeys() { + let count = 100 + let testDictionary = ThreadSafeDictionary() + + // get keys on empty dictionary + XCTAssertEqual(testDictionary.keys,[]) + + for i in 0 ..< count { + testDictionary[i] = i + } + + XCTAssertEqual(testDictionary.keys.count, count) + } + private func dispatchSyncWithDict(i: Int) { dispatchQueueSerial.sync { self.threadSafeDict?[0] = i