Change soft-fail to use the config, rather than env
[rbx.git] / kernel / bootstrap / channel.rb
blob7c89e6b0b9d31b0678baf28c6dffbe9e031d0b51
1 ##
2 # Channel is a FIFO, thread-aware value passing class that can hold any number
3 # of objects similar to Queue.  Use #send to add objects to the channel and
4 # #receive to remove objects from the channel.
6 # If Channel#receive is called on an empty channel, the VM puts the current
7 # Thread (t1) to sleep.  At some future time, when Channel#send is called on
8 # that same thread, the VM wakes up t1 and the value passed to #send is
9 # returned.  This allows us to implement all manner of Thread semantics, such
10 # as Mutex.
12 # Channel is used heavily by Scheduler, to allow ruby code to interact with
13 # the outside world in a thread aware manner.
15 class Channel
17   ivar_as_index :waiting => 1, :value => 2
19   ##
20   # Returns nil if nothing is waiting, or a List object which contains all
21   # Thread objects waiting on this Channel.
23   def waiting() @waiting end
25   ##
26   # Returns nil if there are no values, otherwise a List object containing all
27   # values the Channel contains.
29   def value() @value end
31   ##
32   # Creates a new Channel and registers it with the VM.
34   def self.new
35     Ruby.primitive :channel_new
36     raise PrimitiveFailure, "primitive failed"
37   end
39   ##
40   # Puts +obj+ in the Channel.  If there are waiting threads the first thread
41   # will be woken up and handed +obj+.
43   def send(obj)
44     Ruby.primitive :channel_send
45     raise PrimitiveFailure, "primitive failed"
46   end
48   ##
49   # Removes and returns the first value from the Channel.  If the channel
50   # is empty, Thread.current is put to sleep until #send is called.
52   def receive
53     Ruby.primitive :channel_receive
54     raise PrimitiveFailure, "primitive failed"
55   end
57   ##
58   # Converts +obj+ into a Channel using #to_channel.
60   def self.convert_to_channel(obj)
61     return obj if Channel === obj
62     begin
63       o2 = obj.to_channel
64       unless Channel === o2
65         raise ArgumentError, "to_channel on #{obj.inspect} did not return a Channel"
66       end
67       return o2
68     rescue NoMethodError
69        raise ArgumentError, "Unable to convert #{obj.inspect} into a channel"
70     end
71   end
73   ##
74   # Legacy API. To be removed.
76   def self.receive(obj) # :nodoc:
77     return convert_to_channel(obj).receive
78   end
80   ##
81   # API compliance, returns self.
83   def to_channel
84     self
85   end
87 end