Skip to content

Commit 3ff1cb0

Browse files
committed
Bump version, update doc
1 parent d84d13e commit 3ff1cb0

31 files changed

+2276
-227
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
## Current
22

3+
## Release v1.1.5, edge v0.5.0 (10 mar 2019)
4+
5+
concurrent-ruby:
6+
7+
* fix potential leak of context on JRuby and Java 7
8+
9+
concurrent-ruby-edge:
10+
11+
* Add finalized Concurrent::Cancellation
12+
* Add finalized Concurrent::Throttle
13+
* Add finalized Concurrent::Promises::Channel
14+
* Add new Concurrent::ErlangActor
15+
316
## Release v1.1.4 (14 Dec 2018)
417

518
* (#780) Remove java_alias of 'submit' method of Runnable to let executor service work on java 11

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ end
2020
group :documentation, optional: true do
2121
gem 'yard', '~> 0.9.0', require: false
2222
gem 'redcarpet', '~> 3.0', platforms: :mri # understands github markdown
23-
gem 'md-ruby-eval', '~> 0.4'
23+
gem 'md-ruby-eval', '~> 0.6'
2424
end
2525

2626
group :testing do

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,9 @@ and to the past maintainers
367367
* [Paweł Obrok](https://github.com/obrok)
368368
* [Lucas Allan](https://github.com/lucasallan)
369369

370+
and to [Ruby Association](https://www.ruby.or.jp/en/) for sponsoring a project
371+
["Enhancing Ruby’s concurrency tooling"](https://www.ruby.or.jp/en/news/20181106) in 2018.
372+
370373
## License and Copyright
371374

372375
*Concurrent Ruby* is free software released under the

Rakefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ begin
171171
'-',
172172
'docs-source/thread_pools.md',
173173
'docs-source/promises.out.md',
174+
'docs-source/medium-example.out.rb',
174175
'LICENSE.md',
175176
'CHANGELOG.md']
176177
end

docs-source/channel.out.md

Lines changed: 69 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ threads = Array.new(3) { |i| Thread.new { ch.push message: i } }
1616
sleep 0.01 # let the threads run
1717
threads
1818
# => [#<Thread:[email protected]:14 dead>,
19-
# #<Thread:[email protected]:14 sleep_forever>,
20-
# #<Thread:[email protected]:14 dead>]
19+
# #<Thread:[email protected]:14 dead>,
20+
# #<Thread:[email protected]:14 sleep_forever>]
2121
```
2222

2323
When message is popped the last thread continues and finishes as well.
2424

2525
```ruby
26-
ch.pop # => {:message=>2}
26+
ch.pop # => {:message=>0}
2727
threads.map(&:join)
2828
# => [#<Thread:[email protected]:14 dead>,
2929
# #<Thread:[email protected]:14 dead>,
@@ -38,11 +38,14 @@ one will be blocked until new messages is pushed.
3838
```ruby
3939
threads = Array.new(3) { |i| Thread.new { ch.pop } }
4040
sleep 0.01 # let the threads run
41-
threads.map(&:status) # => [false, false, "sleep"]
41+
threads
42+
# => [#<Thread:[email protected]:32 dead>,
43+
# #<Thread:[email protected]:32 dead>,
44+
# #<Thread:[email protected]:32 sleep_forever>]
4245
ch.push message: 3
4346
# => #<Concurrent::Promises::Channel:0x000002 capacity taken 0 of 2>
4447
threads.map(&:value)
45-
# => [{:message=>0}, {:message=>1}, {:message=>3}]
48+
# => [{:message=>1}, {:message=>2}, {:message=>3}]
4649
```
4750

4851
### Promises integration
@@ -52,11 +55,11 @@ therefore all operations can be represented as futures.
5255

5356
```ruby
5457
ch = Concurrent::Promises::Channel.new 2
55-
# => #<Concurrent::Promises::Channel:0x000006 capacity taken 0 of 2>
58+
# => #<Concurrent::Promises::Channel:0x000009 capacity taken 0 of 2>
5659
push_operations = Array.new(3) { |i| ch.push_op message: i }
57-
# => [#<Concurrent::Promises::Future:0x000007 fulfilled with #<Concurrent::Promises::Channel:0x000006 capacity taken 2 of 2>>,
58-
# #<Concurrent::Promises::Future:0x000008 fulfilled with #<Concurrent::Promises::Channel:0x000006 capacity taken 2 of 2>>,
59-
# #<Concurrent::Promises::ResolvableFuture:0x000009 pending>]
60+
# => [#<Concurrent::Promises::Future:0x00000a fulfilled with #<Concurrent::Promises::Channel:0x000009 capacity taken 2 of 2>>,
61+
# #<Concurrent::Promises::Future:0x00000b fulfilled with #<Concurrent::Promises::Channel:0x000009 capacity taken 2 of 2>>,
62+
# #<Concurrent::Promises::ResolvableFuture:0x00000c pending>]
6063
```
6164

6265
> We do not have to sleep here letting the futures execute as Threads.
@@ -70,14 +73,14 @@ making a space for a new message.
7073
```ruby
7174
ch.pop_op.value! # => {:message=>0}
7275
push_operations.map(&:value!)
73-
# => [#<Concurrent::Promises::Channel:0x000006 capacity taken 2 of 2>,
74-
# #<Concurrent::Promises::Channel:0x000006 capacity taken 2 of 2>,
75-
# #<Concurrent::Promises::Channel:0x000006 capacity taken 2 of 2>]
76+
# => [#<Concurrent::Promises::Channel:0x000009 capacity taken 2 of 2>,
77+
# #<Concurrent::Promises::Channel:0x000009 capacity taken 2 of 2>,
78+
# #<Concurrent::Promises::Channel:0x000009 capacity taken 2 of 2>]
7679

7780
pop_operations = Array.new(3) { |i| ch.pop_op }
78-
# => [#<Concurrent::Promises::ResolvableFuture:0x00000a fulfilled with {:message=>1}>,
79-
# #<Concurrent::Promises::ResolvableFuture:0x00000b fulfilled with {:message=>2}>,
80-
# #<Concurrent::Promises::ResolvableFuture:0x00000c pending>]
81+
# => [#<Concurrent::Promises::ResolvableFuture:0x00000d fulfilled with {:message=>1}>,
82+
# #<Concurrent::Promises::ResolvableFuture:0x00000e fulfilled with {:message=>2}>,
83+
# #<Concurrent::Promises::ResolvableFuture:0x00000f pending>]
8184
ch.push message: 3 # (push|pop) can be freely mixed with (push_o|pop_op)
8285
pop_operations.map(&:value)
8386
# => [{:message=>1}, {:message=>2}, {:message=>3}]
@@ -91,21 +94,21 @@ returns a pair to be able to find out which channel had the message available.
9194

9295
```ruby
9396
ch1 = Concurrent::Promises::Channel.new 2
94-
# => #<Concurrent::Promises::Channel:0x00000d capacity taken 0 of 2>
97+
# => #<Concurrent::Promises::Channel:0x000010 capacity taken 0 of 2>
9598
ch2 = Concurrent::Promises::Channel.new 2
96-
# => #<Concurrent::Promises::Channel:0x00000e capacity taken 0 of 2>
99+
# => #<Concurrent::Promises::Channel:0x000011 capacity taken 0 of 2>
97100
ch1.push 1
98-
# => #<Concurrent::Promises::Channel:0x00000d capacity taken 1 of 2>
101+
# => #<Concurrent::Promises::Channel:0x000010 capacity taken 1 of 2>
99102
ch2.push 2
100-
# => #<Concurrent::Promises::Channel:0x00000e capacity taken 1 of 2>
103+
# => #<Concurrent::Promises::Channel:0x000011 capacity taken 1 of 2>
101104

102105
Concurrent::Promises::Channel.select([ch1, ch2])
103-
# => [#<Concurrent::Promises::Channel:0x00000d capacity taken 0 of 2>, 1]
106+
# => [#<Concurrent::Promises::Channel:0x000010 capacity taken 0 of 2>, 1]
104107
ch1.select(ch2)
105-
# => [#<Concurrent::Promises::Channel:0x00000e capacity taken 0 of 2>, 2]
108+
# => [#<Concurrent::Promises::Channel:0x000011 capacity taken 0 of 2>, 2]
106109

107110
Concurrent::Promises.future { 3 + 4 }.then_channel_push(ch1)
108-
# => #<Concurrent::Promises::Future:0x00000f pending>
111+
# => #<Concurrent::Promises::Future:0x000012 pending>
109112
Concurrent::Promises::Channel.
110113
# or `ch1.select_op(ch2)` would be equivalent
111114
select_op([ch1, ch2]).
@@ -122,7 +125,7 @@ They always return immediately and indicate either success or failure.
122125

123126
```ruby
124127
ch
125-
# => #<Concurrent::Promises::Channel:0x000006 capacity taken 0 of 2>
128+
# => #<Concurrent::Promises::Channel:0x000009 capacity taken 0 of 2>
126129
ch.try_push 1 # => true
127130
ch.try_push 2 # => true
128131
ch.try_push 3 # => false
@@ -139,7 +142,7 @@ when the timeout option is used.
139142

140143
```ruby
141144
ch
142-
# => #<Concurrent::Promises::Channel:0x000006 capacity taken 0 of 2>
145+
# => #<Concurrent::Promises::Channel:0x000009 capacity taken 0 of 2>
143146
ch.push 1, 0.01 # => true
144147
ch.push 2, 0.01 # => true
145148
ch.push 3, 0.01 # => false
@@ -156,7 +159,7 @@ if the consumers are not keeping up.
156159

157160
```ruby
158161
channel = Concurrent::Promises::Channel.new 2
159-
# => #<Concurrent::Promises::Channel:0x000010 capacity taken 0 of 2>
162+
# => #<Concurrent::Promises::Channel:0x000013 capacity taken 0 of 2>
160163
log = Concurrent::Array.new # => []
161164

162165
producers = Array.new 2 do |i|
@@ -167,8 +170,8 @@ producers = Array.new 2 do |i|
167170
end
168171
end
169172
end
170-
# => [#<Thread:0x000011@channel.in.md:133 run>,
171-
# #<Thread:0x000012@channel.in.md:133 run>]
173+
# => [#<Thread:0x000014@channel.in.md:133 run>,
174+
# #<Thread:0x000015@channel.in.md:133 run>]
172175

173176
consumers = Array.new 4 do |i|
174177
Thread.new(i) do |consumer|
@@ -180,38 +183,38 @@ consumers = Array.new 4 do |i|
180183
end
181184
end
182185
end
183-
# => [#<Thread:0x000013@channel.in.md:142 run>,
184-
# #<Thread:0x000014@channel.in.md:142 run>,
185-
# #<Thread:0x000015@channel.in.md:142 run>,
186-
# #<Thread:0x000016@channel.in.md:142 run>]
186+
# => [#<Thread:0x000016@channel.in.md:142 run>,
187+
# #<Thread:0x000017@channel.in.md:142 run>,
188+
# #<Thread:0x000018@channel.in.md:142 run>,
189+
# #<Thread:0x000019@channel.in.md:142 run>]
187190

188191
# wait for all to finish
189192
producers.map(&:join)
190-
# => [#<Thread:0x000011@channel.in.md:133 dead>,
191-
# #<Thread:0x000012@channel.in.md:133 dead>]
193+
# => [#<Thread:0x000014@channel.in.md:133 dead>,
194+
# #<Thread:0x000015@channel.in.md:133 dead>]
192195
consumers.map(&:join)
193-
# => [#<Thread:0x000013@channel.in.md:142 dead>,
194-
# #<Thread:0x000014@channel.in.md:142 dead>,
195-
# #<Thread:0x000015@channel.in.md:142 dead>,
196-
# #<Thread:0x000016@channel.in.md:142 dead>]
196+
# => [#<Thread:0x000016@channel.in.md:142 dead>,
197+
# #<Thread:0x000017@channel.in.md:142 dead>,
198+
# #<Thread:0x000018@channel.in.md:142 dead>,
199+
# #<Thread:0x000019@channel.in.md:142 dead>]
197200
# investigate log
198-
log
201+
log
199202
# => ["producer 0 pushing 0",
200203
# "producer 0 pushing 1",
201204
# "producer 0 pushing 2",
202205
# "producer 1 pushing 0",
203206
# "consumer 0 got 0. payload 0 from producer 0",
204-
# "producer 0 pushing 3",
205-
# "consumer 2 got 0. payload 1 from producer 0",
207+
# "consumer 1 got 0. payload 1 from producer 0",
206208
# "producer 1 pushing 1",
207-
# "consumer 1 got 0. payload 2 from producer 0",
208-
# "consumer 3 got 0. payload 0 from producer 1",
209+
# "consumer 3 got 0. payload 2 from producer 0",
209210
# "producer 1 pushing 2",
210-
# "consumer 2 got 1. payload 3 from producer 0",
211-
# "consumer 0 got 1. payload 1 from producer 1",
212-
# "consumer 3 got 1. payload 2 from producer 1",
211+
# "consumer 2 got 0. payload 0 from producer 1",
213212
# "producer 1 pushing 3",
214-
# "consumer 1 got 1. payload 3 from producer 1"]
213+
# "producer 0 pushing 3",
214+
# "consumer 0 got 1. payload 1 from producer 1",
215+
# "consumer 1 got 1. payload 2 from producer 1",
216+
# "consumer 3 got 1. payload 3 from producer 1",
217+
# "consumer 2 got 1. payload 3 from producer 0"]
215218
```
216219

217220
The producers are much faster than consumers
@@ -226,7 +229,7 @@ that run a thread pool.
226229

227230
```ruby
228231
channel = Concurrent::Promises::Channel.new 2
229-
# => #<Concurrent::Promises::Channel:0x000017 capacity taken 0 of 2>
232+
# => #<Concurrent::Promises::Channel:0x00001a capacity taken 0 of 2>
230233
log = Concurrent::Array.new # => []
231234

232235
def produce(channel, log, producer, i)
@@ -248,38 +251,38 @@ end # => :consume
248251
producers = Array.new 2 do |i|
249252
Concurrent::Promises.future(channel, log, i) { |*args| produce *args, 0 }.run
250253
end
251-
# => [#<Concurrent::Promises::Future:0x000018 pending>,
252-
# #<Concurrent::Promises::Future:0x000019 pending>]
254+
# => [#<Concurrent::Promises::Future:0x00001b pending>,
255+
# #<Concurrent::Promises::Future:0x00001c pending>]
253256

254257
consumers = Array.new 4 do |i|
255258
Concurrent::Promises.future(channel, log, i) { |*args| consume *args, 0 }.run
256259
end
257-
# => [#<Concurrent::Promises::Future:0x00001a pending>,
258-
# #<Concurrent::Promises::Future:0x00001b pending>,
259-
# #<Concurrent::Promises::Future:0x00001c pending>,
260-
# #<Concurrent::Promises::Future:0x00001d pending>]
260+
# => [#<Concurrent::Promises::Future:0x00001d pending>,
261+
# #<Concurrent::Promises::Future:0x00001e pending>,
262+
# #<Concurrent::Promises::Future:0x00001f pending>,
263+
# #<Concurrent::Promises::Future:0x000020 pending>]
261264

262265
# wait for all to finish
263266
producers.map(&:value!) # => [:done, :done]
264267
consumers.map(&:value!) # => [:done, :done, :done, :done]
265268
# investigate log
266-
log
269+
log
267270
# => ["producer 0 pushing 0",
268271
# "producer 1 pushing 0",
269-
# "consumer 1 got 0. payload 0 from producer 1",
270272
# "producer 0 pushing 1",
271273
# "producer 1 pushing 1",
272274
# "consumer 0 got 0. payload 0 from producer 0",
273-
# "consumer 3 got 0. payload 1 from producer 0",
275+
# "consumer 1 got 0. payload 0 from producer 1",
276+
# "consumer 2 got 0. payload 1 from producer 0",
274277
# "producer 0 pushing 2",
278+
# "consumer 3 got 0. payload 1 from producer 1",
275279
# "producer 1 pushing 2",
276-
# "producer 1 pushing 3",
277280
# "producer 0 pushing 3",
278-
# "consumer 2 got 0. payload 1 from producer 1",
279-
# "consumer 0 got 1. payload 2 from producer 0",
280-
# "consumer 2 got 1. payload 3 from producer 1",
281-
# "consumer 1 got 1. payload 3 from producer 0",
282-
# "consumer 3 got 1. payload 2 from producer 1"]
281+
# "producer 1 pushing 3",
282+
# "consumer 0 got 1. payload 2 from producer 1",
283+
# "consumer 2 got 1. payload 3 from producer 0",
284+
# "consumer 1 got 1. payload 2 from producer 0",
285+
# "consumer 3 got 1. payload 3 from producer 1"]
283286
```
284287

285288
### Synchronization of workers by passing a value
@@ -292,19 +295,19 @@ The operations have to be paired to succeed.
292295

293296
```ruby
294297
channel = Concurrent::Promises::Channel.new 0
295-
# => #<Concurrent::Promises::Channel:0x00001e capacity taken 0 of 0>
298+
# => #<Concurrent::Promises::Channel:0x000021 capacity taken 0 of 0>
296299
thread = Thread.new { channel.pop }; sleep 0.01
297300
# allow the thread to go to sleep
298301
thread
299-
# => #<Thread:0x00001f@channel.in.md:246 sleep_forever>
302+
# => #<Thread:0x000022@channel.in.md:214 sleep_forever>
300303
# succeeds because there is matching pop operation waiting in the thread
301304
channel.try_push(:v1) # => true
302305
# remains pending, since there is no matching operation
303306
push = channel.push_op(:v2)
304-
# => #<Concurrent::Promises::ResolvableFuture:0x000020 pending>
307+
# => #<Concurrent::Promises::ResolvableFuture:0x000023 pending>
305308
thread.value # => :v1
306309
# the push operation resolves as a pairing pop is called
307310
channel.pop # => :v2
308311
push
309-
# => #<Concurrent::Promises::ResolvableFuture:0x000020 fulfilled with #<Concurrent::Promises::Channel:0x00001e capacity taken 0 of 0>>
312+
# => #<Concurrent::Promises::ResolvableFuture:0x000023 fulfilled with #<Concurrent::Promises::Channel:0x000021 capacity taken 0 of 0>>
310313
```

0 commit comments

Comments
 (0)