Class: CallbackTimer

Inherits:
Object
  • Object
show all
Defined in:
lib/callback_timer.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(callback:, duration:) ⇒ CallbackTimer

Creates and starts a new CallbackTimer.

Parameters:

  • callback (#to_proc)
  • duration (Numeric)

    non-negative number specified in seconds

Raises:

  • (ArgumentError)


75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/callback_timer.rb', line 75

def initialize(callback: , duration: )
  raise ArgumentError, "'callback' must respond to 'to_proc'" unless callback.respond_to?(:to_proc)
  @callback = callback.to_proc
  unless duration.is_a?(Numeric) && duration >= 0
    raise ArgumentError, "'duration' must be a non-negative Numeric"
  end
  @start_time = Time.now
  @deadline = @start_time + duration
  @mutex = Mutex.new
  @complete = false
  self.class.add(self)
end

Instance Attribute Details

#deadlineTime (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Time that the CallbackTimer should call it’s callback.

Returns:

  • (Time)


69
70
71
# File 'lib/callback_timer.rb', line 69

def deadline
  @deadline
end

Class Method Details

.add(timer) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Add CallbackTimer to the scheduler.

Parameters:



17
18
19
20
21
22
23
24
25
26
# File 'lib/callback_timer.rb', line 17

def self.add(timer)
  @mutex.synchronize do
    @timers.push(timer)
    @timers.sort_by!(&:deadline)
    if @timers.first == timer
      @condition_variable.signal
    end
  end
  nil
end

.cancel(timer) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Remove CallbackTimer from scheduler.

Parameters:



32
33
34
35
36
37
38
# File 'lib/callback_timer.rb', line 32

def self.cancel(timer)
  @mutex.synchronize do
    @condition_variable.signal if @timers.first == timer
    @timers.delete(timer)
  end
  nil
end

.worker_loopvoid

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Scheduler worker loop to run in it’s own thread.



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/callback_timer.rb', line 43

def self.worker_loop
  @mutex.lock
  loop do
    next_timer = @timers.first
    unless next_timer
      @condition_variable.wait(@mutex)
      next
    end
    next_deadline = next_timer.deadline
    duration = next_deadline - Time.now
    @condition_variable.wait(@mutex, duration) if duration.positive?
    if @timers.first != next_timer
      # timer may have been canceled or a new timer has been added to @timers with an earlier deadline
      next
    end
    @timers.shift
    @mutex.unlock
    next_timer.time_has_elapsed
    @mutex.lock
  end
  nil
end

Instance Method Details

#cancelvoid

This method returns an undefined value.

Cancels the CallbackTimer. Will ignore if already called or if callback has already been called.



91
92
93
94
95
96
97
98
# File 'lib/callback_timer.rb', line 91

def cancel
  @mutex.synchronize do
    return if @complete
    @complete = true
  end
  self.class.cancel(self)
  nil
end

#time_has_elapsedvoid

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Tells CallbackTimer it has reached it’s deadline.



103
104
105
106
107
108
109
110
111
# File 'lib/callback_timer.rb', line 103

def time_has_elapsed
  @mutex.synchronize do
    return if @complete
    @complete = true
  end
  elapsed_time = Time.now - @start_time
  @callback.call(elapsed_time)
  nil
end