From 3de74c73a23817f53c80798ede3ceb79d14788d2 Mon Sep 17 00:00:00 2001 From: QuentinJin Date: Sun, 26 Aug 2018 19:05:24 +0800 Subject: [PATCH] Remove WeakSet, rename TaskCenter to TaskHub --- Schedule.xcodeproj/project.pbxproj | 24 ++-- Sources/Schedule/Monthday.swift | 12 +- Sources/Schedule/Task.swift | 14 +-- .../{TaskCenter.swift => TaskHub.swift} | 31 +++-- Sources/Schedule/WeakSet.swift | 69 ----------- Sources/Schedule/Weekday.swift | 10 +- Tests/ScheduleTests/TaskCenterTests.swift | 53 --------- Tests/ScheduleTests/TaskHubTests.swift | 62 ++++++++++ Tests/ScheduleTests/WeakSetTests.swift | 107 ------------------ Tests/ScheduleTests/XCTestManifests.swift | 10 +- 10 files changed, 116 insertions(+), 276 deletions(-) rename Sources/Schedule/{TaskCenter.swift => TaskHub.swift} (65%) delete mode 100644 Sources/Schedule/WeakSet.swift delete mode 100644 Tests/ScheduleTests/TaskCenterTests.swift create mode 100644 Tests/ScheduleTests/TaskHubTests.swift delete mode 100644 Tests/ScheduleTests/WeakSetTests.swift diff --git a/Schedule.xcodeproj/project.pbxproj b/Schedule.xcodeproj/project.pbxproj index 1d40694..47312d2 100644 --- a/Schedule.xcodeproj/project.pbxproj +++ b/Schedule.xcodeproj/project.pbxproj @@ -31,10 +31,9 @@ OBJ_52 /* Period.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_16 /* Period.swift */; }; OBJ_53 /* Schedule.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_17 /* Schedule.swift */; }; OBJ_54 /* Task.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_18 /* Task.swift */; }; - OBJ_55 /* TaskCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_19 /* TaskCenter.swift */; }; + OBJ_55 /* TaskHub.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_19 /* TaskHub.swift */; }; OBJ_56 /* Time.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_20 /* Time.swift */; }; OBJ_57 /* Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_21 /* Timeline.swift */; }; - OBJ_58 /* WeakSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_22 /* WeakSet.swift */; }; OBJ_59 /* Weekday.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_23 /* Weekday.swift */; }; OBJ_66 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; }; OBJ_77 /* AtomicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_26 /* AtomicTests.swift */; }; @@ -43,9 +42,8 @@ OBJ_80 /* ExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_29 /* ExtensionsTests.swift */; }; OBJ_81 /* Misc.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_30 /* Misc.swift */; }; OBJ_82 /* SchedulesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_31 /* SchedulesTests.swift */; }; - OBJ_83 /* TaskCenterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_32 /* TaskCenterTests.swift */; }; + OBJ_83 /* TaskHubTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_32 /* TaskHubTests.swift */; }; OBJ_84 /* TaskTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_33 /* TaskTests.swift */; }; - OBJ_85 /* WeakSetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_34 /* WeakSetTests.swift */; }; OBJ_86 /* XCTestManifests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_35 /* XCTestManifests.swift */; }; OBJ_88 /* Schedule.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "Schedule::Schedule::Product" /* Schedule.framework */; }; /* End PBXBuildFile section */ @@ -85,10 +83,9 @@ OBJ_16 /* Period.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Period.swift; sourceTree = ""; }; OBJ_17 /* Schedule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Schedule.swift; sourceTree = ""; }; OBJ_18 /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = ""; }; - OBJ_19 /* TaskCenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskCenter.swift; sourceTree = ""; }; + OBJ_19 /* TaskHub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskHub.swift; sourceTree = ""; }; OBJ_20 /* Time.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Time.swift; sourceTree = ""; }; OBJ_21 /* Timeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timeline.swift; sourceTree = ""; }; - OBJ_22 /* WeakSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakSet.swift; sourceTree = ""; }; OBJ_23 /* Weekday.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Weekday.swift; sourceTree = ""; }; OBJ_26 /* AtomicTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtomicTests.swift; sourceTree = ""; }; OBJ_27 /* BucketTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BucketTests.swift; sourceTree = ""; }; @@ -96,9 +93,8 @@ OBJ_29 /* ExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionsTests.swift; sourceTree = ""; }; OBJ_30 /* Misc.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Misc.swift; sourceTree = ""; }; OBJ_31 /* SchedulesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SchedulesTests.swift; sourceTree = ""; }; - OBJ_32 /* TaskCenterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskCenterTests.swift; sourceTree = ""; }; + OBJ_32 /* TaskHubTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskHubTests.swift; sourceTree = ""; }; OBJ_33 /* TaskTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskTests.swift; sourceTree = ""; }; - OBJ_34 /* WeakSetTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WeakSetTests.swift; sourceTree = ""; }; OBJ_35 /* XCTestManifests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestManifests.swift; sourceTree = ""; }; OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; OBJ_9 /* Atomic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = ""; }; @@ -146,7 +142,6 @@ OBJ_10 /* Bucket.swift */, OBJ_11 /* Extensions.swift */, OBJ_13 /* Lock.swift */, - OBJ_22 /* WeakSet.swift */, ); name = Utils; sourceTree = ""; @@ -166,7 +161,6 @@ 6695C99A21329DDB00934290 /* UtilsTests */ = { isa = PBXGroup; children = ( - OBJ_34 /* WeakSetTests.swift */, OBJ_26 /* AtomicTests.swift */, OBJ_27 /* BucketTests.swift */, OBJ_29 /* ExtensionsTests.swift */, @@ -188,7 +182,7 @@ OBJ_28 /* DateTimeTests.swift */, OBJ_30 /* Misc.swift */, OBJ_31 /* SchedulesTests.swift */, - OBJ_32 /* TaskCenterTests.swift */, + OBJ_32 /* TaskHubTests.swift */, OBJ_33 /* TaskTests.swift */, OBJ_35 /* XCTestManifests.swift */, 6695C99A21329DDB00934290 /* UtilsTests */, @@ -232,7 +226,7 @@ OBJ_15 /* ParasiticTask.swift */, OBJ_17 /* Schedule.swift */, OBJ_18 /* Task.swift */, - OBJ_19 /* TaskCenter.swift */, + OBJ_19 /* TaskHub.swift */, OBJ_21 /* Timeline.swift */, 668685F5210DD226009305C3 /* DateTime */, 668685F4210DD21A009305C3 /* Utils */, @@ -352,10 +346,9 @@ OBJ_52 /* Period.swift in Sources */, OBJ_53 /* Schedule.swift in Sources */, OBJ_54 /* Task.swift in Sources */, - OBJ_55 /* TaskCenter.swift in Sources */, + OBJ_55 /* TaskHub.swift in Sources */, OBJ_56 /* Time.swift in Sources */, OBJ_57 /* Timeline.swift in Sources */, - OBJ_58 /* WeakSet.swift in Sources */, OBJ_59 /* Weekday.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -378,9 +371,8 @@ OBJ_80 /* ExtensionsTests.swift in Sources */, OBJ_81 /* Misc.swift in Sources */, OBJ_82 /* SchedulesTests.swift in Sources */, - OBJ_83 /* TaskCenterTests.swift in Sources */, + OBJ_83 /* TaskHubTests.swift in Sources */, OBJ_84 /* TaskTests.swift in Sources */, - OBJ_85 /* WeakSetTests.swift in Sources */, OBJ_86 /* XCTestManifests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Sources/Schedule/Monthday.swift b/Sources/Schedule/Monthday.swift index 1797f16..7aaed48 100644 --- a/Sources/Schedule/Monthday.swift +++ b/Sources/Schedule/Monthday.swift @@ -34,6 +34,12 @@ public enum Monthday { case december(Int) + var isToday: Bool { + let lhs = Calendar.gregorian.dateComponents(in: TimeZone.autoupdatingCurrent, from: Date()) + let rhs = toDateComponents() + return lhs.month == rhs.month && lhs.day == rhs.day + } + func toDateComponents() -> DateComponents { var month, day: Int switch self { @@ -55,10 +61,4 @@ public enum Monthday { month: month, day: day) } - - var isToday: Bool { - let lhs = Calendar.gregorian.dateComponents(in: TimeZone.autoupdatingCurrent, from: Date()) - let rhs = toDateComponents() - return lhs.month == rhs.month && lhs.day == rhs.day - } } diff --git a/Sources/Schedule/Task.swift b/Sources/Schedule/Task.swift index 0085f11..df7cb05 100644 --- a/Sources/Schedule/Task.swift +++ b/Sources/Schedule/Task.swift @@ -65,7 +65,7 @@ public class Task { _timer.schedule(after: interval) _timeline.estimatedNextExecution = Date().adding(interval) - TaskCenter.shared.add(self, withTag: tag) + TaskHub.shared.add(self, withTag: tag) _timer.resume() } @@ -166,7 +166,7 @@ public class Task { _lock.withLock { _timer.cancel() } - TaskCenter.shared.remove(self) + TaskHub.shared.remove(self) } // MARK: - Lifecycle @@ -298,7 +298,7 @@ public class Task { _lock.unlock() for tag in set { - TaskCenter.shared.add(tag: tag, to: self) + TaskHub.shared.add(tag: tag, to: self) } } @@ -325,7 +325,7 @@ public class Task { _lock.unlock() for tag in set { - TaskCenter.shared.remove(tag: tag, from: self) + TaskHub.shared.remove(tag: tag, from: self) } } @@ -344,17 +344,17 @@ extension Task { /// Suspends all tasks that have the tag. public static func suspend(byTag tag: String) { - TaskCenter.shared.tasks(forTag: tag).forEach { $0.suspend() } + TaskHub.shared.tasks(forTag: tag).forEach { $0.suspend() } } /// Resumes all tasks that have the tag. public static func resume(byTag tag: String) { - TaskCenter.shared.tasks(forTag: tag).forEach { $0.resume() } + TaskHub.shared.tasks(forTag: tag).forEach { $0.resume() } } /// Cancels all tasks that have the tag. public static func cancel(byTag tag: String) { - TaskCenter.shared.tasks(forTag: tag).forEach { $0.cancel() } + TaskHub.shared.tasks(forTag: tag).forEach { $0.cancel() } } } diff --git a/Sources/Schedule/TaskCenter.swift b/Sources/Schedule/TaskHub.swift similarity index 65% rename from Sources/Schedule/TaskCenter.swift rename to Sources/Schedule/TaskHub.swift index 730b232..88d147b 100644 --- a/Sources/Schedule/TaskCenter.swift +++ b/Sources/Schedule/TaskHub.swift @@ -1,5 +1,5 @@ // -// TaskCenter.swift +// TaskHub.swift // Schedule // // Created by Quentin Jin on 2018/7/17. @@ -7,21 +7,21 @@ import Foundation -final class TaskCenter { +final class TaskHub { - static let shared = TaskCenter() + static let shared = TaskHub() private init() { } private let lock = Lock() private var tasks: Set = [] - private var registry: [String: WeakSet] = [:] + private var registry: [String: Set] = [:] func add(_ task: Task, withTag tag: String? = nil) { lock.withLock { tasks.insert(task) if let tag = tag { if registry[tag] == nil { - registry[tag] = WeakSet() + registry[tag] = [] } registry[tag]?.insert(task) } @@ -31,6 +31,11 @@ final class TaskCenter { func remove(_ task: Task) { lock.withLock { _ = tasks.remove(task) + + let tags = task.tags + for tag in tags { + registry[tag]?.remove(task) + } } } @@ -38,7 +43,7 @@ final class TaskCenter { lock.withLock { guard tasks.contains(task) else { return } if registry[tag] == nil { - registry[tag] = WeakSet() + registry[tag] = [] } registry[tag]?.insert(task) } @@ -52,7 +57,8 @@ final class TaskCenter { func tasks(forTag tag: String) -> [Task] { return lock.withLock { - registry[tag]?.objects ?? [] + guard let tasks = registry[tag] else { return [] } + return Array(tasks) } } @@ -67,4 +73,15 @@ final class TaskCenter { tasks.count } } + + @discardableResult + func clear() -> [Task] { + var holder: [Task] = [] + lock.withLock { + holder = Array(tasks) + tasks = [] + registry = [:] + } + return holder + } } diff --git a/Sources/Schedule/WeakSet.swift b/Sources/Schedule/WeakSet.swift deleted file mode 100644 index 1871c53..0000000 --- a/Sources/Schedule/WeakSet.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// WeakSet.swift -// Schedule -// -// Created by Quentin Jin on 2018/7/25. -// - -import Foundation - -private struct WeakBox { - weak var object: T? - init(_ object: T?) { - self.object = object - } -} - -extension WeakBox: Hashable { - - var hashValue: Int { - guard let object = object else { return 0 } - return ObjectIdentifier(object).hashValue - } - - static func == (lhs: WeakBox, rhs: WeakBox) -> Bool { - return lhs.hashValue == rhs.hashValue - } -} - -/// An alternative to `NSHashTable`, since `NSHashTable` is unavailable on linux. -struct WeakSet { - - private var set = Set>() - - mutating func insert(_ object: T) { - set.insert(WeakBox(object)) - } - - @discardableResult - mutating func remove(_ object: T) -> T? { - return set.remove(WeakBox(object))?.object - } - - func contains(_ object: T) -> Bool { - return set.contains(WeakBox(object)) - } - - func containsNil() -> Bool { - return set.contains(where: { $0.object == nil }) - } - - mutating func purify() { - set = set.filter({ $0.object != nil }) - } - - var objects: [T] { - return set.compactMap({ $0.object }) - } - - var count: Int { - return objects.count - } -} - -extension WeakSet: Sequence { - - func makeIterator() -> AnyIterator { - return AnyIterator(objects.makeIterator()) - } -} diff --git a/Sources/Schedule/Weekday.swift b/Sources/Schedule/Weekday.swift index cb6cee4..abd8b2b 100644 --- a/Sources/Schedule/Weekday.swift +++ b/Sources/Schedule/Weekday.swift @@ -12,14 +12,14 @@ public enum Weekday: Int { case sunday = 1, monday, tuesday, wednesday, thursday, friday, saturday + var isToday: Bool { + return Calendar.gregorian + .dateComponents(in: .autoupdatingCurrent, from: Date()).weekday == rawValue + } + func toDateComponents() -> DateComponents { return DateComponents(calendar: Calendar.gregorian, timeZone: TimeZone.autoupdatingCurrent, weekday: rawValue) } - - var isToday: Bool { - return Calendar.gregorian - .dateComponents(in: .autoupdatingCurrent, from: Date()).weekday == rawValue - } } diff --git a/Tests/ScheduleTests/TaskCenterTests.swift b/Tests/ScheduleTests/TaskCenterTests.swift deleted file mode 100644 index 259a052..0000000 --- a/Tests/ScheduleTests/TaskCenterTests.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// TaskCenterTests.swift -// Schedule -// -// Created by Quentin Jin on 2018/7/25. -// - -import XCTest -@testable import Schedule - -final class TaskCenterTests: XCTestCase { - - func makeTask() -> Task { - return Schedule.never.do { } - } - - var center: TaskCenter { - return TaskCenter.shared - } - - func testAdd() { - let task = makeTask() - center.add(task) - XCTAssertTrue(center.contains(task)) - } - - func testRemove() { - let task = makeTask() - center.add(task) - center.remove(task) - XCTAssertFalse(center.contains(task)) - } - - func testTag() { - let task = makeTask() - let tag0 = UUID().uuidString - center.add(task, withTag: tag0) - XCTAssertTrue(center.tasks(forTag: tag0).contains(task)) - - let tag1 = UUID().uuidString - center.add(tag: tag1, to: task) - XCTAssertTrue(center.tasks(forTag: tag1).contains(task)) - - center.remove(tag: tag0, from: task) - XCTAssertFalse(center.tasks(forTag: tag0).contains(task)) - } - - static var allTests = [ - ("testAdd", testAdd), - ("testRemove", testRemove), - ("testTag", testTag) - ] -} diff --git a/Tests/ScheduleTests/TaskHubTests.swift b/Tests/ScheduleTests/TaskHubTests.swift new file mode 100644 index 0000000..b771dee --- /dev/null +++ b/Tests/ScheduleTests/TaskHubTests.swift @@ -0,0 +1,62 @@ +// +// TaskHubTests.swift +// Schedule +// +// Created by Quentin Jin on 2018/7/25. +// + +import XCTest +@testable import Schedule + +final class TaskHubTests: XCTestCase { + + @discardableResult + func makeTask() -> Task { + return Schedule.never.do { } + } + + var shared: TaskHub { + return TaskHub.shared + } + + func testAdd() { + let task = makeTask() + XCTAssertTrue(shared.contains(task)) + shared.add(task) + XCTAssertEqual(shared.countOfTasks, 1) + } + + func testRemove() { + let task = makeTask() + shared.remove(task) + XCTAssertFalse(shared.contains(task)) + } + + func testTag() { + + let task = makeTask() + let tag0 = UUID().uuidString + shared.add(task, withTag: tag0) + XCTAssertTrue(shared.tasks(forTag: tag0).contains(task)) + + let tag1 = UUID().uuidString + shared.add(tag: tag1, to: task) + XCTAssertTrue(shared.tasks(forTag: tag1).contains(task)) + + shared.remove(tag: tag0, from: task) + XCTAssertFalse(shared.tasks(forTag: tag0).contains(task)) + } + + func testCount() { + shared.clear() + XCTAssertEqual(shared.countOfTasks, 0) + makeTask() + XCTAssertEqual(shared.countOfTasks, 1) + } + + static var allTests = [ + ("testAdd", testAdd), + ("testRemove", testRemove), + ("testTag", testTag) + ] +} diff --git a/Tests/ScheduleTests/WeakSetTests.swift b/Tests/ScheduleTests/WeakSetTests.swift deleted file mode 100644 index 7465ba2..0000000 --- a/Tests/ScheduleTests/WeakSetTests.swift +++ /dev/null @@ -1,107 +0,0 @@ -// -// WeakSetTests.swift -// Schedule -// -// Created by Quentin Jin on 2018/7/25. -// - -import XCTest -@testable import Schedule - -private class Object { } - -final class WeakSetTests: XCTestCase { - - func testInsert() { - var set = WeakSet() - - let block = { - let obj = Object() - set.insert(obj) - } - block() - XCTAssertEqual(set.count, 0) - - let obj = Object() - set.insert(obj) - set.insert(obj) - XCTAssertEqual(set.count, 1) - } - - func testRemove() { - var set = WeakSet() - let obj = Object() - set.insert(obj) - set.remove(obj) - XCTAssertEqual(set.count, 0) - } - - func testContains() { - var set = WeakSet() - - let block = { - let obj = Object() - set.insert(obj) - } - block() - XCTAssertTrue(set.containsNil()) - - let obj = Object() - set.insert(obj) - XCTAssertTrue(set.contains(obj)) - } - - func testObjects() { - var set = WeakSet() - - let obj0 = Object() - let obj1 = Object() - set.insert(obj0) - set.insert(obj1) - - let objs = set.objects - XCTAssertEqual(objs.count, 2) - XCTAssertTrue(objs.contains(where: { $0 === obj0 })) - XCTAssertTrue(objs.contains(where: { $0 === obj1 })) - } - - func testIterator() { - var set = WeakSet() - - let obj0 = Object() - let obj1 = Object() - set.insert(obj0) - set.insert(obj1) - - let it = set.makeIterator() - XCTAssertNotNil(it.next()) - XCTAssertNotNil(it.next()) - XCTAssertNil(it.next()) - } - - func testPurify() { - var set = WeakSet() - - let block = { - let obj = Object() - set.insert(obj) - } - autoreleasepool { - block() - } - - let obj = Object() - set.insert(obj) - - set.purify() - XCTAssertFalse(set.containsNil()) - } - - static var allTests = [ - ("testInsert", testInsert), - ("testRemove", testRemove), - ("testContains", testContains), - ("testObjects", testObjects), - ("testIterator", testIterator) - ] -} diff --git a/Tests/ScheduleTests/XCTestManifests.swift b/Tests/ScheduleTests/XCTestManifests.swift index c4a45f2..9516327 100644 --- a/Tests/ScheduleTests/XCTestManifests.swift +++ b/Tests/ScheduleTests/XCTestManifests.swift @@ -5,13 +5,11 @@ public func allTests() -> [XCTestCaseEntry] { return [ testCase(DateTimeTests.allTests), testCase(SchedulesTests.allTests), - testCase(TaskCenterTests.allTests), - testCase(ExtensionsTests.allTests), - testCase(BucketTests.allTests), - testCase(WeakSetTests.allTests), + testCase(TaskHubTests.allTests), testCase(TaskTests.allTests), - testCase(TaskCenterTests.allTests), - testCase(AtomicTests.allTests) + testCase(AtomicTests.allTests), + testCase(BucketTests.allTests), + testCase(ExtensionsTests.allTests) ] } #endif