Improve the implementaion of task center

This commit is contained in:
Quentin Jin 2019-07-11 11:05:46 +08:00
parent e008b0671a
commit 4bb334fda4
4 changed files with 72 additions and 72 deletions

View File

@ -18,23 +18,21 @@ open class Task {
// MARK: - Private properties
private let _lock = NSRecursiveLock()
private let _lock = NSLock()
private var _iterator: AnyIterator<Interval>
private let _timer: DispatchSourceTimer
private lazy var _actions = Bag<Action>()
private var _actions = Bag<Action>()
private lazy var _suspensionCount: Int = 0
private lazy var _executionCount: Int = 0
private var _suspensionCount = 0
private var _executionCount = 0
private lazy var _executionDates: [Date]? = nil
private lazy var _estimatedNextExecutionDate: Date? = nil
private var _executionDates: [Date]?
private var _estimatedNextExecutionDate: Date?
private weak var _taskCenter: TaskCenter?
private let _taskCenterLock = NSRecursiveLock()
private var associateKey = 1
private var _taskCenter: TaskCenter?
private var _tags: Set<String> = []
// MARK: - Public properties
@ -99,31 +97,6 @@ open class Task {
return _lock.withLock { _taskCenter }
}
// MARK: - Task center
/// Adds this task to the given task center.
func addToTaskCenter(_ center: TaskCenter) {
_taskCenterLock.lock()
defer { _taskCenterLock.unlock() }
if _taskCenter === center { return }
let c = _taskCenter
_taskCenter = center
c?.remove(self)
}
/// Removes this task from the given task center.
func removeFromTaskCenter(_ center: TaskCenter) {
_taskCenterLock.lock()
defer { _taskCenterLock.unlock() }
if _taskCenter !== center { return }
_taskCenter = nil
center.remove(self)
}
// MARK: - Init
@ -164,7 +137,7 @@ open class Task {
_suspensionCount -= 1
}
_taskCenter?.remove(self)
self.removeFromTaskCenter()
}
private func elapse() {
@ -208,11 +181,14 @@ open class Task {
/// Reschedules this task with the new plan.
public func reschedule(_ new: Plan) {
_lock.withLockVoid {
if _timer.isCancelled { return }
_lock.lock()
if _timer.isCancelled {
_lock.unlock()
return
}
_iterator = new.makeIterator()
}
_lock.unlock()
scheduleNextExecution()
}
@ -269,6 +245,29 @@ open class Task {
_actions.removeAll()
}
}
/// Adds this task to the given task center.
func addToTaskCenter(_ center: TaskCenter) {
_lock.lock(); defer { _lock.unlock() }
if _taskCenter === center { return }
let c = _taskCenter
_taskCenter = center
c?.removeSimply(self)
center.addSimply(self)
}
/// Removes this task from the given task center.
public func removeFromTaskCenter() {
_lock.lock(); defer { _lock.unlock() }
guard let center = self._taskCenter else {
return
}
_taskCenter = nil
center.removeSimply(self)
}
}
extension Task: Hashable {
@ -280,6 +279,6 @@ extension Task: Hashable {
/// Returns a boolean value indicating whether two tasks are equal.
public static func == (lhs: Task, rhs: Task) -> Bool {
return lhs === rhs
return lhs.id == rhs.id
}
}

View File

@ -1,7 +1,5 @@
import Foundation
private let _default = TaskCenter()
extension TaskCenter {
private class TaskBox: Hashable {
@ -27,6 +25,8 @@ extension TaskCenter {
}
}
private let _default = TaskCenter()
/// A task center that enables batch operation.
open class TaskCenter {
@ -41,30 +41,33 @@ open class TaskCenter {
}
/// Adds the given task to this center.
///
/// Please note: task center will not retain tasks.
open func add(_ task: Task) {
task.addToTaskCenter(self)
}
func addSimply(_ task: Task) {
lock.withLockVoid {
let box = TaskBox(task)
self.tasks[box] = []
}
}
/// Removes the given task from this center.
open func remove(_ task: Task) {
task.removeFromTaskCenter(self)
func removeSimply(_ task: Task) {
lock.withLockVoid {
let box = TaskBox(task)
if let tags = self.tasks[box] {
guard let tags = self.tasks[box] else {
return
}
self.tasks[box] = nil
for tag in tags {
self.tags[tag]?.remove(box)
if self.tags[tag]?.count == 0 {
self.tags[tag] = nil
}
}
self.tasks[box] = nil
}
}
}
@ -79,12 +82,14 @@ open class TaskCenter {
///
/// If the task is not in this center, do nothing.
open func addTags(_ tags: [String], to task: Task) {
guard task.taskCenter === self else { return }
lock.withLockVoid {
let box = TaskBox(task)
guard self.tasks[box] != nil else {
return
}
for tag in tags {
tasks[box]?.insert(tag)
self.tasks[box]?.insert(tag)
if self.tags[tag] == nil {
self.tags[tag] = []
}
@ -104,10 +109,12 @@ open class TaskCenter {
///
/// If the task is not in this center, do nothing.
open func removeTags(_ tags: [String], from task: Task) {
guard task.taskCenter === self else { return }
lock.withLockVoid {
let box = TaskBox(task)
guard self.tasks[box] != nil else {
return
}
for tag in tags {
self.tasks[box]?.remove(tag)
self.tags[tag]?.remove(box)
@ -122,8 +129,6 @@ open class TaskCenter {
///
/// If the task is not in this center, return an empty array.
open func tags(forTask task: Task) -> [String] {
guard task.taskCenter === self else { return [] }
return lock.withLock {
Array(tasks[TaskBox(task)] ?? [])
}
@ -152,9 +157,8 @@ open class TaskCenter {
/// Removes all tasks from this center.
open func removeAll() {
lock.withLockVoid {
tasks = [:]
tags = [:]
allTasks.forEach {
$0.removeFromTaskCenter()
}
}

View File

@ -40,7 +40,7 @@ final class TaskCenterTests: XCTestCase {
let tag = UUID().uuidString
center.addTag(tag, to: task)
center.remove(task)
task.removeFromTaskCenter()
XCTAssertFalse(center.allTasks.contains(task))
XCTAssertFalse(center.allTags.contains(tag))

View File

@ -53,10 +53,7 @@ final class TaskTests: XCTestCase {
let task = Plan.never.do { }
XCTAssertTrue(task.taskCenter === TaskCenter.default)
task.removeFromTaskCenter(TaskCenter())
XCTAssertNotNil(task.taskCenter)
task.removeFromTaskCenter(task.taskCenter!)
task.removeFromTaskCenter()
XCTAssertNil(task.taskCenter)
let center = TaskCenter()