Remove `ParasiticTask`, now `host` is a built-in parameter for all tasks.
This commit is contained in:
parent
95ab16f3f7
commit
4242f84f07
|
@ -32,7 +32,6 @@
|
|||
OBJ_48 /* Interval.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* Interval.swift */; };
|
||||
OBJ_49 /* Lock.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_13 /* Lock.swift */; };
|
||||
OBJ_50 /* Monthday.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_14 /* Monthday.swift */; };
|
||||
OBJ_51 /* ParasiticTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_15 /* ParasiticTask.swift */; };
|
||||
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 */; };
|
||||
|
@ -82,7 +81,6 @@
|
|||
OBJ_12 /* Interval.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Interval.swift; sourceTree = "<group>"; };
|
||||
OBJ_13 /* Lock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Lock.swift; sourceTree = "<group>"; };
|
||||
OBJ_14 /* Monthday.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Monthday.swift; sourceTree = "<group>"; };
|
||||
OBJ_15 /* ParasiticTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParasiticTask.swift; sourceTree = "<group>"; };
|
||||
OBJ_16 /* Period.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Period.swift; sourceTree = "<group>"; };
|
||||
OBJ_17 /* Schedule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Schedule.swift; sourceTree = "<group>"; };
|
||||
OBJ_18 /* Task.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Task.swift; sourceTree = "<group>"; };
|
||||
|
@ -222,7 +220,6 @@
|
|||
OBJ_8 /* Schedule */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
OBJ_15 /* ParasiticTask.swift */,
|
||||
66D9F43221563D7700D9F441 /* RunLoopTask.swift */,
|
||||
OBJ_17 /* Schedule.swift */,
|
||||
OBJ_18 /* Task.swift */,
|
||||
|
@ -352,7 +349,6 @@
|
|||
OBJ_48 /* Interval.swift in Sources */,
|
||||
OBJ_49 /* Lock.swift in Sources */,
|
||||
OBJ_50 /* Monthday.swift in Sources */,
|
||||
OBJ_51 /* ParasiticTask.swift in Sources */,
|
||||
OBJ_52 /* Period.swift in Sources */,
|
||||
OBJ_53 /* Schedule.swift in Sources */,
|
||||
OBJ_54 /* Task.swift in Sources */,
|
||||
|
|
|
@ -9,24 +9,34 @@ import Foundation
|
|||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
|
||||
class DeinitObserver<T: AnyObject> {
|
||||
private var deinitObserverKey: Void = ()
|
||||
|
||||
private weak var observed: T?
|
||||
class DeinitObserver {
|
||||
|
||||
private var block: () -> Void
|
||||
private(set) weak var observable: AnyObject?
|
||||
|
||||
private var block: (() -> Void)?
|
||||
|
||||
private init(_ block: @escaping () -> Void) {
|
||||
self.block = block
|
||||
}
|
||||
|
||||
static func observe(_ observed: T, whenDeinit: @escaping () -> Void) {
|
||||
let observer = DeinitObserver(whenDeinit)
|
||||
var key: Void = ()
|
||||
objc_setAssociatedObject(observed, &key, observer, .OBJC_ASSOCIATION_RETAIN)
|
||||
@discardableResult
|
||||
static func observe(_ observable: AnyObject, whenDeinit block: @escaping () -> Void) -> DeinitObserver {
|
||||
let observer = DeinitObserver(block)
|
||||
objc_setAssociatedObject(observable, &deinitObserverKey, observer, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
|
||||
return observer
|
||||
}
|
||||
|
||||
func clear() {
|
||||
block = nil
|
||||
if let o = observable {
|
||||
objc_setAssociatedObject(o, &deinitObserverKey, nil, .OBJC_ASSOCIATION_ASSIGN)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
block()
|
||||
block?()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
//
|
||||
// ParasiticTask.swift
|
||||
// Schedule
|
||||
//
|
||||
// Created by Quentin Jin on 2018/7/17.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension Schedule {
|
||||
|
||||
/// Schedules a task with this schedule.
|
||||
///
|
||||
/// This method will receive a `host` object as a parameter,
|
||||
/// the returned task will not retain this object, instead,
|
||||
/// it will observe this object, when this object is dealloced,
|
||||
/// the task will not be scheduled any more, something like parasitism.
|
||||
///
|
||||
/// This feature is very useful when you want a scheduled task live and die
|
||||
/// with a controller.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - queue: The queue to which the task will be dispatched.
|
||||
/// - tag: The tag to be associated to the task.
|
||||
/// - host: The object to be hosted on.
|
||||
/// - onElapse: The action to do when time is out.
|
||||
/// - Returns: The task just created.
|
||||
@discardableResult
|
||||
public func `do`(queue: DispatchQueue,
|
||||
tag: String? = nil,
|
||||
host: AnyObject,
|
||||
onElapse: @escaping (Task) -> Void) -> Task {
|
||||
return ParasiticTask(schedule: self, queue: queue, tag: tag, host: host, onElapse: onElapse)
|
||||
}
|
||||
|
||||
/// Schedules a task with this schedule.
|
||||
///
|
||||
/// This method will receive a `host` object as a parameter,
|
||||
/// the returned task will not retain this object, instead,
|
||||
/// it will observe this object, when this object is dealloced,
|
||||
/// the task will not scheduled any more, something like parasitism.
|
||||
///
|
||||
/// This feature is very useful when you want a scheduled task live and die
|
||||
/// with a controller.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - queue: The queue to which the task will be dispatched.
|
||||
/// - tag: The tag to be associated to the task.
|
||||
/// - host: The object to be hosted on.
|
||||
/// - onElapse: The action to do when time is out.
|
||||
/// - Returns: The task just created.
|
||||
@discardableResult
|
||||
public func `do`(queue: DispatchQueue,
|
||||
tag: String? = nil,
|
||||
host: AnyObject,
|
||||
onElapse: @escaping () -> Void) -> Task {
|
||||
return self.do(queue: queue, tag: tag, host: host, onElapse: { (_) in onElapse() })
|
||||
}
|
||||
}
|
||||
|
||||
private final class ParasiticTask: Task {
|
||||
|
||||
weak var parasitifer: AnyObject?
|
||||
|
||||
init(schedule: Schedule, queue: DispatchQueue?, tag: String?, host: AnyObject, onElapse: @escaping (Task) -> Void) {
|
||||
super.init(schedule: schedule, queue: queue, tag: tag) { (task) in
|
||||
guard (task as? ParasiticTask)?.parasitifer != nil else {
|
||||
task.cancel()
|
||||
return
|
||||
}
|
||||
onElapse(task)
|
||||
}
|
||||
self.parasitifer = host
|
||||
|
||||
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
|
||||
DeinitObserver.observe(host) { [weak self] in
|
||||
self?.cancel()
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -11,48 +11,30 @@ extension Schedule {
|
|||
|
||||
/// Schedules a task with this schedule.
|
||||
///
|
||||
/// This method will receive a `host` object as a parameter,
|
||||
/// the returned task will not retain this object, instead,
|
||||
/// it will observe this object, when this object is dealloced,
|
||||
/// the task will not be scheduled any more, something like parasitism.
|
||||
///
|
||||
/// This feature is very useful when you want a scheduled task live and die
|
||||
/// with a controller.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - queue: The queue to which the task will be dispatched.
|
||||
/// - tag: The tag to be associated to the task.
|
||||
/// - mode: The mode in which to add the schedule.
|
||||
/// - host: The object to be hosted on.
|
||||
/// - onElapse: The action to do when time is out.
|
||||
/// - Returns: The task just created.
|
||||
@discardableResult
|
||||
public func `do`(mode: RunLoop.Mode = .default,
|
||||
tag: String? = nil,
|
||||
host: AnyObject? = nil,
|
||||
onElapse: @escaping (Task) -> Void) -> Task {
|
||||
return RunLoopTask(schedule: self, mode: mode, tag: tag, onElapse: onElapse)
|
||||
return RunLoopTask(schedule: self, mode: mode, host: host, onElapse: onElapse)
|
||||
}
|
||||
|
||||
/// Schedules a task with this schedule.
|
||||
///
|
||||
/// This method will receive a `host` object as a parameter,
|
||||
/// the returned task will not retain this object, instead,
|
||||
/// it will observe this object, when this object is dealloced,
|
||||
/// the task will not scheduled any more, something like parasitism.
|
||||
///
|
||||
/// This feature is very useful when you want a scheduled task live and die
|
||||
/// with a controller.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - queue: The queue to which the task will be dispatched.
|
||||
/// - tag: The tag to be associated to the task.
|
||||
/// - mode: The mode in which to add the schedule.
|
||||
/// - host: The object to be hosted on.
|
||||
/// - onElapse: The action to do when time is out.
|
||||
/// - Returns: The task just created.
|
||||
@discardableResult
|
||||
public func `do`(mode: RunLoop.Mode = .default,
|
||||
tag: String? = nil,
|
||||
host: AnyObject? = nil,
|
||||
onElapse: @escaping () -> Void) -> Task {
|
||||
return self.do(mode: mode, tag: tag) { (_) in
|
||||
return self.do(mode: mode, host: host) { (_) in
|
||||
onElapse()
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +44,7 @@ private final class RunLoopTask: Task {
|
|||
|
||||
var timer: Timer!
|
||||
|
||||
init(schedule: Schedule, mode: RunLoop.Mode, tag: String?, onElapse: @escaping (Task) -> Void) {
|
||||
init(schedule: Schedule, mode: RunLoop.Mode, host: AnyObject?, onElapse: @escaping (Task) -> Void) {
|
||||
|
||||
var this: Task?
|
||||
|
||||
|
@ -74,7 +56,7 @@ private final class RunLoopTask: Task {
|
|||
|
||||
RunLoop.current.add(timer, forMode: mode)
|
||||
|
||||
super.init(schedule: schedule, queue: nil, tag: tag) { (task) in
|
||||
super.init(schedule: schedule, queue: nil, host: host) { (task) in
|
||||
guard let task = task as? RunLoopTask else { return }
|
||||
task.timer.fireDate = Date()
|
||||
}
|
||||
|
|
|
@ -26,28 +26,30 @@ public struct Schedule {
|
|||
///
|
||||
/// - Parameters:
|
||||
/// - queue: The queue to which the task will be dispatched.
|
||||
/// - tag: The tag to be associated to the task.
|
||||
/// - host: The object to be hosted on. When this object is dealloced,
|
||||
/// the task will not scheduled any more.
|
||||
/// - onElapse: The action to do when time is out.
|
||||
/// - Returns: The task just created.
|
||||
@discardableResult
|
||||
public func `do`(queue: DispatchQueue,
|
||||
tag: String? = nil,
|
||||
host: AnyObject? = nil,
|
||||
onElapse: @escaping (Task) -> Void) -> Task {
|
||||
return Task(schedule: self, queue: queue, tag: tag, onElapse: onElapse)
|
||||
return Task(schedule: self, queue: queue, host: host, onElapse: onElapse)
|
||||
}
|
||||
|
||||
/// Schedules a task with this schedule.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - queue: The queue to which the task will be dispatched.
|
||||
/// - tag: The tag to be associated to the task.
|
||||
/// - host: The object to be hosted on. When this object is dealloced,
|
||||
/// the task will not scheduled any more.
|
||||
/// - onElapse: The action to do when time is out.
|
||||
/// - Returns: The task just created.
|
||||
@discardableResult
|
||||
public func `do`(queue: DispatchQueue,
|
||||
tag: String? = nil,
|
||||
host: AnyObject? = nil,
|
||||
onElapse: @escaping () -> Void) -> Task {
|
||||
return self.do(queue: queue, tag: tag, onElapse: { (_) in onElapse() })
|
||||
return self.do(queue: queue, host: host, onElapse: { (_) in onElapse() })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,10 @@ public class Task {
|
|||
private lazy var _tags: Set<String> = []
|
||||
private lazy var _countOfExecutions: Int = 0
|
||||
|
||||
#if os(Linux)
|
||||
private weak var _host: AnyObject? = TaskHub.shared
|
||||
#endif
|
||||
|
||||
private lazy var _lifetime: Interval = Int.max.second
|
||||
private lazy var _lifetimeTimer: DispatchSourceTimer = {
|
||||
let timer = DispatchSource.makeTimerSource()
|
||||
|
@ -47,8 +51,8 @@ public class Task {
|
|||
}()
|
||||
|
||||
init(schedule: Schedule,
|
||||
queue: DispatchQueue? = nil,
|
||||
tag: String? = nil,
|
||||
queue: DispatchQueue?,
|
||||
host: AnyObject?,
|
||||
onElapse: @escaping (Task) -> Void) {
|
||||
|
||||
_iterator = schedule.makeIterator()
|
||||
|
@ -57,6 +61,14 @@ public class Task {
|
|||
_actions.append(onElapse)
|
||||
|
||||
_timer.setEventHandler { [weak self] in
|
||||
|
||||
#if os(Linux)
|
||||
guard self?._host != nil else {
|
||||
self?.cancel()
|
||||
return
|
||||
}
|
||||
#endif
|
||||
|
||||
self?.elapse()
|
||||
}
|
||||
|
||||
|
@ -65,7 +77,18 @@ public class Task {
|
|||
_timer.schedule(after: interval)
|
||||
_timeline.estimatedNextExecution = Date().adding(interval)
|
||||
|
||||
TaskHub.shared.add(self, withTag: tag)
|
||||
#if os(Linux)
|
||||
_host = host
|
||||
#else
|
||||
if let host = host {
|
||||
DeinitObserver.observe(host) { [weak self] in
|
||||
self?.cancel()
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
TaskHub.shared.add(self)
|
||||
|
||||
_timer.resume()
|
||||
}
|
||||
|
||||
|
@ -341,9 +364,6 @@ public class Task {
|
|||
public func removeTag(_ tag: String) {
|
||||
removeTags(tag)
|
||||
}
|
||||
}
|
||||
|
||||
extension Task {
|
||||
|
||||
/// Suspends all tasks that have the tag.
|
||||
public static func suspend(byTag tag: String) {
|
||||
|
|
Loading…
Reference in New Issue