Sha256: 83120b97a1e46434f8b8ee5d95ad675ec095ee2c3be1bc684968e76e1ea86ad9

Contents?: true

Size: 1.16 KB

Versions: 2

Compression:

Stored size: 1.16 KB

Contents

# frozen_string_literal: true

# A mechanism for waiting until a timer expires or until another thread signals
# readiness.
class ServiceSkeleton::HurriableTimer
  def initialize(timeout)
    @mutex = Mutex.new
    @condition = ConditionVariable.new
    @end_time = now + timeout
    @hurried = false
  end

  # Wait for the timer to elapse
  #
  # Any number of threads can wait on the same HurriableTimer
  def wait(t = nil)
    end_time =
      if t
        [@end_time, now + t].min
      else
        @end_time
      end

    @mutex.synchronize {
      while true
        remaining = end_time - now

        if remaining < 0 || @hurried
          break
        else
          @condition.wait(@mutex, remaining)
        end
      end
    }

    nil
  end

  # Cause the timer to trigger early if it hasn't already expired
  #
  # This method is idempotent
  def hurry!
    @mutex.synchronize {
      @hurried = true
      @condition.broadcast
    }

    nil
  end

  def expired?
    @hurried || @end_time - now < 0
  end

  private

  def now
    # Using this instead of Time.now, because it isn't affected by NTP updates
    Process.clock_gettime(Process::CLOCK_MONOTONIC_RAW)
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
service_skeleton-2.2.0 lib/service_skeleton/hurriable_timer.rb
service_skeleton-2.1.0 lib/service_skeleton/hurriable_timer.rb