File tree 13 files changed +70
-50
lines changed
13 files changed +70
-50
lines changed Original file line number Diff line number Diff line change 12
12
13
13
loop do
14
14
Channel . select do |s |
15
- s . take ( tick ) { print "tick.\n " }
15
+ s . take ( tick ) { | t | print "tick.\n " if t }
16
16
s . take ( boom ) do
17
17
print "BOOM!\n "
18
18
exit
Original file line number Diff line number Diff line change 17
17
18
18
limiter = Channel . ticker ( 0.2 )
19
19
requests . each do |req |
20
- ~limiter
21
- print "request #{ req } #{ Channel ::Tick . new } \n "
20
+ print "request #{ req } #{ Channel ::Tick . new } \n " if ~limiter
22
21
end
23
22
print "\n "
24
23
27
26
bursty_limiter << Channel ::Tick . new
28
27
end
29
28
29
+ ticker = Channel . ticker ( 0.2 )
30
30
Channel . go do
31
- Channel . ticker ( 0.2 ) . each do |t |
31
+ ticker . each do |t |
32
32
bursty_limiter << t
33
33
end
34
34
end
44
44
print "request #{ req } #{ Channel ::Tick . new } \n "
45
45
end
46
46
47
+ limiter . close
48
+ ticker . close
49
+
47
50
__END__
48
51
request 1 2012-10-19 00:38:18.687438 +0000 UTC
49
52
request 2 2012-10-19 00:38:18.887471 +0000 UTC
Original file line number Diff line number Diff line change 10
10
ticker = Channel . ticker ( 0.5 )
11
11
Channel . go do
12
12
ticker . each do |tick |
13
- print "Tick at #{ tick } \n "
13
+ print "Tick at #{ tick } \n " if tick
14
14
end
15
15
end
16
16
Original file line number Diff line number Diff line change 9
9
10
10
timer1 = Channel . timer ( 2 )
11
11
12
- ~timer1
13
- puts 'Timer 1 expired'
12
+ puts 'Timer 1 expired' if ~timer1
14
13
15
14
timer2 = Channel . timer ( 1 )
16
15
Channel . go do
17
- ~timer2
18
- print "Timer 2 expired\n "
16
+ print "Timer 2 expired\n " if ~timer2
19
17
end
20
18
21
19
stop2 = timer2 . stop
Original file line number Diff line number Diff line change @@ -12,7 +12,7 @@ class Channel
12
12
include Enumerable
13
13
14
14
# NOTE: Move to global IO pool once stable
15
- GOROUTINES = Concurrent ::CachedThreadPool . new
15
+ GOROUTINES = Concurrent ::CachedThreadPool . new ( auto_terminate : true )
16
16
private_constant :GOROUTINES
17
17
18
18
BUFFER_TYPES = {
Original file line number Diff line number Diff line change 1
1
require 'concurrent/synchronization/lockable_object'
2
+ require 'concurrent/utility/at_exit'
2
3
3
4
module Concurrent
4
5
class Channel
@@ -32,6 +33,7 @@ def initialize(*args)
32
33
@capacity = 0
33
34
@buffer = nil
34
35
ns_initialize ( *args )
36
+ AtExit . add ( self ) { terminate_at_exit }
35
37
end
36
38
end
37
39
@@ -232,6 +234,11 @@ def ns_full?
232
234
def ns_closed?
233
235
@closed
234
236
end
237
+
238
+ # @!visibility private
239
+ def terminate_at_exit
240
+ synchronize { self . closed = true }
241
+ end
235
242
end
236
243
end
237
244
end
Original file line number Diff line number Diff line change @@ -19,12 +19,14 @@ def ns_initialize(interval)
19
19
20
20
def do_poll
21
21
synchronize do
22
- if !ns_closed? && ( now = Concurrent . monotonic_time ) >= @next_tick
22
+ if ns_closed?
23
+ return Concurrent ::NULL , false
24
+ elsif ( now = Concurrent . monotonic_time ) >= @next_tick
23
25
tick = Concurrent ::Channel ::Tick . new ( @next_tick )
24
26
@next_tick = now + @interval
25
- return tick
27
+ return tick , true
26
28
else
27
- return Concurrent :: NULL
29
+ return nil , true
28
30
end
29
31
end
30
32
end
Original file line number Diff line number Diff line change @@ -18,26 +18,28 @@ def offer(item)
18
18
end
19
19
20
20
def take
21
- # a Go timer will block forever if stopped
22
21
loop do
23
- tick = do_poll
24
- return tick if tick != Concurrent ::NULL
25
- Thread . pass
22
+ tick , _ = do_poll
23
+ if tick
24
+ return tick
25
+ else
26
+ Thread . pass
27
+ end
26
28
end
27
29
end
28
30
29
31
def next
30
- # a Go timer will block forever if stopped
31
- # it will always return `true` for more
32
32
loop do
33
- tick = do_poll
34
- return tick , true if tick != Concurrent :: NULL
33
+ tick , more = do_poll
34
+ return tick , more if tick
35
35
Thread . pass
36
36
end
37
37
end
38
38
39
39
def poll
40
- do_poll
40
+ tick , _ = do_poll
41
+ tick = Concurrent ::NULL unless tick
42
+ tick
41
43
end
42
44
43
45
private
@@ -61,12 +63,14 @@ def ns_full?
61
63
62
64
def do_poll
63
65
synchronize do
64
- if !ns_closed? && Concurrent . monotonic_time >= @tick
66
+ if ns_closed?
67
+ return Concurrent ::NULL , false
68
+ elsif Concurrent . monotonic_time >= @tick
65
69
# only one listener gets notified
66
70
self . closed = true
67
- return Concurrent ::Channel ::Tick . new ( @tick )
71
+ return Concurrent ::Channel ::Tick . new ( @tick ) , false
68
72
else
69
- return Concurrent :: NULL
73
+ return nil , true
70
74
end
71
75
end
72
76
end
Original file line number Diff line number Diff line change @@ -16,6 +16,13 @@ module Concurrent::Channel::Buffer
16
16
expected . times { actual += 1 if subject . take . is_a? Concurrent ::Channel ::Tick }
17
17
expect ( actual ) . to eq expected
18
18
end
19
+
20
+ it 'returns Concurrent::NULL when closed after trigger' do
21
+ subject . take
22
+ subject . close
23
+ expect ( subject ) . to be_closed
24
+ expect ( subject . take ) . to eq Concurrent ::NULL
25
+ end
19
26
end
20
27
21
28
context '#poll' do
@@ -37,6 +44,17 @@ module Concurrent::Channel::Buffer
37
44
expected . times { actual += 1 if subject . next . first . is_a? Concurrent ::Channel ::Tick }
38
45
expect ( actual ) . to eq expected
39
46
end
47
+
48
+ it 'returns true for more while open' do
49
+ _ , more = subject . next
50
+ expect ( more ) . to be true
51
+ end
52
+
53
+ it 'returns false for more once closed' do
54
+ subject . close
55
+ _ , more = subject . next
56
+ expect ( more ) . to be false
57
+ end
40
58
end
41
59
end
42
60
end
Original file line number Diff line number Diff line change @@ -33,6 +33,11 @@ module Concurrent::Channel::Buffer
33
33
end
34
34
expect ( subject ) . to be_closed
35
35
end
36
+
37
+ it 'returns false for more' do
38
+ _ , more = subject . next
39
+ expect ( more ) . to be false
40
+ end
36
41
end
37
42
end
38
43
end
Original file line number Diff line number Diff line change 69
69
expect ( actual - start ) . to be >= 0.1
70
70
end
71
71
72
- it 'blocks forever when closed' do
72
+ it 'returns Concurrent::NULL when closed' do
73
73
subject . close
74
- t = Thread . new do
75
- subject . take
76
- end
77
- actual = t . join ( 1 )
78
- t . kill # clean up
79
-
80
- expect ( actual ) . to be_falsey
74
+ expect ( subject . take ) . to eq Concurrent ::NULL
81
75
end
82
76
end
83
77
129
123
expect ( value ) . to be_a Concurrent ::Channel ::Tick
130
124
end
131
125
132
- it 'returns true for more' do
133
- _ , more = subject . next
134
- expect ( more ) . to be true
135
- end
136
-
137
- it 'blocks forever when closed' do
126
+ it 'returns Concurrent::NULL, false when closed' do
138
127
subject . close
139
- t = Thread . new do
140
- subject . next
141
- end
142
- actual = t . join ( 1 )
143
- t . kill # clean up
144
-
145
- expect ( actual ) . to be_falsey
128
+ expect ( subject . take ) . to eq Concurrent ::NULL
146
129
end
147
130
148
131
it 'triggers after the specified time interval' do
Original file line number Diff line number Diff line change 1
- describe 'channel integration tests' , notravis : true do
1
+ describe 'channel integration tests' do
2
2
3
3
let! ( :examples_root ) { File . expand_path ( File . join ( File . dirname ( __FILE__ ) , '../../../examples' ) ) }
4
4
65
65
expect ( result ) . to eq expected
66
66
end
67
67
68
- specify 'default-selection.rb' do
68
+ specify 'default-selection.rb' , notravis : true do
69
69
expected = <<-STDOUT
70
70
.
71
71
.
Original file line number Diff line number Diff line change @@ -557,7 +557,7 @@ module Concurrent
557
557
end
558
558
end
559
559
560
- context 'goroutines' do
560
+ context 'goroutines' , notravis : true do
561
561
562
562
let ( :default_executor ) { Channel . const_get ( :GOROUTINES ) }
563
563
@@ -608,7 +608,7 @@ module Concurrent
608
608
actual < expected
609
609
end
610
610
611
- latch . wait ( 3 )
611
+ latch . wait ( 10 )
612
612
expect ( actual ) . to eq expected
613
613
end
614
614
end
You can’t perform that action at this time.
0 commit comments