Skip to content

Commit 41cf14d

Browse files
committed
More documentation for Throttle and other minor improvmenets
1 parent 9d7b3cb commit 41cf14d

File tree

7 files changed

+172
-87
lines changed

7 files changed

+172
-87
lines changed

doc/promises.in.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -757,12 +757,12 @@ pool of size 3. We create throttle with the same size
757757
```ruby
758758
DB_INTERNAL_POOL = Concurrent::Array.new data
759759

760-
max_tree = Promises::Throttle.new 3
760+
max_tree = Concurrent::Throttle.new 3
761761

762762
futures = 11.times.map do |i|
763763
max_tree.
764764
# throttled tasks, at most 3 simultaneous calls of [] on the database
765-
then_throttled { DB_INTERNAL_POOL[i] }.
765+
throttled_future { DB_INTERNAL_POOL[i] }.
766766
# un-throttled tasks, unlimited concurrency
767767
then { |starts| starts.size }.
768768
rescue { |reason| reason.message }

doc/promises.out.md

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,17 @@ Class.new do
4747
resolvable_event
4848
end
4949
end.new.a_method
50-
# => <#Concurrent::Promises::ResolvableEvent:0x7fa95ca52488 pending>
50+
# => <#Concurrent::Promises::ResolvableEvent:0x7fb4ba3e8c78 pending>
5151

5252
Module.new { extend Concurrent::Promises::FactoryMethods }.resolvable_event
53-
# => <#Concurrent::Promises::ResolvableEvent:0x7fa95ca4a9e0 pending>
53+
# => <#Concurrent::Promises::ResolvableEvent:0x7fb4ba3e2850 pending>
5454
```
5555

5656
The module is already extended into {Concurrent::Promises} for convenience.
5757

5858
```ruby
5959
Concurrent::Promises.resolvable_event
60-
# => <#Concurrent::Promises::ResolvableEvent:0x7fa95ca48708 pending>
60+
# => <#Concurrent::Promises::ResolvableEvent:0x7fb4ba3e08e8 pending>
6161
```
6262

6363
For this guide we introduce a shortcut in `main` so we can call the factory
@@ -66,7 +66,7 @@ methods in following examples by using `Promisses` directly.
6666
```ruby
6767
Promises = Concurrent::Promises
6868
Promises.resolvable_event
69-
# => <#Concurrent::Promises::ResolvableEvent:0x7fa95ca41d18 pending>
69+
# => <#Concurrent::Promises::ResolvableEvent:0x7fb4ba3d8be8 pending>
7070
```
7171

7272
## Asynchronous task
@@ -82,7 +82,7 @@ future = Promises.future(0.1) do |duration|
8282
sleep duration
8383
:result
8484
end
85-
# => <#Concurrent::Promises::Future:0x7fa95b3eb410 pending>
85+
# => <#Concurrent::Promises::Future:0x7fb4ba3c8248 pending>
8686
```
8787

8888
Asks if the future is resolved, here it will be still in the middle of the
@@ -103,7 +103,7 @@ If the task fails we talk about the future being rejected.
103103

104104
```ruby
105105
future = Promises.future { raise 'Boom' }
106-
# => <#Concurrent::Promises::Future:0x7fa95b3dae58 pending>
106+
# => <#Concurrent::Promises::Future:0x7fb4ba3b1bd8 pending>
107107
```
108108

109109
There is no result, the future was rejected with a reason.
@@ -198,20 +198,20 @@ through evaluation as follows.
198198

199199
```ruby
200200
Promises.future { :value }
201-
# => <#Concurrent::Promises::Future:0x7fa95b89f510 pending>
201+
# => <#Concurrent::Promises::Future:0x7fb4ba322230 pending>
202202
```
203203

204204
Instead it can be created directly.
205205

206206
```ruby
207207
Promises.fulfilled_future(:value)
208-
# => <#Concurrent::Promises::Future:0x7fa95b390bc8 fulfilled>
208+
# => <#Concurrent::Promises::Future:0x7fb4ba31a648 fulfilled>
209209
Promises.rejected_future(StandardError.new('Ups'))
210-
# => <#Concurrent::Promises::Future:0x7fa95b38b628 rejected>
210+
# => <#Concurrent::Promises::Future:0x7fb4ba319298 rejected>
211211
Promises.resolved_future(true, :value, nil)
212-
# => <#Concurrent::Promises::Future:0x7fa95b38a688 fulfilled>
212+
# => <#Concurrent::Promises::Future:0x7fb4ba3133e8 fulfilled>
213213
Promises.resolved_future(false, nil, StandardError.new('Ups'))
214-
# => <#Concurrent::Promises::Future:0x7fa95b3892b0 rejected>
214+
# => <#Concurrent::Promises::Future:0x7fb4ba311700 rejected>
215215
```
216216

217217
## Chaining
@@ -252,9 +252,9 @@ do_stuff arg }`) is **required**, both following examples may break.
252252
```ruby
253253
arg = 1 # => 1
254254
Thread.new { do_stuff arg }
255-
# => #<Thread:0x007fa95b322fd8@promises.in.md:193 run>
255+
# => #<Thread:0x007fb4ba2a2710@promises.in.md:193 run>
256256
Promises.future { do_stuff arg }
257-
# => <#Concurrent::Promises::Future:0x7fa95b321020 pending>
257+
# => <#Concurrent::Promises::Future:0x7fb4ba2a0dc0 pending>
258258
```
259259

260260
## Branching, and zipping
@@ -316,7 +316,7 @@ Promises.
316316
result
317317
# => [false,
318318
# nil,
319-
# #<NoMethodError: undefined method `succ' for #<Object:0x007fa95ca28368>>]
319+
# #<NoMethodError: undefined method `succ' for #<Object:0x007fb4ba2310d8>>]
320320
```
321321

322322
As `then` chained tasks execute only on fulfilled futures, there is a `rescue`
@@ -364,7 +364,7 @@ Zip is rejected if any of the zipped futures is.
364364
rejected_zip = Promises.zip(
365365
Promises.fulfilled_future(1),
366366
Promises.rejected_future(StandardError.new('Ups')))
367-
# => <#Concurrent::Promises::Future:0x7fa95b2428e8 rejected>
367+
# => <#Concurrent::Promises::Future:0x7fb4bc332390 rejected>
368368
rejected_zip.result
369369
# => [false, [1, nil], [nil, #<StandardError: Ups>]]
370370
rejected_zip.
@@ -379,11 +379,11 @@ requiring resolution.
379379

380380
```ruby
381381
future = Promises.delay { sleep 0.1; 'lazy' }
382-
# => <#Concurrent::Promises::Future:0x7fa95b229eb0 pending>
382+
# => <#Concurrent::Promises::Future:0x7fb4bc3188f0 pending>
383383
sleep 0.1
384384
future.resolved? # => false
385385
future.touch
386-
# => <#Concurrent::Promises::Future:0x7fa95b229eb0 pending>
386+
# => <#Concurrent::Promises::Future:0x7fb4bc3188f0 pending>
387387
sleep 0.2
388388
future.resolved? # => true
389389
```
@@ -460,7 +460,7 @@ Schedule task to be executed in 0.1 seconds.
460460

461461
```ruby
462462
scheduled = Promises.schedule(0.1) { 1 }
463-
# => <#Concurrent::Promises::Future:0x7fa95c9b1ce0 pending>
463+
# => <#Concurrent::Promises::Future:0x7fb4bc288958 pending>
464464
scheduled.resolved? # => false
465465
```
466466

@@ -485,7 +485,7 @@ Time can be used as well.
485485

486486
```ruby
487487
Promises.schedule(Time.now + 10) { :val }
488-
# => <#Concurrent::Promises::Future:0x7fa95c972ae0 pending>
488+
# => <#Concurrent::Promises::Future:0x7fb4bc252330 pending>
489489
```
490490

491491
## Resolvable Future and Event:
@@ -497,15 +497,15 @@ Sometimes it is required to resolve a future externally, in these cases
497497

498498
```ruby
499499
future = Promises.resolvable_future
500-
# => <#Concurrent::Promises::ResolvableFuture:0x7fa95c970e98 pending>
500+
# => <#Concurrent::Promises::ResolvableFuture:0x7fb4bc250620 pending>
501501
```
502502

503503
The thread will be blocked until the future is resolved
504504

505505
```ruby
506506
thread = Thread.new { future.value }
507507
future.fulfill 1
508-
# => <#Concurrent::Promises::ResolvableFuture:0x7fa95c970e98 fulfilled>
508+
# => <#Concurrent::Promises::ResolvableFuture:0x7fb4bc250620 fulfilled>
509509
thread.value # => 1
510510
```
511511

@@ -522,9 +522,9 @@ future.fulfill 2, false # => false
522522
## Callbacks
523523

524524
```ruby
525-
queue = Queue.new # => #<Thread::Queue:0x007fa95e0565b8>
525+
queue = Queue.new # => #<Thread::Queue:0x007fb4bb9d5e78>
526526
future = Promises.delay { 1 + 1 }
527-
# => <#Concurrent::Promises::Future:0x7fa95e0547b8 pending>
527+
# => <#Concurrent::Promises::Future:0x7fb4bb9d4730 pending>
528528

529529
future.on_fulfillment { queue << 1 } # evaluated asynchronously
530530
future.on_fulfillment! { queue << 2 } # evaluated on resolving thread
@@ -547,7 +547,7 @@ and `:io` for blocking and long tasks.
547547
```ruby
548548
Promises.future_on(:fast) { 2 }.
549549
then_on(:io) { File.read __FILE__ }.
550-
value.size # => 18760
550+
value.size # => 18764
551551
```
552552

553553
# Interoperability
@@ -560,7 +560,7 @@ Create an actor which takes received numbers and returns the number squared.
560560
actor = Concurrent::Actor::Utils::AdHoc.spawn :square do
561561
-> v { v ** 2 }
562562
end
563-
# => #<Concurrent::Actor::Reference:0x7fa95c919e90 /square (Concurrent::Actor::Utils::AdHoc)>
563+
# => #<Concurrent::Actor::Reference:0x7fb4bb986670 /square (Concurrent::Actor::Utils::AdHoc)>
564564
```
565565

566566
Send result of `1+1` to the actor, and add 2 to the result send back from the
@@ -592,17 +592,17 @@ actor.ask(2).then(&:succ).value! # => 5
592592

593593
```ruby
594594
Promises.future { do_stuff }
595-
# => <#Concurrent::Promises::Future:0x7fa95b1eb8e0 pending>
595+
# => <#Concurrent::Promises::Future:0x7fb4bb947740 pending>
596596
```
597597

598598
## Parallel background processing
599599

600600
```ruby
601601
tasks = 4.times.map { |i| Promises.future(i) { |i| i*2 } }
602-
# => [<#Concurrent::Promises::Future:0x7fa95b1e2e48 pending>,
603-
# <#Concurrent::Promises::Future:0x7fa95b1e1f70 pending>,
604-
# <#Concurrent::Promises::Future:0x7fa95b1e1188 pending>,
605-
# <#Concurrent::Promises::Future:0x7fa95b1e0198 pending>]
602+
# => [<#Concurrent::Promises::Future:0x7fb4bb93f090 pending>,
603+
# <#Concurrent::Promises::Future:0x7fb4bb93e488 pending>,
604+
# <#Concurrent::Promises::Future:0x7fb4bb93d6f0 pending>,
605+
# <#Concurrent::Promises::Future:0x7fb4bb93c778 pending>]
606606
Promises.zip(*tasks).value! # => [0, 2, 4, 6]
607607
```
608608

@@ -655,11 +655,11 @@ Create the computer actor and send it 3 jobs.
655655

656656
```ruby
657657
computer = Concurrent::Actor.spawn Computer, :computer
658-
# => #<Concurrent::Actor::Reference:0x7fa95a3f2c48 /computer (Computer)>
658+
# => #<Concurrent::Actor::Reference:0x7fb4ba9b3388 /computer (Computer)>
659659
results = 3.times.map { computer.ask [:run, -> { sleep 0.1; :result }] }
660-
# => [<#Concurrent::Promises::Future:0x7fa95a3d30c8 pending>,
661-
# <#Concurrent::Promises::Future:0x7fa95a3d0e40 pending>,
662-
# <#Concurrent::Promises::Future:0x7fa95a3cb760 pending>]
660+
# => [<#Concurrent::Promises::Future:0x7fb4ba990450 pending>,
661+
# <#Concurrent::Promises::Future:0x7fb4ba9897e0 pending>,
662+
# <#Concurrent::Promises::Future:0x7fb4ba988318 pending>]
663663
computer.ask(:status).value! # => {:running_jobs=>3}
664664
results.map(&:value!) # => [:result, :result, :result]
665665
```
@@ -706,8 +706,8 @@ Lets have two processes which will count until cancelled.
706706

707707
```ruby
708708
source, token = Concurrent::Cancellation.create
709-
# => [<#Concurrent::Cancellation:0x7fa95a223840 canceled:false>,
710-
# <#Concurrent::Cancellation::Token:0x7fa95a2222b0 canceled:false>]
709+
# => [<#Concurrent::Cancellation:0x7fb4ba1bc300 canceled:false>,
710+
# <#Concurrent::Cancellation::Token:0x7fb4ba1b7670 canceled:false>]
711711

712712
count_until_cancelled = -> token, count do
713713
if token.canceled?
@@ -720,12 +720,12 @@ end
720720
futures = Array.new(2) do
721721
Promises.future(token, 0, &count_until_cancelled).run
722722
end
723-
# => [<#Concurrent::Promises::Future:0x7fa95b1b8a08 pending>,
724-
# <#Concurrent::Promises::Future:0x7fa95b1aa110 pending>]
723+
# => [<#Concurrent::Promises::Future:0x7fb4ba13d578 pending>,
724+
# <#Concurrent::Promises::Future:0x7fb4ba13c308 pending>]
725725

726726
sleep 0.01
727727
source.cancel # => true
728-
futures.map(&:value!) # => [65, 66]
728+
futures.map(&:value!) # => [35, 34]
729729
```
730730

731731
Cancellation can also be used as event or future to log or plan re-execution.
@@ -744,8 +744,8 @@ tasks share a cancellation, when one of them fails it cancels the others.
744744

745745
```ruby
746746
source, token = Concurrent::Cancellation.create
747-
# => [<#Concurrent::Cancellation:0x7fa95c9c8c60 canceled:false>,
748-
# <#Concurrent::Cancellation::Token:0x7fa95c9c8710 canceled:false>]
747+
# => [<#Concurrent::Cancellation:0x7fb4ba053130 canceled:false>,
748+
# <#Concurrent::Cancellation::Token:0x7fb4ba051fb0 canceled:false>]
749749
tasks = 4.times.map do |i|
750750
Promises.future(source, token, i) do |source, token, i|
751751
count = 0
@@ -761,22 +761,22 @@ tasks = 4.times.map do |i|
761761
end
762762
end
763763
end
764-
# => [<#Concurrent::Promises::Future:0x7fa95c9a1818 pending>,
765-
# <#Concurrent::Promises::Future:0x7fa95c9a0aa8 pending>,
766-
# <#Concurrent::Promises::Future:0x7fa95c98bb30 pending>,
767-
# <#Concurrent::Promises::Future:0x7fa95c98aed8 pending>]
764+
# => [<#Concurrent::Promises::Future:0x7fb4ba03b0f8 pending>,
765+
# <#Concurrent::Promises::Future:0x7fb4ba0397a8 pending>,
766+
# <#Concurrent::Promises::Future:0x7fb4ba038308 pending>,
767+
# <#Concurrent::Promises::Future:0x7fb4ba0332b8 pending>]
768768
Promises.zip(*tasks).result
769769
# => [false,
770-
# [nil, :cancelled, :cancelled, nil],
771-
# [#<RuntimeError: random error>, nil, nil, #<RuntimeError: random error>]]
770+
# [:cancelled, :cancelled, nil, :cancelled],
771+
# [nil, nil, #<RuntimeError: random error>, nil]]
772772
```
773773

774774
Without the randomly failing part it produces following.
775775

776776
```ruby
777777
source, token = Concurrent::Cancellation.create
778-
# => [<#Concurrent::Cancellation:0x7fa95ca897d0 canceled:false>,
779-
# <#Concurrent::Cancellation::Token:0x7fa95ca83c68 canceled:false>]
778+
# => [<#Concurrent::Cancellation:0x7fb4bb9ee0b8 canceled:false>,
779+
# <#Concurrent::Cancellation::Token:0x7fb4bb9ed9d8 canceled:false>]
780780
tasks = 4.times.map do |i|
781781
Promises.future(source, token, i) do |source, token, i|
782782
count = 0
@@ -884,13 +884,13 @@ DB_INTERNAL_POOL = Concurrent::Array.new data
884884
# "********",
885885
# "*********"]
886886

887-
max_tree = Promises::Throttle.new 3
888-
# => <#Concurrent::Promises::Throttle:0x7fa95b2d0cb0 limit:3 can_run:3>
887+
max_tree = Concurrent::Throttle.new 3
888+
# => <#Concurrent::Throttle:0x7fb4ba2f22d8 limit:3 can_run:3>
889889

890890
futures = 11.times.map do |i|
891891
max_tree.
892892
# throttled tasks, at most 3 simultaneous calls of [] on the database
893-
then_throttled { DB_INTERNAL_POOL[i] }.
893+
throttled_future { DB_INTERNAL_POOL[i] }.
894894
# un-throttled tasks, unlimited concurrency
895895
then { |starts| starts.size }.
896896
rescue { |reason| reason.message }
@@ -927,7 +927,7 @@ def schedule_job(interval, &job)
927927
end
928928
end
929929

930-
queue = Queue.new # => #<Thread::Queue:0x007fa95e08d838>
930+
queue = Queue.new # => #<Thread::Queue:0x007fb4ba201568>
931931
count = 0 # => 0
932932
interval = 0.05 # small just not to delay execution of this example
933933

lib/concurrent-edge.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@
1212

1313
require 'concurrent/edge/promises'
1414
require 'concurrent/edge/cancellation'
15+
require 'concurrent/edge/throttle'

lib/concurrent/edge/lock_free_linked_set.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def remove(item)
124124
#
125125
# An iterator to loop through the set.
126126
#
127-
# @yield [Object] each item in the set
127+
# @yield [item] each item in the set
128128
# @yieldparam [Object] item the item you to remove from the set
129129
#
130130
# @return [Object] self: the linked set on which each was called

0 commit comments

Comments
 (0)