Stack with Timeout

Stack with 5s timeout:

class TimedStack
  def initialize(timeout: 5)
    @mutex = Mutex.new
    @queue = []
    @resource = ConditionVariable.new
    @timeout = timeout
  end

  def push(obj)
    @mutex.synchronize do
      @queue.push(obj)
      @resource.broadcast
    end
  end

  def pop(timeout: nil)
    wait_time = timeout || @timeout

    @mutex.synchronize do
      if @queue.empty?
        to_wait = wait_time + now

        while @queue.empty? && (remaining = to_wait - now) > 0
          @resource.wait(@mutex, remaining)
        end
      end

      @queue.shift
    end
  end

  private

  def now
    Process.clock_gettime(Process::CLOCK_MONOTONIC)
  end
end