Skip to content

Commit d194d71

Browse files
committed
Documentation update
1 parent b1a6c80 commit d194d71

File tree

4 files changed

+160
-72
lines changed

4 files changed

+160
-72
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ be obeyed though. Features developed in `concurrent-ruby-edge` are expected to m
106106
Communicating Sequential Processes (CSP).
107107
* [Exchanger](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Exchanger.html)
108108
* [LazyRegister](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/LazyRegister.html)
109+
* [New Future Promise Framework](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Edge.html) - new
110+
unified implementation of Futures and Promises which combines Features of previous `Future`,
111+
`Promise`, `IVar`, `Probe`, `dataflow`, `Delay`, `TimerTask` into single framework. It uses extensively
112+
new synchronization layer to make all the paths lock-free with exception of blocking threads on `#wait`.
113+
It offers better performance and does not block threads (exception being `#wait` and similar methods where it's
114+
intended).
115+
109116

110117
## Usage
111118

examples/edge_futures.in.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
branch1 = head.then(&:succ) #
2424
branch2 = head.then(&:succ).then(&:succ) #
2525
branch1.zip(branch2).value
26-
(branch1 & branch2).then { |(a, b)| a + b }.value
26+
(branch1 & branch2).then { |a, b| a + b }.value!
27+
(branch1 & branch2).then(&:+).value!
28+
Concurrent.zip(branch1, branch2, branch1).then { |*values| values.reduce &:+ }.value!
2729
# pick only first completed
2830
(branch1 | branch2).value
2931

@@ -170,7 +172,7 @@
170172

171173
def schedule_job
172174
Concurrent.schedule(1) { do_stuff }.
173-
rescue { |e| report_error e }.
175+
rescue { |e| StandardError === e ? report_error(e) : raise(e) }.
174176
then { schedule_job unless @end }
175177
end
176178

@@ -214,7 +216,7 @@ def work(message)
214216
end
215217
end
216218

217-
data = Array.new(10) { |i| '*' * i }
219+
data = Array.new(10) { |i| '*' * i }
218220
pool_size = 5
219221

220222
DB_POOL = Concurrent::Actor::Utils::Pool.spawn!('DB-pool', pool_size) do |balancer, index|

examples/edge_futures.out.rb

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
### Simple asynchronous task
22

33
future = Concurrent.future { sleep 0.1; 1 + 1 } # evaluation starts immediately
4-
# => <#Concurrent::Edge::Future:0x7fad9ca186e0 pending blocks:[]>
4+
# => <#Concurrent::Edge::Future:0x7f9f549266e8 pending blocks:[]>
55
future.completed? # => false
66
# block until evaluated
77
future.value # => 2
@@ -11,7 +11,7 @@
1111
### Failing asynchronous task
1212

1313
future = Concurrent.future { raise 'Boom' }
14-
# => <#Concurrent::Edge::Future:0x7fad9c9f95b0 pending blocks:[]>
14+
# => <#Concurrent::Edge::Future:0x7f9f548dd3f8 pending blocks:[]>
1515
future.value # => nil
1616
future.value! rescue $! # => #<RuntimeError: Boom>
1717
future.reason # => #<RuntimeError: Boom>
@@ -23,10 +23,13 @@
2323

2424
head = Concurrent.future { 1 }
2525
branch1 = head.then(&:succ)
26-
branch2 = head.then(&:succ).then(&:succ)
26+
branch2 = head.then(&:succ).then(&:succ)
27+
# zipping futures
2728
branch1.zip(branch2).value # => [2, 3]
28-
(branch1 & branch2).then { |(a, b)| a + b }.value
29-
# => nil
29+
(branch1 & branch2).then { |a, b| a + b }.value! # => 5
30+
(branch1 & branch2).then(&:+).value! # => 5
31+
Concurrent.zip(branch1, branch2, branch1).then { |*values| values.reduce &:+ }.value!
32+
# => 7
3033
# pick only first completed
3134
(branch1 | branch2).value # => 2
3235

@@ -45,21 +48,21 @@
4548

4649
# will not evaluate until asked by #value or other method requiring completion
4750
future = Concurrent.delay { 'lazy' }
48-
# => <#Concurrent::Edge::Future:0x7fad9c8fb3e8 pending blocks:[]>
51+
# => <#Concurrent::Edge::Future:0x7f9f53a57b58 pending blocks:[]>
4952
sleep 0.1
5053
future.completed? # => false
5154
future.value # => "lazy"
5255

5356
# propagates trough chain allowing whole or partial lazy chains
5457

5558
head = Concurrent.delay { 1 }
56-
# => <#Concurrent::Edge::Future:0x7fad9b158bf0 pending blocks:[]>
59+
# => <#Concurrent::Edge::Future:0x7f9f53a35508 pending blocks:[]>
5760
branch1 = head.then(&:succ)
58-
# => <#Concurrent::Edge::Future:0x7fad9b149ba0 pending blocks:[]>
61+
# => <#Concurrent::Edge::Future:0x7f9f53a17328 pending blocks:[]>
5962
branch2 = head.delay.then(&:succ)
60-
# => <#Concurrent::Edge::Future:0x7fad9b12a020 pending blocks:[]>
63+
# => <#Concurrent::Edge::Future:0x7f9f5590d868 pending blocks:[]>
6164
join = branch1 & branch2
62-
# => <#Concurrent::Edge::ArrayFuture:0x7fad9b8a0778 pending blocks:[]>
65+
# => <#Concurrent::Edge::ArrayFuture:0x7f9f558fd7d8 pending blocks:[]>
6366

6467
sleep 0.1 # nothing will complete # => 0
6568
[head, branch1, branch2, join].map(&:completed?) # => [false, false, false, false]
@@ -87,14 +90,14 @@
8790
### Schedule
8891

8992
scheduled = Concurrent.schedule(0.1) { 1 }
90-
# => <#Concurrent::Edge::Future:0x7fad9a941e08 pending blocks:[]>
93+
# => <#Concurrent::Edge::Future:0x7f9f5581ed30 pending blocks:[]>
9194

9295
scheduled.completed? # => false
9396
scheduled.value # available after 0.1sec # => 1
9497

9598
# and in chain
9699
scheduled = Concurrent.delay { 1 }.schedule(0.1).then(&:succ)
97-
# => <#Concurrent::Edge::Future:0x7fad9b0aa7d0 pending blocks:[]>
100+
# => <#Concurrent::Edge::Future:0x7f9f548494c8 pending blocks:[]>
98101
# will not be scheduled until value is requested
99102
sleep 0.1
100103
scheduled.value # returns after another 0.1sec # => 2
@@ -103,35 +106,35 @@
103106
### Completable Future and Event
104107

105108
future = Concurrent.future
106-
# => <#Concurrent::Edge::CompletableFuture:0x7fad9a87b6e0 pending blocks:[]>
109+
# => <#Concurrent::Edge::CompletableFuture:0x7f9f5385bcf0 pending blocks:[]>
107110
event = Concurrent.event
108-
# => <#Concurrent::Edge::CompletableEvent:0x7fad9a86ba88 pending blocks:[]>
111+
# => <#Concurrent::Edge::CompletableEvent:0x7f9f53858ca8 pending blocks:[]>
109112

110113
# will be blocked until completed
111114
t1 = Thread.new { future.value }
112115
t2 = Thread.new { event.wait }
113116

114117
future.success 1
115-
# => <#Concurrent::Edge::CompletableFuture:0x7fad9a87b6e0 success blocks:[]>
118+
# => <#Concurrent::Edge::CompletableFuture:0x7f9f5385bcf0 success blocks:[]>
116119
future.success 1 rescue $!
117120
# => #<Concurrent::MultipleAssignmentError: multiple assignment>
118121
future.try_success 2 # => false
119122
event.complete
120-
# => <#Concurrent::Edge::CompletableEvent:0x7fad9a86ba88 completed blocks:[]>
123+
# => <#Concurrent::Edge::CompletableEvent:0x7f9f53858ca8 completed blocks:[]>
121124

122125
[t1, t2].each &:join
123126

124127

125128
### Callbacks
126129

127-
queue = Queue.new # => #<Thread::Queue:0x007fad9a862320>
130+
queue = Queue.new # => #<Thread::Queue:0x007f9f53861b50>
128131
future = Concurrent.delay { 1 + 1 }
129-
# => <#Concurrent::Edge::Future:0x7fad9a853960 pending blocks:[]>
132+
# => <#Concurrent::Edge::Future:0x7f9f54853d10 pending blocks:[]>
130133

131134
future.on_success { queue << 1 } # evaluated asynchronously
132-
# => <#Concurrent::Edge::Future:0x7fad9a853960 pending blocks:[]>
135+
# => <#Concurrent::Edge::Future:0x7f9f54853d10 pending blocks:[]>
133136
future.on_success! { queue << 2 } # evaluated on completing thread
134-
# => <#Concurrent::Edge::Future:0x7fad9a853960 pending blocks:[]>
137+
# => <#Concurrent::Edge::Future:0x7f9f54853d10 pending blocks:[]>
135138

136139
queue.empty? # => true
137140
future.value # => 2
@@ -142,7 +145,7 @@
142145
### Thread-pools
143146

144147
Concurrent.future(:fast) { 2 }.then(:io) { File.read __FILE__ }.wait
145-
# => <#Concurrent::Edge::Future:0x7fad9a883958 success blocks:[]>
148+
# => <#Concurrent::Edge::Future:0x7f9f539545f8 success blocks:[]>
146149

147150

148151
### Interoperability with actors
@@ -163,32 +166,32 @@
163166

164167
### Interoperability with channels
165168

166-
ch1 = Concurrent::Edge::Channel.new # => #<Concurrent::Edge::Channel:0x007fad9c892ac8>
167-
ch2 = Concurrent::Edge::Channel.new # => #<Concurrent::Edge::Channel:0x007fad9c8904a8>
169+
ch1 = Concurrent::Edge::Channel.new # => #<Concurrent::Edge::Channel:0x007f9f558e5db8>
170+
ch2 = Concurrent::Edge::Channel.new # => #<Concurrent::Edge::Channel:0x007f9f558e4f80>
168171

169172
result = Concurrent.select(ch1, ch2)
170-
# => <#Concurrent::Edge::CompletableFuture:0x7fad9b86aa88 pending blocks:[]>
173+
# => <#Concurrent::Edge::CompletableFuture:0x7f9f53a4fe58 pending blocks:[]>
171174
ch1.push 1 # => nil
172175
result.value!
173-
# => [1, #<Concurrent::Edge::Channel:0x007fad9c892ac8>]
176+
# => [1, #<Concurrent::Edge::Channel:0x007f9f558e5db8>]
174177

175178
Concurrent.
176179
future { 1+1 }.
177180
then_push(ch1)
178-
# => <#Concurrent::Edge::Future:0x7fad9c898d88 pending blocks:[]>
181+
# => <#Concurrent::Edge::Future:0x7f9f53a2e758 pending blocks:[]>
179182
result = Concurrent.
180183
future { '%02d' }.
181184
then_select(ch1, ch2).
182185
then { |format, (value, channel)| format format, value }
183-
# => <#Concurrent::Edge::Future:0x7fad9b88b4e0 pending blocks:[]>
186+
# => <#Concurrent::Edge::Future:0x7f9f55925f30 pending blocks:[]>
184187
result.value! # => "02"
185188

186189

187190
### Common use-cases Examples
188191

189192
# simple background processing
190193
Concurrent.future { do_stuff }
191-
# => <#Concurrent::Edge::Future:0x7fad9b151b98 pending blocks:[]>
194+
# => <#Concurrent::Edge::Future:0x7f9f53a93e50 pending blocks:[]>
192195

193196
# parallel background processing
194197
jobs = 10.times.map { |i| Concurrent.future { i } }
@@ -200,12 +203,12 @@
200203

201204
def schedule_job
202205
Concurrent.schedule(1) { do_stuff }.
203-
rescue { |e| report_error e }.
206+
rescue { |e| StandardError === e ? report_error(e) : raise(e) }.
204207
then { schedule_job unless @end }
205208
end # => :schedule_job
206209

207210
schedule_job
208-
# => <#Concurrent::Edge::Future:0x7fad9c96a6a8 pending blocks:[]>
211+
# => <#Concurrent::Edge::Future:0x7f9f548b01a0 pending blocks:[]>
209212
@end = true # => true
210213

211214

@@ -247,7 +250,7 @@ def work(message)
247250
end
248251
end # => :work
249252

250-
data = Array.new(10) { |i| '*' * i }
253+
data = Array.new(10) { |i| '*' * i }
251254
# => ["", "*", "**", "***", "****", "*****", "******", "*******", "********", "*********"]
252255
pool_size = 5 # => 5
253256

0 commit comments

Comments
 (0)