-
Notifications
You must be signed in to change notification settings - Fork 1
swift 3.0 #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
swift 3.0 #1
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,70 +1,82 @@ | ||
|
|
||
| import Foundation | ||
|
|
||
| public typealias Queue = DispatchQueue | ||
|
|
||
| public class DispatchQueue { | ||
| open class DispatcherQueue { | ||
|
|
||
| private static let Label = "com.mobilenatives.dispatcher" | ||
|
|
||
| // MARK: Public | ||
|
|
||
| public let isConcurrent: Bool | ||
| open let isConcurrent: Bool | ||
|
|
||
| public var isCurrent: Bool { return dispatch_get_specific(&kCurrentQueue) == getMutablePointer(self) } | ||
| open var isCurrent: Bool { | ||
| return DispatchQueue.getSpecific(key: kCurrentQueue) == getMutablePointer(self) | ||
| } | ||
|
|
||
| public func async (callback: Void -> Void) { | ||
| dispatch_async(dispatch_queue) { callback() } | ||
| open func async (_ callback: @escaping (Void) -> Void) { | ||
| dispatch_queue.async(execute: callback) | ||
| } | ||
|
|
||
| public func sync (callback: Void -> Void) { | ||
| open func sync (_ callback: (Void) -> Void) { | ||
| if isCurrent { callback(); return } // prevent deadlocks! | ||
| dispatch_sync(dispatch_queue) { callback() } | ||
| dispatch_queue.sync(execute: callback) | ||
| } | ||
|
|
||
| public func async <T> (callback: T -> Void) -> T -> Void { | ||
| open func async <T> (_ callback: @escaping (T) -> Void) -> (T) -> Void { | ||
| return { [weak self] value in | ||
| if self == nil { return } | ||
| self!.async { callback(value) } | ||
| guard let strongSelf = self else { return } | ||
| strongSelf.async { callback(value) } | ||
| } | ||
| } | ||
|
|
||
| public func sync <T> (callback: T -> Void) -> T -> Void { | ||
| open func sync <T> (_ callback: @escaping (T) -> Void) -> (T) -> Void { | ||
| return { [weak self] value in | ||
| if self == nil { return } | ||
| self!.sync { callback(value) } | ||
| guard let strongSelf = self else { return } | ||
| strongSelf.sync { callback(value) } | ||
| } | ||
| } | ||
|
|
||
| public let dispatch_queue: dispatch_queue_t | ||
| open let dispatch_queue: DispatchQueue | ||
|
|
||
|
|
||
|
|
||
| // MARK: Internal | ||
|
|
||
| init (_ queue: dispatch_queue_t) { | ||
| init (queue: DispatchQueue) { | ||
| isConcurrent = false | ||
| dispatch_queue = queue | ||
| remember() | ||
| } | ||
| init (_ priority: dispatch_queue_priority_t) { | ||
|
|
||
| init (qos: DispatchQoS.QoSClass) { | ||
| isConcurrent = true | ||
| dispatch_queue = dispatch_get_global_queue(priority, 0) | ||
| dispatch_queue = DispatchQueue.global(qos: qos) | ||
| remember() | ||
| } | ||
|
|
||
| init (_ concurrent: Bool) { | ||
| init (concurrent: Bool) { | ||
| isConcurrent = concurrent | ||
| dispatch_queue = dispatch_queue_create(nil, isConcurrent ? DISPATCH_QUEUE_CONCURRENT : DISPATCH_QUEUE_SERIAL) | ||
|
|
||
| // https://bugs.swift.org/browse/SR-1859 | ||
| if #available(iOS 10.0, *) { | ||
| dispatch_queue = DispatchQueue(label: DispatcherQueue.Label, attributes: isConcurrent ? [DispatchQueue.Attributes.concurrent, DispatchQueue.Attributes.initiallyInactive] : [DispatchQueue.Attributes.initiallyInactive]) | ||
| } else { | ||
| dispatch_queue = isConcurrent ? DispatchQueue(label: DispatcherQueue.Label, attributes: [DispatchQueue.Attributes.concurrent]) : DispatchQueue(label: DispatcherQueue.Label) | ||
| } | ||
| remember() | ||
| } | ||
|
|
||
| func remember () { | ||
| dispatch_queue_set_specific(dispatch_queue, &kCurrentQueue, getMutablePointer(self), nil) | ||
| guard let mutablePointer = getMutablePointer(self) else { | ||
| return | ||
| } | ||
|
|
||
| dispatch_queue.setSpecific(key: kCurrentQueue, value: mutablePointer) | ||
| } | ||
| } | ||
|
|
||
| var kCurrentQueue = 0 | ||
| var kCurrentQueue = DispatchSpecificKey<UnsafeMutableRawPointer>() | ||
|
|
||
| func getMutablePointer (object: AnyObject) -> UnsafeMutablePointer<Void> { | ||
| return UnsafeMutablePointer<Void>(bitPattern: Int(ObjectIdentifier(object).uintValue)) | ||
| func getMutablePointer (_ object: AnyObject) -> UnsafeMutableRawPointer? { | ||
| return UnsafeMutableRawPointer(bitPattern: Int(bitPattern: ObjectIdentifier(object))) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,15 +2,13 @@ | |
| import Foundation | ||
| import UIKit | ||
|
|
||
| public typealias Timer = DispatchTimer | ||
| open class DispatcherTimer { | ||
|
|
||
| public class DispatchTimer { | ||
|
|
||
| public convenience init (_ delay: CGFloat, _ callback: Void -> Void) { | ||
| public convenience init (_ delay: CGFloat, _ callback: @escaping (Void) -> Void) { | ||
| self.init(delay, 0, callback) | ||
| } | ||
|
|
||
| public init (_ delay: CGFloat, _ tolerance: CGFloat, _ callback: Void -> Void) { | ||
| public init (_ delay: CGFloat, _ tolerance: CGFloat, _ callback: @escaping (Void) -> Void) { | ||
| self.callback = callback | ||
| self.tolerance = tolerance | ||
|
|
||
|
|
@@ -20,57 +18,65 @@ public class DispatchTimer { | |
| } | ||
|
|
||
| self.callbackQueue = gcd.current | ||
| self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue.dispatch_queue) | ||
| self.timer = DispatchSource.makeTimerSource(flags: DispatchSource.TimerFlags(rawValue: 0), queue: queue.dispatch_queue) | ||
|
|
||
| if !gcd.main.isCurrent { dispatch_set_target_queue(queue.dispatch_queue, gcd.current.dispatch_queue) } | ||
| if !gcd.main.isCurrent { | ||
| if let dispatch_queue = gcd.current?.dispatch_queue { | ||
| queue.dispatch_queue.setTarget(queue: dispatch_queue) | ||
| } | ||
| } | ||
|
|
||
| let delay_ns = delay * CGFloat(NSEC_PER_SEC) | ||
| let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay_ns)) | ||
| dispatch_source_set_timer(timer, time, UInt64(delay_ns), UInt64(tolerance * CGFloat(NSEC_PER_SEC))) | ||
| dispatch_source_set_event_handler(timer) { [weak self] in let _ = self?.fire() } | ||
| dispatch_resume(timer) | ||
| let time = DispatchTime.now() + Double(delay) | ||
|
|
||
| let interval = DispatchTimeInterval.nanoseconds(Int(delay_ns)) | ||
| let leeway = DispatchTimeInterval.nanoseconds(Int(UInt64(tolerance * CGFloat(NSEC_PER_SEC)))) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe we can avoid double converting to UInt64 and Int
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are we sure that
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you're converting to UInt64 anyway |
||
|
|
||
| timer?.scheduleRepeating(deadline: time, interval: interval, leeway: leeway) | ||
| timer?.setEventHandler { [weak self] in let _ = self?.fire() } | ||
| timer?.resume() | ||
| } | ||
|
|
||
| // MARK: Read-only | ||
|
|
||
| public let tolerance: CGFloat | ||
| open let tolerance: CGFloat | ||
|
|
||
| public let callback: Void -> Void | ||
| open let callback: (Void) -> Void | ||
|
|
||
| // MARK: Instance methods | ||
|
|
||
| public func doRepeat (times: UInt! = nil) { | ||
| open func doRepeat (_ times: UInt! = nil) { | ||
| isRepeating = true | ||
| repeatsLeft = times != nil ? Int(times) : -1 | ||
| } | ||
|
|
||
| public func autorelease () { | ||
| open func autorelease () { | ||
| isAutoReleased = true | ||
| autoReleasedTimers[ObjectIdentifier(self)] = self | ||
| } | ||
|
|
||
| public func fire () { | ||
| open func fire () { | ||
| if OSAtomicAnd32OrigBarrier(1, &invalidated) == 1 { return } | ||
| callbackQueue.sync(callback) | ||
| callbackQueue?.sync(callback) | ||
| if isRepeating && repeatsLeft > 0 { | ||
| repeatsLeft -= 1 | ||
| } | ||
| if !isRepeating || repeatsLeft == 0 { stop() } | ||
| } | ||
|
|
||
| public func stop () { | ||
| open func stop () { | ||
| if OSAtomicTestAndSetBarrier(7, &invalidated) { return } | ||
| queue.sync({dispatch_source_cancel(self.timer)}) | ||
| queue.sync({self.timer?.cancel()}) | ||
| if isAutoReleased { autoReleasedTimers[ObjectIdentifier(self)] = nil } | ||
| } | ||
|
|
||
| // MARK: Internal | ||
|
|
||
| var timer: dispatch_source_t! | ||
| var timer: DispatchSourceTimer? | ||
|
|
||
| let queue: DispatchQueue = gcd.serial() | ||
| let queue: DispatcherQueue = gcd.serial() | ||
|
|
||
| var callbackQueue: DispatchQueue! | ||
| var callbackQueue: DispatcherQueue? | ||
|
|
||
| var invalidated: UInt32 = 0 | ||
|
|
||
|
|
@@ -85,4 +91,4 @@ public class DispatchTimer { | |
| } | ||
| } | ||
|
|
||
| var autoReleasedTimers = [ObjectIdentifier:Timer]() | ||
| var autoReleasedTimers = [ObjectIdentifier:DispatcherTimer]() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this dangerous? Can it collide with NSTimer -> Timer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i can remove it all together but then we'll break the public API of the framework. i don't think it matters actually
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i removed this, Group and Dispatch typealiases