Improve the implementaion of task center
This commit is contained in:
parent
e008b0671a
commit
4bb334fda4
|
@ -18,23 +18,21 @@ open class Task {
|
||||||
|
|
||||||
// MARK: - Private properties
|
// MARK: - Private properties
|
||||||
|
|
||||||
private let _lock = NSRecursiveLock()
|
private let _lock = NSLock()
|
||||||
|
|
||||||
private var _iterator: AnyIterator<Interval>
|
private var _iterator: AnyIterator<Interval>
|
||||||
private let _timer: DispatchSourceTimer
|
private let _timer: DispatchSourceTimer
|
||||||
|
|
||||||
private lazy var _actions = Bag<Action>()
|
private var _actions = Bag<Action>()
|
||||||
|
|
||||||
private lazy var _suspensionCount: Int = 0
|
private var _suspensionCount = 0
|
||||||
private lazy var _executionCount: Int = 0
|
private var _executionCount = 0
|
||||||
|
|
||||||
private lazy var _executionDates: [Date]? = nil
|
private var _executionDates: [Date]?
|
||||||
private lazy var _estimatedNextExecutionDate: Date? = nil
|
private var _estimatedNextExecutionDate: Date?
|
||||||
|
|
||||||
private weak var _taskCenter: TaskCenter?
|
private var _taskCenter: TaskCenter?
|
||||||
private let _taskCenterLock = NSRecursiveLock()
|
private var _tags: Set<String> = []
|
||||||
|
|
||||||
private var associateKey = 1
|
|
||||||
|
|
||||||
// MARK: - Public properties
|
// MARK: - Public properties
|
||||||
|
|
||||||
|
@ -99,31 +97,6 @@ open class Task {
|
||||||
return _lock.withLock { _taskCenter }
|
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
|
// MARK: - Init
|
||||||
|
|
||||||
|
@ -164,7 +137,7 @@ open class Task {
|
||||||
_suspensionCount -= 1
|
_suspensionCount -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
_taskCenter?.remove(self)
|
self.removeFromTaskCenter()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func elapse() {
|
private func elapse() {
|
||||||
|
@ -208,11 +181,14 @@ open class Task {
|
||||||
|
|
||||||
/// Reschedules this task with the new plan.
|
/// Reschedules this task with the new plan.
|
||||||
public func reschedule(_ new: Plan) {
|
public func reschedule(_ new: Plan) {
|
||||||
_lock.withLockVoid {
|
_lock.lock()
|
||||||
if _timer.isCancelled { return }
|
if _timer.isCancelled {
|
||||||
|
_lock.unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
_iterator = new.makeIterator()
|
_iterator = new.makeIterator()
|
||||||
}
|
_lock.unlock()
|
||||||
scheduleNextExecution()
|
scheduleNextExecution()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,6 +245,29 @@ open class Task {
|
||||||
_actions.removeAll()
|
_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 {
|
extension Task: Hashable {
|
||||||
|
@ -280,6 +279,6 @@ extension Task: Hashable {
|
||||||
|
|
||||||
/// Returns a boolean value indicating whether two tasks are equal.
|
/// Returns a boolean value indicating whether two tasks are equal.
|
||||||
public static func == (lhs: Task, rhs: Task) -> Bool {
|
public static func == (lhs: Task, rhs: Task) -> Bool {
|
||||||
return lhs === rhs
|
return lhs.id == rhs.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
private let _default = TaskCenter()
|
|
||||||
|
|
||||||
extension TaskCenter {
|
extension TaskCenter {
|
||||||
|
|
||||||
private class TaskBox: Hashable {
|
private class TaskBox: Hashable {
|
||||||
|
@ -27,6 +25,8 @@ extension TaskCenter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private let _default = TaskCenter()
|
||||||
|
|
||||||
/// A task center that enables batch operation.
|
/// A task center that enables batch operation.
|
||||||
open class TaskCenter {
|
open class TaskCenter {
|
||||||
|
|
||||||
|
@ -41,30 +41,33 @@ open class TaskCenter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds the given task to this center.
|
/// Adds the given task to this center.
|
||||||
|
///
|
||||||
|
/// Please note: task center will not retain tasks.
|
||||||
open func add(_ task: Task) {
|
open func add(_ task: Task) {
|
||||||
task.addToTaskCenter(self)
|
task.addToTaskCenter(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addSimply(_ task: Task) {
|
||||||
lock.withLockVoid {
|
lock.withLockVoid {
|
||||||
let box = TaskBox(task)
|
let box = TaskBox(task)
|
||||||
self.tasks[box] = []
|
self.tasks[box] = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes the given task from this center.
|
func removeSimply(_ task: Task) {
|
||||||
open func remove(_ task: Task) {
|
|
||||||
task.removeFromTaskCenter(self)
|
|
||||||
|
|
||||||
lock.withLockVoid {
|
lock.withLockVoid {
|
||||||
let box = TaskBox(task)
|
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 {
|
for tag in tags {
|
||||||
self.tags[tag]?.remove(box)
|
self.tags[tag]?.remove(box)
|
||||||
if self.tags[tag]?.count == 0 {
|
if self.tags[tag]?.count == 0 {
|
||||||
self.tags[tag] = nil
|
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.
|
/// If the task is not in this center, do nothing.
|
||||||
open func addTags(_ tags: [String], to task: Task) {
|
open func addTags(_ tags: [String], to task: Task) {
|
||||||
guard task.taskCenter === self else { return }
|
|
||||||
|
|
||||||
lock.withLockVoid {
|
lock.withLockVoid {
|
||||||
let box = TaskBox(task)
|
let box = TaskBox(task)
|
||||||
|
guard self.tasks[box] != nil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for tag in tags {
|
for tag in tags {
|
||||||
tasks[box]?.insert(tag)
|
self.tasks[box]?.insert(tag)
|
||||||
if self.tags[tag] == nil {
|
if self.tags[tag] == nil {
|
||||||
self.tags[tag] = []
|
self.tags[tag] = []
|
||||||
}
|
}
|
||||||
|
@ -104,10 +109,12 @@ open class TaskCenter {
|
||||||
///
|
///
|
||||||
/// If the task is not in this center, do nothing.
|
/// If the task is not in this center, do nothing.
|
||||||
open func removeTags(_ tags: [String], from task: Task) {
|
open func removeTags(_ tags: [String], from task: Task) {
|
||||||
guard task.taskCenter === self else { return }
|
|
||||||
|
|
||||||
lock.withLockVoid {
|
lock.withLockVoid {
|
||||||
let box = TaskBox(task)
|
let box = TaskBox(task)
|
||||||
|
guard self.tasks[box] != nil else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for tag in tags {
|
for tag in tags {
|
||||||
self.tasks[box]?.remove(tag)
|
self.tasks[box]?.remove(tag)
|
||||||
self.tags[tag]?.remove(box)
|
self.tags[tag]?.remove(box)
|
||||||
|
@ -122,8 +129,6 @@ open class TaskCenter {
|
||||||
///
|
///
|
||||||
/// If the task is not in this center, return an empty array.
|
/// If the task is not in this center, return an empty array.
|
||||||
open func tags(forTask task: Task) -> [String] {
|
open func tags(forTask task: Task) -> [String] {
|
||||||
guard task.taskCenter === self else { return [] }
|
|
||||||
|
|
||||||
return lock.withLock {
|
return lock.withLock {
|
||||||
Array(tasks[TaskBox(task)] ?? [])
|
Array(tasks[TaskBox(task)] ?? [])
|
||||||
}
|
}
|
||||||
|
@ -152,9 +157,8 @@ open class TaskCenter {
|
||||||
|
|
||||||
/// Removes all tasks from this center.
|
/// Removes all tasks from this center.
|
||||||
open func removeAll() {
|
open func removeAll() {
|
||||||
lock.withLockVoid {
|
allTasks.forEach {
|
||||||
tasks = [:]
|
$0.removeFromTaskCenter()
|
||||||
tags = [:]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ final class TaskCenterTests: XCTestCase {
|
||||||
let tag = UUID().uuidString
|
let tag = UUID().uuidString
|
||||||
center.addTag(tag, to: task)
|
center.addTag(tag, to: task)
|
||||||
|
|
||||||
center.remove(task)
|
task.removeFromTaskCenter()
|
||||||
|
|
||||||
XCTAssertFalse(center.allTasks.contains(task))
|
XCTAssertFalse(center.allTasks.contains(task))
|
||||||
XCTAssertFalse(center.allTags.contains(tag))
|
XCTAssertFalse(center.allTags.contains(tag))
|
||||||
|
|
|
@ -53,10 +53,7 @@ final class TaskTests: XCTestCase {
|
||||||
let task = Plan.never.do { }
|
let task = Plan.never.do { }
|
||||||
XCTAssertTrue(task.taskCenter === TaskCenter.default)
|
XCTAssertTrue(task.taskCenter === TaskCenter.default)
|
||||||
|
|
||||||
task.removeFromTaskCenter(TaskCenter())
|
task.removeFromTaskCenter()
|
||||||
XCTAssertNotNil(task.taskCenter)
|
|
||||||
|
|
||||||
task.removeFromTaskCenter(task.taskCenter!)
|
|
||||||
XCTAssertNil(task.taskCenter)
|
XCTAssertNil(task.taskCenter)
|
||||||
|
|
||||||
let center = TaskCenter()
|
let center = TaskCenter()
|
||||||
|
|
Loading…
Reference in New Issue