File tree Expand file tree Collapse file tree 5 files changed +96
-11
lines changed Expand file tree Collapse file tree 5 files changed +96
-11
lines changed Original file line number Diff line number Diff line change 32
32
require 'concurrent/tvar'
33
33
require 'concurrent/utilities'
34
34
35
+ require 'concurrent/channel/probe'
35
36
require 'concurrent/channel/unbuffered_channel'
36
37
37
38
require 'concurrent/cached_thread_pool'
Original file line number Diff line number Diff line change
1
+ module Concurrent
2
+ class Probe < IVar
3
+
4
+ def initialize ( value = NO_VALUE , opts = { } )
5
+ super ( value , opts )
6
+ end
7
+
8
+ def set_unless_assigned ( value )
9
+ mutex . synchronize do
10
+ return false if [ :fulfilled , :rejected ] . include? @state
11
+
12
+ set_state ( true , value , nil )
13
+ event . set
14
+ true
15
+ end
16
+
17
+ end
18
+ end
19
+ end
Original file line number Diff line number Diff line change @@ -9,30 +9,33 @@ def initialize
9
9
end
10
10
11
11
def push ( value )
12
- probe = @mutex . synchronize do
13
- @condition . wait ( @mutex ) while @wait_set . empty?
14
- @wait_set . shift
12
+ until first_waiting_probe . set_unless_assigned ( value )
15
13
end
16
-
17
- probe . set ( value )
18
14
end
19
15
20
16
def pop
21
- probe = IVar . new
17
+ probe = Probe . new
18
+ select ( probe )
19
+ probe . value
20
+ end
22
21
22
+ def select ( probe )
23
23
@mutex . synchronize do
24
24
@wait_set << probe
25
25
@condition . signal
26
26
end
27
-
28
- probe . value
29
- end
30
-
31
- def select ( probe )
32
27
end
33
28
34
29
def remove_probe ( probe )
35
30
end
36
31
32
+ private
33
+ def first_waiting_probe
34
+ @mutex . synchronize do
35
+ @condition . wait ( @mutex ) while @wait_set . empty?
36
+ @wait_set . shift
37
+ end
38
+ end
39
+
37
40
end
38
41
end
Original file line number Diff line number Diff line change
1
+ require 'spec_helper'
2
+
3
+ module Concurrent
4
+
5
+ describe Probe do
6
+ it 'should be written'
7
+ end
8
+ end
Original file line number Diff line number Diff line change @@ -31,6 +31,7 @@ module Concurrent
31
31
end
32
32
33
33
context 'cooperating threads' do
34
+
34
35
it 'passes the pushed value to thread waiting on pop' do
35
36
result = nil
36
37
@@ -41,7 +42,60 @@ module Concurrent
41
42
42
43
result . should eq 42
43
44
end
45
+
46
+ it 'passes the pushed value to only one thread' do
47
+ result = [ ]
48
+
49
+ Thread . new { channel . push 37 }
50
+ Thread . new { result << channel . pop }
51
+ Thread . new { result << channel . pop }
52
+
53
+ sleep ( 0.05 )
54
+
55
+ result . should have ( 1 ) . items
56
+ end
44
57
end
45
58
59
+ describe 'select' do
60
+
61
+ let ( :probe ) { Probe . new }
62
+
63
+ it 'does not block' do
64
+ t = Thread . new { channel . select ( probe ) }
65
+
66
+ sleep ( 0.05 )
67
+
68
+ t . status . should eq false
69
+ end
70
+
71
+ it 'gets notified by writer thread' do
72
+ channel . select ( probe )
73
+
74
+ Thread . new { channel . push 82 }
75
+
76
+ probe . value . should eq 82
77
+ end
78
+
79
+ it 'ignores already set probes and waits for a new one' do
80
+ probe . set ( 27 )
81
+
82
+ channel . select ( probe )
83
+
84
+ t = Thread . new { channel . push 72 }
85
+
86
+ sleep ( 0.05 )
87
+
88
+ t . status . should eq 'sleep'
89
+
90
+ new_probe = Probe . new
91
+
92
+ channel . select ( new_probe )
93
+
94
+ sleep ( 0.05 )
95
+
96
+ new_probe . value . should eq 72
97
+ end
98
+
99
+ end
46
100
end
47
101
end
You can’t perform that action at this time.
0 commit comments