Class: QuackConcurrency::ConditionVariable::Waitable

Inherits:
Object
  • Object
show all
Defined in:
lib/quack_concurrency/condition_variable/waitable.rb

Overview

Used to put threads to sleep and wake them back up in order. A given mutex will be unlocked while the thread sleeps. When waking a thread it will ensure the mutex is relocked before wakng the next thread. Threads will be woken in the chronological order that #wait was called.

Direct Known Subclasses

SafeConditionVariable::Waitable

Instance Method Summary collapse

Constructor Details

#initialize(condition_variable) ⇒ ConditionVariable



12
13
14
15
16
17
18
# File 'lib/quack_concurrency/condition_variable/waitable.rb', line 12

def initialize(condition_variable)
  @condition_variable = condition_variable
  @complete_condition_variable = ::ConditionVariable.new
  @mutex = ::Mutex.new
  @sleeper = Sleeper.new
  @state = :inital
end

Instance Method Details

#resumeBoolean

Request the sleeping thread to wake. It will return false if the thread was already woken,

possibly due to an interrupt or calling +Thread#run+, etc.

Returns:

  • (Boolean)

    if the thread was successfully woken during this call



24
25
26
27
28
29
30
31
32
33
# File 'lib/quack_concurrency/condition_variable/waitable.rb', line 24

def resume
  @mutex.synchronize do
    if @state == :complete
      false
    else
      @sleeper.wake
      true
    end
  end
end

#wait(mutex, timeout) ⇒ self

Note:

Will block until resumed

Puts this thread to sleep until #resume is called. Unlocks mutex while sleeping It will ensure that previous sleeping threads have resumed before mutex is relocked.

Parameters:

  • mutex (Mutex)

    mutex to be unlocked while this thread is sleeping

  • timeout (nil, Numeric)

    maximum time to sleep in seconds, nil for forever

Returns:

  • (self)

Raises:

  • (TypeError)

    if timeout is not nil or Numeric

  • (ArgumentError)

    if timeout is negative

  • (Exception)

    any exception raised by ::ConditionVariable#wait (eg. interrupts, ThreadError)



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/quack_concurrency/condition_variable/waitable.rb', line 45

def wait(mutex, timeout)
  # ideally we would would check if this thread can sleep (ie. is not the last thread alive)
  #   before we unlock the mutex, however I am not sure that it can be implemented
  if mutex.respond_to?(:unlock!)
    mutex.unlock! { sleep(timeout) }
  else
    mutex_unlock(mutex) { sleep(timeout) }
  end
ensure
  @mutex.synchronize do
    @condition_variable.waitable_woken(self)
    @state = :complete
    @complete_condition_variable.broadcast
  end
end

#wait_until_resumedvoid

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.

Wait until thread has woken and relocked the mutex. Will block until thread has resumed. Will not block if #resume has already been called.



66
67
68
69
70
# File 'lib/quack_concurrency/condition_variable/waitable.rb', line 66

def wait_until_resumed
  @mutex.synchronize do
    @complete_condition_variable.wait(@mutex) unless @state == :complete
  end
end