Class: Celluloid::Condition

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

Overview

ConditionVariable-like signaling between tasks and threads

Defined Under Namespace

Classes: Waiter

Instance Method Summary collapse

Constructor Details

#initializeCondition

Returns a new instance of Condition


30
31
32
33
# File 'lib/celluloid/condition.rb', line 30

def initialize
  @mutex = Mutex.new
  @waiters = []
end

Instance Method Details

#broadcast(value = nil) ⇒ Object

Broadcast a value to all waiting tasks and threads


79
80
81
82
83
84
# File 'lib/celluloid/condition.rb', line 79

def broadcast(value = nil)
  @mutex.synchronize do
    @waiters.each { |waiter| waiter << SignalConditionRequest.new(waiter.task, value) }
    @waiters.clear
  end
end

#signal(value = nil) ⇒ Object

Send a signal to the first task waiting on this condition


66
67
68
69
70
71
72
73
74
75
76
# File 'lib/celluloid/condition.rb', line 66

def signal(value = nil)
  @mutex.synchronize do
    if waiter = @waiters.shift
      waiter << SignalConditionRequest.new(waiter.task, value)
    else
      Internals::Logger.with_backtrace(caller(3)) do |logger|
        logger.debug("Celluloid::Condition signaled spuriously")
      end
    end
  end
end

#wait(timeout = nil) ⇒ Object

Wait for the given signal and return the associated value


36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/celluloid/condition.rb', line 36

def wait(timeout = nil)
  fail ConditionError, "cannot wait for signals while exclusive" if Celluloid.exclusive?

  if actor = Thread.current[:celluloid_actor]
    task = Task.current
    if timeout
      bt = caller
      timer = actor.timers.after(timeout) do
        exception = ConditionError.new("timeout after #{timeout.inspect} seconds")
        exception.set_backtrace bt
        task.resume exception
      end
    end
  else
    task = Thread.current
  end
  waiter = Waiter.new(self, task, Celluloid.mailbox, timeout)

  @mutex.synchronize do
    @waiters << waiter
  end

  result = Celluloid.suspend :condwait, waiter
  timer.cancel if timer
  fail result if result.is_a?(ConditionError)
  return yield(result) if block_given?
  result
end