11### Simple asynchronous task
22
33future = Concurrent . future { sleep 0.1 ; 1 + 1 } # evaluation starts immediately
4- # => <#Concurrent::Edge::Future:0x7fc6218f2318 pending blocks:[]>
4+ # => <#Concurrent::Edge::Future:0x7fcc73208180 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:0x7fc6218eae38 pending blocks:[]>
14+ # => <#Concurrent::Edge::Future:0x7fcc731fa0a8 pending blocks:[]>
1515future . value # => nil
1616future . value! rescue $! # => #<RuntimeError: Boom>
1717future . reason # => #<RuntimeError: Boom>
2121
2222### Chaining
2323
24- head = Concurrent . completed_future 1
24+ head = Concurrent . succeeded_future 1
2525branch1 = head . then ( &:succ )
2626branch2 = head . then ( &:succ ) . then ( &:succ )
2727branch1 . zip ( branch2 ) . value! # => [2, 3]
4141Concurrent . future { 1 } . then ( &:succ ) . rescue { |e | e . message } . then ( &:succ ) . value
4242 # => 3
4343
44- failing_zip = Concurrent . completed_future ( 1 ) & Concurrent . future { raise 'boom' }
45- # => <#Concurrent::Edge::Future:0x7fc6218b0f08 pending blocks:[]>
46- failing_zip . result # => [false, [1, nil], [nil, #<RuntimeError : boom>]]
47- failing_zip . then { |v | 'never happens' } . result # => [false, [1, nil], [nil, #<RuntimeError : boom>]]
44+ failing_zip = Concurrent . succeeded_future ( 1 ) & Concurrent . failed_future ( StandardError . new ( 'boom' ) )
45+ # => <#Concurrent::Edge::Future:0x7fcc731c00b0 failed blocks:[]>
46+ failing_zip . result # => [false, [1, nil], [nil, #<StandardError : boom>]]
47+ failing_zip . then { |v | 'never happens' } . result # => [false, [1, nil], [nil, #<StandardError : boom>]]
4848failing_zip . rescue { |a , b | ( a || b ) . message } . value
4949 # => "boom"
5050failing_zip . chain { |success , values , reasons | [ success , values . compact , reasons . compactß ] } . value
5454
5555# will not evaluate until asked by #value or other method requiring completion
5656future = Concurrent . delay { 'lazy' }
57- # => <#Concurrent::Edge::Future:0x7fc6218a37e0 pending blocks:[]>
57+ # => <#Concurrent::Edge::Future:0x7fcc731a1840 pending blocks:[]>
5858sleep 0.1
5959future . completed? # => false
6060future . value # => "lazy"
6161
6262# propagates trough chain allowing whole or partial lazy chains
6363
6464head = Concurrent . delay { 1 }
65- # => <#Concurrent::Edge::Future:0x7fc6218a0720 pending blocks:[]>
65+ # => <#Concurrent::Edge::Future:0x7fcc73193b28 pending blocks:[]>
6666branch1 = head . then ( &:succ )
67- # => <#Concurrent::Edge::Future:0x7fc6212c7b50 pending blocks:[]>
67+ # => <#Concurrent::Edge::Future:0x7fcc73190900 pending blocks:[]>
6868branch2 = head . delay . then ( &:succ )
69- # => <#Concurrent::Edge::Future:0x7fc6212c6098 pending blocks:[]>
69+ # => <#Concurrent::Edge::Future:0x7fcc7318b400 pending blocks:[]>
7070join = branch1 & branch2
71- # => <#Concurrent::Edge::Future:0x7fc6212c4f40 pending blocks:[]>
71+ # => <#Concurrent::Edge::Future:0x7fcc73180af0 pending blocks:[]>
7272
7373sleep 0.1 # nothing will complete # => 0
7474[ head , branch1 , branch2 , join ] . map ( &:completed? ) # => [false, false, false, false]
7575
7676branch1 . value # => 2
7777sleep 0.1 # forces only head to complete, branch 2 stays incomplete
78- # => 1
78+ # => 0
7979[ head , branch1 , branch2 , join ] . map ( &:completed? ) # => [true, true, false, false]
8080
8181join . value # => [2, 2]
9696### Schedule
9797
9898scheduled = Concurrent . schedule ( 0.1 ) { 1 }
99- # => <#Concurrent::Edge::Future:0x7fc62128c550 pending blocks:[]>
99+ # => <#Concurrent::Edge::Future:0x7fcc73143e48 pending blocks:[]>
100100
101101scheduled . completed? # => false
102102scheduled . value # available after 0.1sec # => 1
103103
104104# and in chain
105105scheduled = Concurrent . delay { 1 } . schedule ( 0.1 ) . then ( &:succ )
106- # => <#Concurrent::Edge::Future:0x7fc6228bcdc0 pending blocks:[]>
106+ # => <#Concurrent::Edge::Future:0x7fcc7313a758 pending blocks:[]>
107107# will not be scheduled until value is requested
108108sleep 0.1
109109scheduled . value # returns after another 0.1sec # => 2
112112### Completable Future and Event
113113
114114future = Concurrent . future
115- # => <#Concurrent::Edge::CompletableFuture:0x7fc623083720 pending blocks:[]>
115+ # => <#Concurrent::Edge::CompletableFuture:0x7fcc731286e8 pending blocks:[]>
116116event = Concurrent . event
117- # => <#Concurrent::Edge::CompletableEvent:0x7fc623081100 pending blocks:[]>
117+ # => <#Concurrent::Edge::CompletableEvent:0x7fcc73123058 pending blocks:[]>
118118# Don't forget to keep the reference, `Concurrent.future.then { |v| v }` is incompletable
119119
120120# will be blocked until completed
121121t1 = Thread . new { future . value }
122122t2 = Thread . new { event . wait }
123123
124124future . success 1
125- # => <#Concurrent::Edge::CompletableFuture:0x7fc623083720 success blocks:[]>
125+ # => <#Concurrent::Edge::CompletableFuture:0x7fcc731286e8 success blocks:[]>
126126future . success 1 rescue $!
127127 # => #<Concurrent::MultipleAssignmentError: Future can be completed only once. Current result is [true, 1, nil], trying to set [true, 1, nil]>
128128future . try_success 2 # => false
129129event . complete
130- # => <#Concurrent::Edge::CompletableEvent:0x7fc623081100 completed blocks:[]>
130+ # => <#Concurrent::Edge::CompletableEvent:0x7fcc73123058 completed blocks:[]>
131131
132132[ t1 , t2 ] . each &:join
133133
134134
135135### Callbacks
136136
137- queue = Queue . new # => #<Thread::Queue:0x007fc62127df00 >
137+ queue = Queue . new # => #<Thread::Queue:0x007fcc73110638 >
138138future = Concurrent . delay { 1 + 1 }
139- # => <#Concurrent::Edge::Future:0x7fc62127c060 pending blocks:[]>
139+ # => <#Concurrent::Edge::Future:0x7fcc7310ab98 pending blocks:[]>
140140
141141future . on_success { queue << 1 } # evaluated asynchronously
142- # => <#Concurrent::Edge::Future:0x7fc62127c060 pending blocks:[]>
142+ # => <#Concurrent::Edge::Future:0x7fcc7310ab98 pending blocks:[]>
143143future . on_success! { queue << 2 } # evaluated on completing thread
144- # => <#Concurrent::Edge::Future:0x7fc62127c060 pending blocks:[]>
144+ # => <#Concurrent::Edge::Future:0x7fcc7310ab98 pending blocks:[]>
145145
146146queue . empty? # => true
147147future . value # => 2
152152### Thread-pools
153153
154154Concurrent . future ( :fast ) { 2 } . then ( :io ) { File . read __FILE__ } . wait
155- # => <#Concurrent::Edge::Future:0x7fc62125d9a8 success blocks:[]>
155+ # => <#Concurrent::Edge::Future:0x7fcc730f98e8 success blocks:[]>
156156
157157
158158### Interoperability with actors
159159
160160actor = Concurrent ::Actor ::Utils ::AdHoc . spawn :square do
161161 -> v { v ** 2 }
162162end
163- # => #<Concurrent::Actor::Reference:0x7fc621234a30 /square (Concurrent::Actor::Utils::AdHoc)>
163+ # => #<Concurrent::Actor::Reference:0x7fcc730c36f8 /square (Concurrent::Actor::Utils::AdHoc)>
164164
165165Concurrent .
166166 future { 2 } .
173173
174174### Interoperability with channels
175175
176- ch1 = Concurrent ::Edge ::Channel . new # => #<Concurrent::Edge::Channel:0x007fc621205460 >
177- ch2 = Concurrent ::Edge ::Channel . new # => #<Concurrent::Edge::Channel:0x007fc6212041c8 >
176+ ch1 = Concurrent ::Edge ::Channel . new # => #<Concurrent::Edge::Channel:0x007fcc73043188 >
177+ ch2 = Concurrent ::Edge ::Channel . new # => #<Concurrent::Edge::Channel:0x007fcc730425f8 >
178178
179179result = Concurrent . select ( ch1 , ch2 )
180- # => <#Concurrent::Edge::CompletableFuture:0x7fc6211fe5c0 pending blocks:[]>
180+ # => <#Concurrent::Edge::CompletableFuture:0x7fcc730411a8 pending blocks:[]>
181181ch1 . push 1 # => nil
182182result . value!
183- # => [1, #<Concurrent::Edge::Channel:0x007fc621205460 >]
183+ # => [1, #<Concurrent::Edge::Channel:0x007fcc73043188 >]
184184
185185Concurrent .
186186 future { 1 +1 } .
187187 then_push ( ch1 )
188- # => <#Concurrent::Edge::Future:0x7fc6211f7338 pending blocks:[]>
188+ # => <#Concurrent::Edge::Future:0x7fcc73032c98 pending blocks:[]>
189189result = Concurrent .
190190 future { '%02d' } .
191191 then_select ( ch1 , ch2 ) .
192192 then { |format , ( value , channel ) | format format , value }
193- # => <#Concurrent::Edge::Future:0x7fc6211ec668 pending blocks:[]>
193+ # => <#Concurrent::Edge::Future:0x7fcc7302a4f8 pending blocks:[]>
194194result . value! # => "02"
195195
196196
197197### Common use-cases Examples
198198
199199# simple background processing
200200Concurrent . future { do_stuff }
201- # => <#Concurrent::Edge::Future:0x7fc6211df170 pending blocks:[]>
201+ # => <#Concurrent::Edge::Future:0x7fcc72123c48 pending blocks:[]>
202202
203203# parallel background processing
204204jobs = 10 . times . map { |i | Concurrent . future { i } }
@@ -215,7 +215,7 @@ def schedule_job
215215end # => :schedule_job
216216
217217schedule_job
218- # => <#Concurrent::Edge::Future:0x7fc62119c140 pending blocks:[]>
218+ # => <#Concurrent::Edge::Future:0x7fcc75011370 pending blocks:[]>
219219@end = true # => true
220220
221221
@@ -228,7 +228,7 @@ def schedule_job
228228 data [ message ]
229229 end
230230end
231- # => #<Concurrent::Actor::Reference:0x7fc62117f568 /db (Concurrent::Actor::Utils::AdHoc)>
231+ # => #<Concurrent::Actor::Reference:0x7fcc71832a08 /db (Concurrent::Actor::Utils::AdHoc)>
232232
233233concurrent_jobs = 11 . times . map do |v |
234234 Concurrent .
@@ -258,7 +258,7 @@ def schedule_job
258258 end
259259 end
260260end
261- # => #<Concurrent::Actor::Reference:0x7fc6218969f0 /DB-pool (Concurrent::Actor::Utils::Pool)>
261+ # => #<Concurrent::Actor::Reference:0x7fcc72320118 /DB-pool (Concurrent::Actor::Utils::Pool)>
262262
263263concurrent_jobs = 11 . times . map do |v |
264264 Concurrent .
0 commit comments