Skip to content

Commit 3265766

Browse files
authored
Merge pull request #687 from olleolleolle/documentation-promises
Docs edits to Promise docs
2 parents ec76361 + 7915e4a commit 3265766

File tree

2 files changed

+201
-200
lines changed

2 files changed

+201
-200
lines changed

doc/promises.in.md

Lines changed: 55 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ sleep call.
7070
future.resolved?
7171
```
7272

73-
Retrieving the value will block until the future is resolved.
73+
Retrieving the value will block until the future is **resolved**.
7474

7575
```ruby
7676
future.value
7777
future.resolved?
7878
```
7979

80-
If the task fails we talk about the future being rejected.
80+
If the task fails, we talk about the future being **rejected**.
8181

8282
```ruby
8383
future = Concurrent::Promises.future { raise 'Boom' }
@@ -111,15 +111,15 @@ raise future rescue $!
111111

112112
## States
113113

114-
Lets define a inspection helper for methods.
114+
Let's define an inspection helper for methods.
115115

116116
```ruby
117117
def inspect_methods(*methods, of:)
118118
methods.reduce({}) { |h, m| h.update m => of.send(m) }
119119
end #
120120
```
121121

122-
Event has `pending` and `resolved` state.
122+
Event has a `pending` and a `resolved` state.
123123

124124
```ruby
125125
event = Concurrent::Promises.resolvable_event #
@@ -147,14 +147,14 @@ inspect_methods(:state, :pending?, :resolved?, :fulfilled?, :rejected?,
147147

148148
## Direct creation of resolved futures
149149

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
151151
through evaluation as follows.
152152

153153
```ruby
154154
Concurrent::Promises.future { :value }
155155
```
156156

157-
Instead it can be created directly.
157+
Instead, it can be created directly as already-resolved:
158158

159159
```ruby
160160
Concurrent::Promises.fulfilled_future(:value)
@@ -165,8 +165,8 @@ Concurrent::Promises.resolved_future(false, nil, StandardError.new('Ups'))
165165

166166
## Chaining
167167

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.
170170

171171
```ruby
172172
Concurrent::Promises.
@@ -175,7 +175,7 @@ Concurrent::Promises.
175175
value!
176176
```
177177

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
179179
supplied arguments are passed to the block, and the library ensures that they
180180
are visible to the block.
181181

@@ -196,7 +196,7 @@ Concurrent::Promises.
196196
```
197197

198198
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:
200200

201201
```ruby
202202
arg = 1
@@ -233,7 +233,7 @@ Concurrent::Promises.
233233
value!
234234
```
235235

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.
237237

238238
```ruby
239239
Concurrent::Promises.any(branch1, branch2).value!
@@ -248,11 +248,11 @@ chaining.
248248

249249
If they need to be used (e.g. when integrating with threads), `value!` is a
250250
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.
252252

253253
## Error handling
254254

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
256256
chain without executing the tasks created with `then`.
257257

258258
```ruby
@@ -289,7 +289,7 @@ Concurrent::Promises.
289289
result
290290
```
291291

292-
Tasks added with `chain` are evaluated always.
292+
Tasks added with `chain` are always evaluated.
293293

294294
```ruby
295295
Concurrent::Promises.
@@ -334,7 +334,7 @@ All blocking methods like `wait`, `value` call `touch` and trigger evaluation.
334334
Concurrent::Promises.delay { :value }.value
335335
```
336336

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.
338338

339339
```ruby
340340
head = Concurrent::Promises.delay { 1 } #
@@ -368,17 +368,18 @@ join.value
368368

369369
## Flatting
370370

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
375375
in this situation and does not block any thread.
376376

377377
```ruby
378378
Concurrent::Promises.future { Concurrent::Promises.future { 1+1 } }.flat.value!
379379
```
380380

381381
A more complicated example.
382+
382383
```ruby
383384
Concurrent::Promises.
384385
future { Concurrent::Promises.future { Concurrent::Promises.future { 1 + 1 } } }.
@@ -405,8 +406,8 @@ Value will become available after 0.1 seconds.
405406
scheduled.value
406407
```
407408

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.
410411

411412
```ruby
412413
future = Concurrent::Promises.
@@ -425,7 +426,7 @@ Concurrent::Promises.schedule(Time.now + 10) { :val }
425426
## Resolvable Future and Event:
426427

427428
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
429430
{Concurrent::Promises::ResolvableFuture} and
430431
{Concurrent::Promises::ResolvableEvent}.
431432

@@ -441,7 +442,7 @@ future.fulfill 1
441442
thread.value
442443
```
443444

444-
Future can be resolved only once.
445+
A future can be resolved only once.
445446

446447
```ruby
447448
future.fulfill 1 rescue $!
@@ -451,21 +452,21 @@ future.fulfill 2, false
451452
## How are promises executed?
452453

453454
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
456457
cleaned up at the end of the task).
457458

458459
Since the tasks are running on may different threads of the thread pool, it's
459460
better to follow following rules:
460461

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
462463
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
464465
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.
469470

470471
> *TODO: This part to be extended*
471472
@@ -488,12 +489,12 @@ queue.pop
488489

489490
## Using executors
490491

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.
493494

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.
497498

498499
```ruby
499500
Concurrent::Promises.future_on(:fast) { 2 }.
@@ -505,7 +506,7 @@ Concurrent::Promises.future_on(:fast) { 2 }.
505506

506507
Similar to flatting is running. When `run` is called on a future it will flat
507508
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.
509510

510511
```ruby
511512
count = lambda do |v|
@@ -518,7 +519,7 @@ end
518519
```
519520

520521
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.
522523

523524
# Interoperability
524525

@@ -532,7 +533,7 @@ actor = Concurrent::Actor::Utils::AdHoc.spawn :square do
532533
end
533534
```
534535

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
536537
actor.
537538

538539
```ruby
@@ -553,8 +554,8 @@ actor.ask(2).then(&:succ).value!
553554

554555
## Channel
555556

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.
558559

559560
```ruby
560561
ch1 = Concurrent::Promises::Channel.new 2
@@ -563,7 +564,7 @@ ch1 = Concurrent::Promises::Channel.new 2
563564
We push 3 messages, it can be observed that the last future representing the
564565
push is not fulfilled since the capacity prevents it. When the work which fills
565566
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
567568
more messages.
568569

569570
```ruby
@@ -572,7 +573,7 @@ ch1.pop.value!
572573
pushes
573574
```
574575

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
576577
will be fulfilled with a first message available in any of the channels. It
577578
returns a pair to be able to find out which channel had the message available.
578579

@@ -592,12 +593,12 @@ result.value!
592593
## ProcessingActor
593594

594595
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
597598
implementation. This implementation is close to Erlang actors, therefore OTP
598599
can be ported for this actors (and it's planned).
599600

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
601602
message.
602603

603604
```ruby
@@ -621,7 +622,7 @@ add_2_messages.tell 3
621622
add_2_messages.termination.value!
622623
```
623624

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
625626
defining an actor which a mailbox of size 2.
626627

627628
```ruby
@@ -935,11 +936,11 @@ end #
935936
futures.map(&:value!)
936937
```
937938

938-
## Long stream of tasks, applying back pressure
939+
## Long stream of tasks, applying backpressure
939940

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
941942
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.
943944

944945
```ruby
945946
require 'json' #
@@ -1002,8 +1003,8 @@ end
10021003
sleep 0.5
10031004
```
10041005

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.
10071008

10081009
```ruby
10091010
source.cancel
@@ -1012,14 +1013,13 @@ word_counter_processes.map(&:wait!)
10121013
words
10131014
```
10141015

1015-
Compared to using threads directly this is highly configurable and compostable
1016+
Compared to using threads directly, this is highly configurable and composable
10161017
solution.
10171018

10181019

10191020
## Periodic task
10201021

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`.
10231023

10241024
```ruby
10251025
repeating_scheduled_task = -> interval, token, task do

0 commit comments

Comments
 (0)