1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
   | public protocol BackgroundTimer {     func resume()     func suspend() }
  public class BackgroundTimerMaker {     public static func makeTimer(adding: TimeInterval, task: (()->())?) -> BackgroundTimer {         return BackgroundTimerImp(deadline: .now() + adding, repeating: .never, task: task)     }          public static func makeTimer(adding: TimeInterval, repeatInterval: Int, task: (()->())?) -> BackgroundTimer {         return BackgroundTimerImp(deadline: .now() + adding, repeating: .seconds(repeatInterval), task: task)     }          public static func makeTimer(repeatInterval: Int, task: (()->())?) -> BackgroundTimer {         return BackgroundTimerImp(deadline: .now(), repeating: .seconds(repeatInterval), task: task)     } }
  class BackgroundTimerImp: BackgroundTimer {          private var task: (()->())?          private let _timer: DispatchSourceTimer          private let _lock = NSLock()          private enum State {         case suspended         case resumed     }          private var state: State = .suspended          init(deadline: DispatchTime, repeating: DispatchTimeInterval = .never,          leeway: DispatchTimeInterval = .milliseconds(100), task: (()->())?) {         self.task = task         _timer = DispatchSource.makeTimerSource()         _timer.schedule(deadline: deadline,                         repeating: repeating,                         leeway: leeway)         _timer.setEventHandler(handler: {             task?()         })     }          func resume() {         guard state != .resumed else { return }         _lock.lock()         guard state != .resumed else { return }         state = .resumed         _timer.resume()         defer {             _lock.unlock()         }     }          func suspend() {         guard state != .suspended else { return }         _lock.lock()         guard state != .suspended else { return }         state = .suspended         _timer.suspend()         defer {             _lock.unlock()         }     }          deinit {         
          _timer.setEventHandler {}         _timer.cancel()         resume()         task = nil     } }
 
  |