11### Simple asynchronous task
22
33future = Concurrent . future { sleep 0.1 ; 1 + 1 } # evaluation starts immediately
4- # => <#Concurrent::Edge::Future:0x7fcc038ca588 pending blocks:[]>
4+ # => <#Concurrent::Edge::Future:0x7fd41a956d70 pending blocks:[]>
55future . completed? # => false
66# block until evaluated
77future . value # => 2
1111### Failing asynchronous task
1212
1313future = Concurrent . future { raise 'Boom' }
14- # => <#Concurrent::Edge::Future:0x7fcc038c05b0 pending blocks:[]>
14+ # => <#Concurrent::Edge::Future:0x7fd41a946c18 failed blocks:[]>
1515future . value # => nil
1616future . value! rescue $! # => #<RuntimeError: Boom>
1717future . reason # => #<RuntimeError: Boom>
2121
2222### Chaining
2323
24- head = Concurrent . future { 1 }
24+ head = Concurrent . completed_future 1
2525branch1 = head . then ( &:succ )
2626branch2 = head . then ( &:succ ) . then ( &:succ )
2727branch1 . zip ( branch2 ) . value! # => [2, 3]
3232# pick only first completed
3333( branch1 | branch2 ) . value! # => 2
3434
35- # auto splat arrays for blocks
36- Concurrent . future { [ 1 , 2 ] } . then ( &:+ ) . value! # => 3
37-
38-
3935### Error handling
4036
4137Concurrent . future { Object . new } . then ( &:succ ) . then ( &:succ ) . rescue { |e | e . class } . value # error propagates
5046
5147# will not evaluate until asked by #value or other method requiring completion
5248future = Concurrent . delay { 'lazy' }
53- # => <#Concurrent::Edge::Future:0x7fcc022afaa0 pending blocks:[]>
49+ # => <#Concurrent::Edge::Future:0x7fd41a8f6ec0 pending blocks:[]>
5450sleep 0.1
5551future . completed? # => false
5652future . value # => "lazy"
5753
5854# propagates trough chain allowing whole or partial lazy chains
5955
6056head = Concurrent . delay { 1 }
61- # => <#Concurrent::Edge::Future:0x7fcc022a5640 pending blocks:[]>
57+ # => <#Concurrent::Edge::Future:0x7fd41a8ee1a8 pending blocks:[]>
6258branch1 = head . then ( &:succ )
63- # => <#Concurrent::Edge::Future:0x7fcc0229c478 pending blocks:[]>
59+ # => <#Concurrent::Edge::Future:0x7fd41a8ed438 pending blocks:[]>
6460branch2 = head . delay . then ( &:succ )
65- # => <#Concurrent::Edge::Future:0x7fcc0228f318 pending blocks:[]>
61+ # => <#Concurrent::Edge::Future:0x7fd41a8e7588 pending blocks:[]>
6662join = branch1 & branch2
67- # => <#Concurrent::Edge::Future:0x7fcc0228de78 pending blocks:[]>
63+ # => <#Concurrent::Edge::Future:0x7fd41a8e4ec8 pending blocks:[]>
6864
6965sleep 0.1 # nothing will complete # => 0
7066[ head , branch1 , branch2 , join ] . map ( &:completed? ) # => [false, false, false, false]
7167
7268branch1 . value # => 2
7369sleep 0.1 # forces only head to complete, branch 2 stays incomplete
74- # => 0
70+ # => 1
7571[ head , branch1 , branch2 , join ] . map ( &:completed? ) # => [true, true, false, false]
7672
7773join . value # => [2, 2]
9288### Schedule
9389
9490scheduled = Concurrent . schedule ( 0.1 ) { 1 }
95- # => <#Concurrent::Edge::Future:0x7fcc0385b368 pending blocks:[]>
91+ # => <#Concurrent::Edge::Future:0x7fd41a8a4468 pending blocks:[]>
9692
9793scheduled . completed? # => false
9894scheduled . value # available after 0.1sec # => 1
9995
10096# and in chain
10197scheduled = Concurrent . delay { 1 } . schedule ( 0.1 ) . then ( &:succ )
102- # => <#Concurrent::Edge::Future:0x7fcc03843948 pending blocks:[]>
98+ # => <#Concurrent::Edge::Future:0x7fd41a895828 pending blocks:[]>
10399# will not be scheduled until value is requested
104100sleep 0.1
105101scheduled . value # returns after another 0.1sec # => 2
108104### Completable Future and Event
109105
110106future = Concurrent . future
111- # => <#Concurrent::Edge::CompletableFuture:0x7fcc0304fdb8 pending blocks:[]>
107+ # => <#Concurrent::Edge::CompletableFuture:0x7fd41a87c648 pending blocks:[]>
112108event = Concurrent . event
113- # => <#Concurrent::Edge::CompletableEvent:0x7fcc0304e210 pending blocks:[]>
109+ # => <#Concurrent::Edge::CompletableEvent:0x7fd41a8770d0 pending blocks:[]>
110+ # Don't forget to keep the reference, `Concurrent.future.then { |v| v }` is incompletable
114111
115112# will be blocked until completed
116113t1 = Thread . new { future . value }
117114t2 = Thread . new { event . wait }
118115
119116future . success 1
120- # => <#Concurrent::Edge::CompletableFuture:0x7fcc0304fdb8 success blocks:[]>
117+ # => <#Concurrent::Edge::CompletableFuture:0x7fd41a87c648 success blocks:[]>
121118future . success 1 rescue $!
122- # => #<Concurrent::MultipleAssignmentError: multiple assignment >
119+ # => #<Concurrent::MultipleAssignmentError: Future can be completed only once. Current result is [true, 1, nil], trying to set [true, 1, nil] >
123120future . try_success 2 # => false
124121event . complete
125- # => <#Concurrent::Edge::CompletableEvent:0x7fcc0304e210 completed blocks:[]>
122+ # => <#Concurrent::Edge::CompletableEvent:0x7fd41a8770d0 completed blocks:[]>
126123
127124[ t1 , t2 ] . each &:join
128125
129126
130127### Callbacks
131128
132- queue = Queue . new # => #<Thread::Queue:0x007fcc03101720 >
129+ queue = Queue . new # => #<Thread::Queue:0x007fd41b0543e8 >
133130future = Concurrent . delay { 1 + 1 }
134- # => <#Concurrent::Edge::Future:0x7fcc030fbaf0 pending blocks:[]>
131+ # => <#Concurrent::Edge::Future:0x7fd41b04f028 pending blocks:[]>
135132
136133future . on_success { queue << 1 } # evaluated asynchronously
137- # => <#Concurrent::Edge::Future:0x7fcc030fbaf0 pending blocks:[]>
134+ # => <#Concurrent::Edge::Future:0x7fd41b04f028 pending blocks:[]>
138135future . on_success! { queue << 2 } # evaluated on completing thread
139- # => <#Concurrent::Edge::Future:0x7fcc030fbaf0 pending blocks:[]>
136+ # => <#Concurrent::Edge::Future:0x7fd41b04f028 pending blocks:[]>
140137
141138queue . empty? # => true
142139future . value # => 2
147144### Thread-pools
148145
149146Concurrent . future ( :fast ) { 2 } . then ( :io ) { File . read __FILE__ } . wait
150- # => <#Concurrent::Edge::Future:0x7fcc030e8bd0 success blocks:[]>
147+ # => <#Concurrent::Edge::Future:0x7fd41a857550 success blocks:[]>
151148
152149
153150### Interoperability with actors
154151
155152actor = Concurrent ::Actor ::Utils ::AdHoc . spawn :square do
156153 -> v { v ** 2 }
157154end
158- # => #<Concurrent::Actor::Reference:0x7fcc0223f020 /square (Concurrent::Actor::Utils::AdHoc)>
155+ # => #<Concurrent::Actor::Reference:0x7fd41c03b5b8 /square (Concurrent::Actor::Utils::AdHoc)>
159156
160157Concurrent .
161158 future { 2 } .
168165
169166### Interoperability with channels
170167
171- ch1 = Concurrent ::Edge ::Channel . new # => #<Concurrent::Edge::Channel:0x007fcc021ec6b8 >
172- ch2 = Concurrent ::Edge ::Channel . new # => #<Concurrent::Edge::Channel:0x007fcc021e7b18 >
168+ ch1 = Concurrent ::Edge ::Channel . new # => #<Concurrent::Edge::Channel:0x007fd41a297458 >
169+ ch2 = Concurrent ::Edge ::Channel . new # => #<Concurrent::Edge::Channel:0x007fd41a296940 >
173170
174171result = Concurrent . select ( ch1 , ch2 )
175- # => <#Concurrent::Edge::CompletableFuture:0x7fcc021e6060 pending blocks:[]>
172+ # => <#Concurrent::Edge::CompletableFuture:0x7fd41a295c98 pending blocks:[]>
176173ch1 . push 1 # => nil
177174result . value!
178- # => [1, #<Concurrent::Edge::Channel:0x007fcc021ec6b8 >]
175+ # => [1, #<Concurrent::Edge::Channel:0x007fd41a297458 >]
179176
180177Concurrent .
181178 future { 1 +1 } .
182179 then_push ( ch1 )
183- # => <#Concurrent::Edge::Future:0x7fcc021dc3d0 pending blocks:[]>
180+ # => <#Concurrent::Edge::Future:0x7fd41a284010 pending blocks:[]>
184181result = Concurrent .
185182 future { '%02d' } .
186183 then_select ( ch1 , ch2 ) .
187184 then { |format , ( value , channel ) | format format , value }
188- # => <#Concurrent::Edge::Future:0x7fcc021cd9e8 pending blocks:[]>
185+ # => <#Concurrent::Edge::Future:0x7fd41a25d938 pending blocks:[]>
189186result . value! # => "02"
190187
191188
192189### Common use-cases Examples
193190
194191# simple background processing
195192Concurrent . future { do_stuff }
196- # => <#Concurrent::Edge::Future:0x7fcc021b7530 pending blocks:[]>
193+ # => <#Concurrent::Edge::Future:0x7fd41a23d520 pending blocks:[]>
197194
198195# parallel background processing
199196jobs = 10 . times . map { |i | Concurrent . future { i } }
@@ -210,7 +207,7 @@ def schedule_job
210207end # => :schedule_job
211208
212209schedule_job
213- # => <#Concurrent::Edge::Future:0x7fcc0218faf8 pending blocks:[]>
210+ # => <#Concurrent::Edge::Future:0x7fd41a2245e8 pending blocks:[]>
214211@end = true # => true
215212
216213
@@ -223,7 +220,7 @@ def schedule_job
223220 data [ message ]
224221 end
225222end
226- # => #<Concurrent::Actor::Reference:0x7fcc0214f458 /db (Concurrent::Actor::Utils::AdHoc)>
223+ # => #<Concurrent::Actor::Reference:0x7fd41a206228 /db (Concurrent::Actor::Utils::AdHoc)>
227224
228225concurrent_jobs = 11 . times . map do |v |
229226 Concurrent .
@@ -253,7 +250,7 @@ def schedule_job
253250 end
254251 end
255252end
256- # => #<Concurrent::Actor::Reference:0x7fcc02930398 /DB-pool (Concurrent::Actor::Utils::Pool)>
253+ # => #<Concurrent::Actor::Reference:0x7fd41a0530c0 /DB-pool (Concurrent::Actor::Utils::Pool)>
257254
258255concurrent_jobs = 11 . times . map do |v |
259256 Concurrent .
0 commit comments