-
Notifications
You must be signed in to change notification settings - Fork 606
/
channel.rb
74 lines (60 loc) · 2.19 KB
/
channel.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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
64
65
66
67
68
69
70
71
72
73
74
##
# Channel is a FIFO, thread-aware value passing class that can hold any number
# of objects similar to Queue. Use #send to add objects to the channel and
# #receive to remove objects from the channel.
#
# If Channel#receive is called on an empty channel, the VM puts the current
# Thread (t1) to sleep. At some future time, when Channel#send is called on
# that same thread, the VM wakes up t1 and the value passed to #send is
# returned. This allows us to implement all manner of Thread semantics, such
# as Mutex.
module Rubinius
class Channel
##
# Returns nil if nothing is waiting, or a List object which contains all
# Thread objects waiting on this Channel.
attr_reader :waiting
##
# Returns nil if there are no values, otherwise a List object containing all
# values the Channel contains.
attr_reader :value
##
# Creates a new Channel and registers it with the VM.
def self.new
Rubinius.primitive :channel_new
raise PrimitiveFailure, "Channel.new primitive failed"
end
# We must be sure a Channel is always created properly, so handle
# this the same as new.
def self.allocate
Rubinius.primitive :channel_new
raise PrimitiveFailure, "Channel.new primitive failed"
end
##
# Puts +obj+ in the Channel. If there are waiting threads the first thread
# will be woken up and handed +obj+.
def send(obj)
Rubinius.primitive :channel_send
raise PrimitiveFailure, "Channel#send primitive failed"
end
alias_method :<<, :send
##
# Removes and returns the first value from the Channel. If the channel
# is empty, Thread.current is put to sleep until #send is called.
def receive
Rubinius.primitive :channel_receive
raise PrimitiveFailure, "Channel#receive primitive failed"
end
def receive_timeout(duration)
Rubinius.primitive :channel_receive_timeout
raise PrimitiveFailure, "Channel#receive_timeout primitive failed"
end
def try_receive
Rubinius.primitive :channel_try_receive
raise PrimitiveFailure, "Channel#try_receive primitive failed"
end
def inspect
"#<Rubinius::Channel:0x#{object_id.to_s(16)}>"
end
end
end