@@ -70,14 +70,14 @@ sleep call.
70
70
future.resolved?
71
71
```
72
72
73
- Retrieving the value will block until the future is resolved.
73
+ Retrieving the value will block until the future is ** resolved** .
74
74
75
75
``` ruby
76
76
future.value
77
77
future.resolved?
78
78
```
79
79
80
- If the task fails we talk about the future being rejected.
80
+ If the task fails, we talk about the future being ** rejected** .
81
81
82
82
``` ruby
83
83
future = Concurrent ::Promises .future { raise ' Boom' }
@@ -111,15 +111,15 @@ raise future rescue $!
111
111
112
112
## States
113
113
114
- Lets define a inspection helper for methods.
114
+ Let's define an inspection helper for methods.
115
115
116
116
``` ruby
117
117
def inspect_methods (* methods , of: )
118
118
methods.reduce({}) { |h , m | h.update m => of.send(m) }
119
119
end #
120
120
```
121
121
122
- Event has ` pending ` and ` resolved ` state.
122
+ Event has a ` pending ` and a ` resolved ` state.
123
123
124
124
``` ruby
125
125
event = Concurrent ::Promises .resolvable_event #
@@ -147,14 +147,14 @@ inspect_methods(:state, :pending?, :resolved?, :fulfilled?, :rejected?,
147
147
148
148
## Direct creation of resolved futures
149
149
150
- When an existing value has to wrapped in a future it does not have to go
150
+ When an existing value has to be wrapped in a future it does not have to go
151
151
through evaluation as follows.
152
152
153
153
``` ruby
154
154
Concurrent ::Promises .future { :value }
155
155
```
156
156
157
- Instead it can be created directly.
157
+ Instead, it can be created directly as already-resolved:
158
158
159
159
``` ruby
160
160
Concurrent ::Promises .fulfilled_future(:value )
@@ -165,8 +165,8 @@ Concurrent::Promises.resolved_future(false, nil, StandardError.new('Ups'))
165
165
166
166
## Chaining
167
167
168
- Big advantage of promises is ability to chain tasks together without blocking
169
- current thread.
168
+ A big advantage of promises is the ability to chain tasks together without blocking
169
+ the current thread.
170
170
171
171
``` ruby
172
172
Concurrent ::Promises .
@@ -175,7 +175,7 @@ Concurrent::Promises.
175
175
value!
176
176
```
177
177
178
- As ` future ` factory method takes argument, ` then ` method takes as well . Any
178
+ As ` future ` factory method takes an argument, so does the ` then ` method. Any
179
179
supplied arguments are passed to the block, and the library ensures that they
180
180
are visible to the block.
181
181
@@ -196,7 +196,7 @@ Concurrent::Promises.
196
196
```
197
197
198
198
Passing the arguments in (similarly as for a thread `Thread.new(arg) { |arg|
199
- do_stuff arg }`) is ** required** , both following examples may break.
199
+ do_stuff arg }`) is ** required** . Both of the following bad examples may break:
200
200
201
201
``` ruby
202
202
arg = 1
@@ -233,7 +233,7 @@ Concurrent::Promises.
233
233
value!
234
234
```
235
235
236
- Instead of zipping only the first one can be taken if needed.
236
+ Instead of zipping only the first one can be taken, if needed.
237
237
238
238
``` ruby
239
239
Concurrent ::Promises .any(branch1, branch2).value!
@@ -248,11 +248,11 @@ chaining.
248
248
249
249
If they need to be used (e.g. when integrating with threads), ` value! ` is a
250
250
better option over ` value ` when rejections are not dealt with differently.
251
- Otherwise the rejection are not handled and probably silently forgotten.
251
+ Otherwise the rejections are not handled and probably silently forgotten.
252
252
253
253
## Error handling
254
254
255
- When one of the tasks in the chain fails, the rejection propagates down the
255
+ When a task in the chain fails, the rejection propagates down the
256
256
chain without executing the tasks created with ` then ` .
257
257
258
258
``` ruby
@@ -289,7 +289,7 @@ Concurrent::Promises.
289
289
result
290
290
```
291
291
292
- Tasks added with ` chain ` are evaluated always.
292
+ Tasks added with ` chain ` are always evaluated .
293
293
294
294
``` ruby
295
295
Concurrent ::Promises .
@@ -334,7 +334,7 @@ All blocking methods like `wait`, `value` call `touch` and trigger evaluation.
334
334
Concurrent ::Promises .delay { :value }.value
335
335
```
336
336
337
- It propagates trough chain up allowing whole or partial lazy chains.
337
+ It propagates up through the chain, allowing whole or partial lazy chains.
338
338
339
339
``` ruby
340
340
head = Concurrent ::Promises .delay { 1 } #
@@ -368,17 +368,18 @@ join.value
368
368
369
369
## Flatting
370
370
371
- Sometimes it is needed to wait for a inner future. Apparent solution is to wait
372
- inside the future ` Concurrent::Promises.future { Concurrent::Promises.future { 1+1 }.value }.value `
373
- however as mentioned before, ` value ` calls should be ** avoided** to avoid
374
- blocking threads. Therefore there is a flat method which is a correct solution
371
+ Sometimes it is needed to wait for an inner future. An apparent solution is to wait
372
+ inside the future ` Concurrent::Promises.future { Concurrent::Promises.future { 1+1 }.value }.value ` .
373
+ However, as mentioned before, ` value ` calls should be ** avoided** to avoid
374
+ blocking threads. Therefore there is a ` # flat` method which is a correct solution
375
375
in this situation and does not block any thread.
376
376
377
377
``` ruby
378
378
Concurrent ::Promises .future { Concurrent ::Promises .future { 1 + 1 } }.flat.value!
379
379
```
380
380
381
381
A more complicated example.
382
+
382
383
``` ruby
383
384
Concurrent ::Promises .
384
385
future { Concurrent ::Promises .future { Concurrent ::Promises .future { 1 + 1 } } }.
@@ -405,8 +406,8 @@ Value will become available after 0.1 seconds.
405
406
scheduled.value
406
407
```
407
408
408
- It can be used in the chain as well, where the delay is counted form a moment
409
- its parent resolves. Therefore following future will be resolved in 0.2 seconds.
409
+ It can be used in the chain as well, where the delay is counted from the moment
410
+ its parent resolves. Therefore, the following future will be resolved in 0.2 seconds.
410
411
411
412
``` ruby
412
413
future = Concurrent ::Promises .
@@ -425,7 +426,7 @@ Concurrent::Promises.schedule(Time.now + 10) { :val }
425
426
## Resolvable Future and Event:
426
427
427
428
Sometimes it is required to resolve a future externally, in these cases
428
- ` resolvable_future ` and ` resolvable_event ` factory methods can be uses . See
429
+ ` resolvable_future ` and ` resolvable_event ` factory methods can be used . See
429
430
{Concurrent::Promises::ResolvableFuture} and
430
431
{Concurrent::Promises::ResolvableEvent}.
431
432
@@ -441,7 +442,7 @@ future.fulfill 1
441
442
thread.value
442
443
```
443
444
444
- Future can be resolved only once.
445
+ A future can be resolved only once.
445
446
446
447
``` ruby
447
448
future.fulfill 1 rescue $!
@@ -451,21 +452,21 @@ future.fulfill 2, false
451
452
## How are promises executed?
452
453
453
454
Promises use global pools to execute the tasks. Therefore each task may run on
454
- different thread which implies that users have to be careful not to depend on
455
- Thread local variables (or they have to set at the begging of the task and
455
+ different threads which implies that users have to be careful not to depend on
456
+ Thread- local variables (or they have to be set at the beginning of the task and
456
457
cleaned up at the end of the task).
457
458
458
459
Since the tasks are running on may different threads of the thread pool, it's
459
460
better to follow following rules:
460
461
461
- - Use only data passed in through arguments or values of parent futures, to
462
+ - Use only data passed via arguments or values of parent futures, to
462
463
have better control over what are futures accessing.
463
- - The data passed in and out of futures are easier to deal with if they are
464
+ - The data passed in and out of futures is easier to deal with if it is
464
465
immutable or at least treated as such.
465
- - Any mutable and mutated object accessed by more than one threads or futures
466
- must be thread safe, see {Concurrent::Array}, {Concurrent::Hash}, and
467
- {Concurrent::Map}. (Value of a future may be consumed by many futures.)
468
- - Futures can access outside objects, but they has to be thread-safe.
466
+ - Any mutable and mutated object accessed by more than one thread or future
467
+ must be thread- safe, see {Concurrent::Array}, {Concurrent::Hash}, and
468
+ {Concurrent::Map}. (The value of a future may be consumed by many futures.)
469
+ - Futures can access outside objects, but they have to be thread-safe.
469
470
470
471
> * TODO: This part to be extended*
471
472
@@ -488,12 +489,12 @@ queue.pop
488
489
489
490
## Using executors
490
491
491
- Factory methods, chain, and callback methods have all other version of them
492
- which takes executor argument.
492
+ Factory methods, chain, and callback methods all have other versions of them
493
+ which takes an executor argument.
493
494
494
- It takes an instance of an executor or a symbol which is a shortcuts for the
495
- two global pools in concurrent-ruby. ` fast ` for short and non-blocking tasks
496
- and ` :io ` for blocking and long tasks.
495
+ It takes an instance of an executor, or a symbol which is a shortcut for the
496
+ two global pools in concurrent-ruby. ` : fast` for short and non-blocking tasks
497
+ and ` :io ` for long-running and blocking tasks.
497
498
498
499
``` ruby
499
500
Concurrent ::Promises .future_on(:fast ) { 2 }.
@@ -505,7 +506,7 @@ Concurrent::Promises.future_on(:fast) { 2 }.
505
506
506
507
Similar to flatting is running. When ` run ` is called on a future it will flat
507
508
indefinitely as long the future fulfils into a ` Future ` value. It can be used
508
- to simulate a thread like processing without actually occupying the thread.
509
+ to simulate a thread- like processing without actually occupying the thread.
509
510
510
511
``` ruby
511
512
count = lambda do |v |
518
519
```
519
520
520
521
Therefore the above example finished fine on the the ` :fast ` thread pool even
521
- though it has much less threads than there is the simulated process.
522
+ though it has much fewer threads than are simulated in the simulated process.
522
523
523
524
# Interoperability
524
525
@@ -532,7 +533,7 @@ actor = Concurrent::Actor::Utils::AdHoc.spawn :square do
532
533
end
533
534
```
534
535
535
- Send result of ` 1+1 ` to the actor, and add 2 to the result send back from the
536
+ Send result of ` 1+1 ` to the actor, and add 2 to the result sent back from the
536
537
actor.
537
538
538
539
``` ruby
@@ -553,8 +554,8 @@ actor.ask(2).then(&:succ).value!
553
554
554
555
## Channel
555
556
556
- There is an implementation of channel as well. Lets start by creating a
557
- channel with capacity 2 messages.
557
+ There is an implementation of channel as well. Let's start by creating a
558
+ channel with a capacity of 2 messages.
558
559
559
560
``` ruby
560
561
ch1 = Concurrent ::Promises ::Channel .new 2
@@ -563,7 +564,7 @@ ch1 = Concurrent::Promises::Channel.new 2
563
564
We push 3 messages, it can be observed that the last future representing the
564
565
push is not fulfilled since the capacity prevents it. When the work which fills
565
566
the channel depends on the futures created by push it can be used to create
566
- back pressure – the filling work is delayed until the channel has space for
567
+ backpressure – the filling work is delayed until the channel has space for
567
568
more messages.
568
569
569
570
``` ruby
@@ -572,7 +573,7 @@ ch1.pop.value!
572
573
pushes
573
574
```
574
575
575
- A selection over channels can be created with select_channel factory method. It
576
+ A selection over channels can be created with the ` . select_channel` factory method. It
576
577
will be fulfilled with a first message available in any of the channels. It
577
578
returns a pair to be able to find out which channel had the message available.
578
579
@@ -592,12 +593,12 @@ result.value!
592
593
## ProcessingActor
593
594
594
595
There is also a new implementation of actors based on the Channel and the
595
- ability of promises to simulate process . The actor runs as a process but also
596
- does not occupy a thread per actor as previous Concurrent::Actor
596
+ ability of promises to simulate processes . The actor runs as a process but also
597
+ does not occupy a thread per actor as the previously-described Concurrent::Actor
597
598
implementation. This implementation is close to Erlang actors, therefore OTP
598
599
can be ported for this actors (and it's planned).
599
600
600
- The simplest actor is a one which just computes without even receiving a
601
+ The simplest actor is one which just computes without even receiving a
601
602
message.
602
603
603
604
``` ruby
@@ -621,7 +622,7 @@ add_2_messages.tell 3
621
622
add_2_messages.termination.value!
622
623
```
623
624
624
- Actors can also be used to apply back pressure to a producer. Let's start by
625
+ Actors can also be used to apply backpressure to a producer. Let's start by
625
626
defining an actor which a mailbox of size 2.
626
627
627
628
``` ruby
@@ -935,11 +936,11 @@ end #
935
936
futures.map(& :value! )
936
937
```
937
938
938
- ## Long stream of tasks, applying back pressure
939
+ ## Long stream of tasks, applying backpressure
939
940
940
- Lets assume that we queuing an API for a data and the queries can be faster
941
+ Let's assume that we are querying an API for data and the queries can be faster
941
942
than we are able to process them. This example shows how to use channel as a
942
- buffer and how to apply back pressure to slow down the queries.
943
+ buffer and how to apply backpressure to slow down the queries.
943
944
944
945
``` ruby
945
946
require ' json' #
@@ -1002,8 +1003,8 @@ end
1002
1003
sleep 0.5
1003
1004
```
1004
1005
1005
- Let it run for a while then cancel it and ensure that the runs all fulfilled
1006
- (therefore ended) after the cancellation. Finally print the result.
1006
+ Let it run for a while, then cancel it, and ensure that the runs were all fulfilled
1007
+ (therefore ended) after the cancellation. Finally, print the result.
1007
1008
1008
1009
``` ruby
1009
1010
source.cancel
@@ -1012,14 +1013,13 @@ word_counter_processes.map(&:wait!)
1012
1013
words
1013
1014
```
1014
1015
1015
- Compared to using threads directly this is highly configurable and compostable
1016
+ Compared to using threads directly, this is highly configurable and composable
1016
1017
solution.
1017
1018
1018
1019
1019
1020
## Periodic task
1020
1021
1021
- By combining ` schedule ` , ` run ` and ` Cancellation ` periodically executed task
1022
- can be easily created.
1022
+ A periodically executed task can be creating by combining ` schedule ` , ` run ` and ` Cancellation ` .
1023
1023
1024
1024
``` ruby
1025
1025
repeating_scheduled_task = -> interval, token, task do
0 commit comments