3 raise ArgumentError, "No block given" unless block
13 def c.chord(*names, &action)
14 raise ArgumentError, "No channel names specified" if names.empty?
15 raise ArgumentError, "No block given" unless action
16 names.map! { |n| n.to_sym }
17 indices = __defchannels__(*names)
18 mask = indices.inject(0) { |acc, i| acc | ( 1 << i ) }
19 @chords.push [ mask, indices, action ].freeze
20 names.each_with_index do |n, i|
26 names.map! { |n| n.to_sym }
27 __defchannels__(*names).each { |index| @sync[index] = false }
32 names.map! { |n| n.to_sym }
33 __defchannels__(*names).each { |index| @sync[index] = true }
37 def c.__defchannels__(*names)
38 indices = names.map { |name| ( @indices[name] ||= ( @max += 1 ) ) }
39 names.each_with_index do |name, i|
41 def #{ name }(value=nil)
42 __channel_send__( #{ indices[i] }, value )
50 private :chord, :async, :sync, :__defchannels__
54 c.instance_eval { @chords.reverse! }
60 remove_method :chord, :async, :sync, :__defchannels__
61 def new(*args, &block)
67 @join_pending = (0..max).map { Array.new }
68 @join_pending_mask = 0
71 @join_lock = Channel.new
73 initialize(*args, &block)
82 def __channel_send__(index, value)
85 value = [value, reply]
89 @join_pending[index].push value
90 @join_pending_mask |= 1 << index
91 @join_chords.each do |mask, indices, action|
92 if mask & @join_pending_mask == mask
96 pending = @join_pending[i]
100 waiting.push value.last
104 @join_pending_mask ^= 1 << i if pending.empty?
106 thread = Thread.new { instance_exec(*args, &action) }
107 waiting.each { |waiter| waiter.send thread }
120 private :__channel_send__