Timer.swift 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. /*
  2. * Copyright 2024, gRPC Authors All rights reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package import NIOCore
  17. /// A timer backed by `NIOScheduledCallback`.
  18. package final class Timer<Handler: NIOScheduledCallbackHandler> where Handler: Sendable {
  19. /// The event loop on which to run this timer.
  20. private let eventLoop: any EventLoop
  21. /// The duration of the timer.
  22. private let duration: TimeAmount
  23. /// Whether this timer should repeat.
  24. private let repeating: Bool
  25. /// The handler to call when the timer fires.
  26. private let handler: Handler
  27. /// The currently scheduled callback if the timer is running.
  28. private var scheduledCallback: NIOScheduledCallback?
  29. package init(eventLoop: any EventLoop, duration: TimeAmount, repeating: Bool, handler: Handler) {
  30. self.eventLoop = eventLoop
  31. self.duration = duration
  32. self.repeating = repeating
  33. self.handler = handler
  34. self.scheduledCallback = nil
  35. }
  36. /// Cancel the timer, if it is running.
  37. package func cancel() {
  38. self.eventLoop.assertInEventLoop()
  39. guard let scheduledCallback = self.scheduledCallback else { return }
  40. scheduledCallback.cancel()
  41. }
  42. /// Start or restart the timer.
  43. package func start() {
  44. self.eventLoop.assertInEventLoop()
  45. self.scheduledCallback?.cancel()
  46. // Only throws if the event loop is shutting down, so we'll just swallow the error here.
  47. self.scheduledCallback = try? self.eventLoop.scheduleCallback(in: self.duration, handler: self)
  48. }
  49. }
  50. extension Timer: NIOScheduledCallbackHandler, @unchecked Sendable where Handler: Sendable {
  51. /// For repeated timer support, the timer itself proxies the callback and restarts the timer.
  52. ///
  53. /// - NOTE: Users should not call this function directly.
  54. package func handleScheduledCallback(eventLoop: some EventLoop) {
  55. self.eventLoop.assertInEventLoop()
  56. self.handler.handleScheduledCallback(eventLoop: eventLoop)
  57. if self.repeating { self.start() }
  58. }
  59. }