<NME> DispatchTimer.swift
<BEF> //
//  ChronosTests.swift
//  Chronos
//
//  Copyright (c) 2015 Andrew Chun, Comyar Zaheri. All rights reserved.
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to
//  deal in the Software without restriction, including without limitation the
//  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
//  sell copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in
//  all copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
//  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
//  IN THE SOFTWARE.
//


// Mark:- Imports

import Foundation


// Mark:- Constants and Functions

private let queuePrefix = "com.chronos.dispatchTimer"

// MARK:- DispatchTimer Implementation

/**
A DispatchTimer allows you to create a Grand Central Dispatch-based timer
object. A timer waits until a certain time interval has elapsed and then
fires, executing a given closure.

A timer has limited accuracy when determining the exact moment to fire; the
actual time at which a timer fires can potentially be a significant period
of time after the scheduled firing time. However, successive fires are
guarenteed to occur in order.
*/
@objc
@available (iOS, introduced: 8.0)
@available (OSX, introduced: 10.10)
open class DispatchTimer : NSObject, RepeatingTimer {
  
    fileprivate var valid       = State.invalid
    fileprivate var running     = State.paused
    fileprivate var timer:  DispatchSourceTimer
    fileprivate var leeway: UInt64 {
        return UInt64(0.05 * interval) * NSEC_PER_SEC;
    }
    private let timebaseNumer: Double
    private let timebaseDenom: Double
    
    // MARK: Properties
    
    /**
    The timer's execution queue.
    */
    open let queue: DispatchQueue!
    
    /**
    The timer's execution interval, in seconds.
    */
    open let interval: Double!
    
    /**
    The timer's execution closure.
    */
    open let closure: ExecutionClosure!
    
    /**
    The number of times the execution closure has been executed.
    */
    open fileprivate(set) var count = 0
    
    /**
    true, if the timer is valid; otherwise, false.
    
    A timer is considered valid if it has not been canceled.
    */
    open var isValid: Bool {
        return (valid == State.valid)
    }
    
    /**
    true, if the timer is currently running; otherwise, false.
    */
    open var isRunning: Bool {
        return (running == State.running)
    }
    
    // MARK: NSObject
    override fileprivate init() { fatalError("Cannot initialize with init(). Use convenience or designated initializer.") }
    deinit { cancel() }
    
    // MARK: Creating a Dispatch Timer
    
    /**
    Creates a DispatchTimer object.
    
    - parameter interval:        The execution interval, in seconds.
    - parameter closure:         The closure to execute at the given interval.
    
    - returns: A newly created DispatchTimer object.
    */
    convenience public init(interval: Double, closure: @escaping ExecutionClosure) {
        let name = "\(queuePrefix).\(UUID().uuidString)"
        let queue = DispatchQueue(label: name, attributes: [])
        self.init(interval: interval, closure: closure, queue: queue)
    }
    
    /**
    Creates a DispatchTimer object.
    
    - parameter interval:        The execution interval, in seconds.
  
    // MARK: NSObject

    override private init() {}
    deinit { cancel() }

    // MARK: Creating a Dispatch Timer
      self.timer = DispatchSource.makeTimerSource(queue: queue)
      self.valid = State.valid
      self.queue      = queue
      self.interval   = interval
      self.closure    = closure
      
      //set timebase info
      var info = mach_timebase_info(numer: 0, denom: 0)
      mach_timebase_info(&info)
      self.timebaseNumer = Double(info.numer)
      self.timebaseDenom = Double(info.denom)
        
      super.init()
      
      weak var weakSelf: DispatchTimer? = self
      
      timer.setEventHandler {
        if let strongSelf = weakSelf {
          strongSelf.closure(strongSelf, strongSelf.count)
          strongSelf.count += 1
        }
      }
        :returns: A newly created DispatchTimer object.
    */
    convenience public init(interval: NSTimeInterval, closure: ExecutionClosure, queue: dispatch_queue_t) {
        self.init(interval: interval, closure: closure, queue: queue, nil)
    }

    /**
    - parameter now:     true, if the timer should fire immediately.
    */
    open func start(_ now: Bool) {
        validate()
        if OSAtomicCompareAndSwap32Barrier(State.paused, State.running, &running) {
          timer.scheduleRepeating(deadline: startTime(interval, now: now),
                                  interval:.nanoseconds(Int((interval * self.timebaseNumer) / self.timebaseDenom)))
        :returns: A newly created DispatchTimer object.
    */
    public init(interval: NSTimeInterval, closure: ExecutionClosure, queue: dispatch_source_t, failureClosure: FailureClosure) {
        super.init()
        timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue)
        if let timer = timer {
            self.queue    = queue
            self.interval = interval
            self.closure  = closure

            valid = State.valid
            dispatch_source_set_event_handler(timer) {
                closure(self, self.count)
                ++self.count
            }
        } else {
            if let failureClosure = failureClosure {
                failureClosure()
            timer.suspend()
                println("Failed to create dispatch source for timer.")
            }
        }
    }

    // MARK: Using a Dispatch Timer
    fileprivate func validate() {
        if valid != State.valid {
            NSException(name: NSExceptionName.internalInconsistencyException,
                reason: "Attempting to use invalid DispatchTimer",
                userInfo: nil).raise()
    */
    public func start(now: Bool) {
        validate()
        if OSAtomicCompareAndSwap32Barrier(State.paused, State.running, &running) {
            dispatch_source_set_timer(timer, startTime(interval, now), UInt64(interval * Double(NSEC_PER_SEC)), leeway)
            dispatch_resume(timer)
        }
     */
    public func pause() {
        validate()
        if OSAtomicCompareAndSwap32Barrier(State.running, State.paused, &running) {
            dispatch_suspend(timer)
        }
    }

<MSG> Updated DispatchTimer to Swift 1.2

<DFF> @@ -124,7 +124,7 @@ public class DispatchTimer : NSObject {
   
     // MARK: NSObject
 
-    override private init() {}
+    override private init() { fatalError("Cannot initialize with init(). Use convenience or designated initializer.") }
     deinit { cancel() }
 
     // MARK: Creating a Dispatch Timer
@@ -153,7 +153,7 @@ public class DispatchTimer : NSObject {
         :returns: A newly created DispatchTimer object.
     */
     convenience public init(interval: NSTimeInterval, closure: ExecutionClosure, queue: dispatch_queue_t) {
-        self.init(interval: interval, closure: closure, queue: queue, nil)
+        self.init(interval: interval, closure: closure, queue: queue, failureClosure: nil)
     }
 
     /**
@@ -167,18 +167,10 @@ public class DispatchTimer : NSObject {
         :returns: A newly created DispatchTimer object.
     */
     public init(interval: NSTimeInterval, closure: ExecutionClosure, queue: dispatch_source_t, failureClosure: FailureClosure) {
-        super.init()
-        timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue)
-        if let timer = timer {
-            self.queue    = queue
-            self.interval = interval
-            self.closure  = closure
-
-            valid = State.valid
-            dispatch_source_set_event_handler(timer) {
-                closure(self, self.count)
-                ++self.count
-            }
+        
+        if let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue) {
+            self.timer = timer
+            self.valid = State.valid
         } else {
             if let failureClosure = failureClosure {
                 failureClosure()
@@ -186,6 +178,19 @@ public class DispatchTimer : NSObject {
                 println("Failed to create dispatch source for timer.")
             }
         }
+        
+        self.queue = queue
+        self.interval = interval
+        self.closure = closure
+        
+        super.init()
+        
+        if let timer = timer {
+            dispatch_source_set_event_handler(timer) {
+                closure(self, self.count)
+                ++self.count
+            }
+        }
     }
 
     // MARK: Using a Dispatch Timer
@@ -197,7 +202,7 @@ public class DispatchTimer : NSObject {
     */
     public func start(now: Bool) {
         validate()
-        if OSAtomicCompareAndSwap32Barrier(State.paused, State.running, &running) {
+        if let timer = timer where OSAtomicCompareAndSwap32Barrier(State.paused, State.running, &running) {
             dispatch_source_set_timer(timer, startTime(interval, now), UInt64(interval * Double(NSEC_PER_SEC)), leeway)
             dispatch_resume(timer)
         }
@@ -208,7 +213,7 @@ public class DispatchTimer : NSObject {
      */
     public func pause() {
         validate()
-        if OSAtomicCompareAndSwap32Barrier(State.running, State.paused, &running) {
+        if let timer = timer where OSAtomicCompareAndSwap32Barrier(State.running, State.paused, &running) {
             dispatch_suspend(timer)
         }
     }

Updated DispatchTimer to Swift 1.2