Skip to content

Commit b5b90ff

Browse files
committed
Fix typos and wording
1 parent 0334cfb commit b5b90ff

File tree

2 files changed

+89
-78
lines changed

2 files changed

+89
-78
lines changed

doc/synchronization-notes.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Concurrent Ruby Notes
2+
3+
## Locks
4+
5+
Concurrent Ruby also has an internal extension of `Object` called
6+
`LockableObject`, which provides same synchronization primitives as Java's
7+
Object: `synchronize(&block)`, `wait(timeout = nil)`,
8+
`wait_until(timeout = nil, &condition)`, `signal`, `broadcast`. This class is
9+
intended for internal use in `concurrent-ruby` only and it does not support
10+
subclassing (since it cannot protect its lock from its children, for more
11+
details see [this article](http://wiki.apidesign.org/wiki/Java_Monitor)). It has
12+
minimal interface to be able to use directly locking available on given
13+
platforms.
14+
15+
For non-internal use there is `Lock` and `Condition` implementation in
16+
`Synchronization` namespace, a condition can be obtained with `new_condition`
17+
method on `Lock`. So far their implementation is naive and requires more work.
18+
API is not expected to change.
19+
20+
## Method names conventions
21+
22+
Methods starting with `ns_` are marking methods that are not using
23+
synchronization by themselves, they have to be used inside synchronize block.
24+
They are usually used in pairs to separate the synchronization from behavior and
25+
to allow to call methods in the same object without double locking.
26+
27+
``` ruby
28+
class Node
29+
# ...
30+
def left
31+
synchronize { ns_left }
32+
end
33+
34+
def right
35+
synchronize { ns_right }
36+
end
37+
38+
def to_a
39+
# avoids double locking
40+
synchronize { [ns_left, ns_right] }
41+
end
42+
43+
private
44+
45+
def ns_left
46+
@left
47+
end
48+
49+
def ns_right
50+
@right
51+
end
52+
# ...
53+
end
54+
```

doc/synchronization.md

Lines changed: 35 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,41 @@
11
> Quotations are used for notes.
22
33
> This document is work-in-progress.
4-
> Intentions of this effort and document are: to sum up the behavior
4+
> Intentions of this effort and document are: to summarize the behavior
55
> of Ruby in concurrent and parallel environment, initiate discussion,
66
> identify problems in the document, find flaws in the Ruby
77
> implementations if any, suggest what has to be enhanced in Ruby itself
88
> and cooperate towards the goal in all implementations (using
99
> `concurrent-ruby` as compatibility layer).
10+
>
11+
> It's not intention of this effort to introduce high-level concurrency
12+
> abstractions like actors to the language, but rather to improve low-level
13+
> concurrency support to add many more concurrency abstractions through gems.
1014
1115
# Synchronization
1216

13-
This layer provides tools to write concurrent abstractions independent on any
14-
particular Ruby implementation. It is build on top of Ruby memory model which is
15-
also described here. `concurrent-ruby` abstractions are build using this layer.
17+
This layer provides tools to write concurrent abstractions independent of any
18+
particular Ruby implementation. It is built on top of the Ruby memory model
19+
which is also described here. `concurrent-ruby` abstractions are build using
20+
this layer.
1621

1722
**Why?** Ruby is great expressive language, but it lacks in support for
18-
concurrent and parallel computation. It's hoped that this document will provide
19-
ground steps for Ruby to become as good in this area as in others.
23+
well-defined low-level concurrent and parallel computation. It's hoped that this
24+
document will provide ground steps for Ruby to become as good in this area as
25+
in others.
2026

21-
Without memory model and this layer it's very hard to write concurrent
27+
Without a memory model and this layer it's very hard to write concurrent
2228
abstractions for Ruby. To write a proper concurrent abstraction it often means
2329
to reimplement it more than once for different Ruby runtimes, which is very
2430
time-consuming and error-prone.
2531

2632
# Ruby memory model
2733

28-
Ruby memory model is a framework allowing to reason about programs in concurrent
29-
and parallel environment. It allows to identify what is and what is not a [race
30-
condition](https://en.wikipedia.org/wiki/Race_condition). Memory model is also a
31-
contract: if a program is written without the race conditions it behaves in
34+
The Ruby memory model is a framework allowing to reason about programs in
35+
concurrent and parallel environment. It allows to identify what is and what
36+
is not a [race condition](https://en.wikipedia.org/wiki/Race_condition).
37+
The memory model is also a contract: if a program is written without race
38+
conditions it behaves in
3239
[sequential consistent](https://en.wikipedia.org/wiki/Sequential_consistency)
3340
manner.
3441

@@ -57,19 +64,20 @@ Key properties are:
5764
- **serialized (S)** - Operations are serialized in some order (they
5865
cannot disappear). This is a new property not mentioned in other memory
5966
models, since Java and C++ do not have dynamically defined fields. All
60-
operations on one line in the table are serialized with each other.
67+
operations on one line in a row of the tables bellow are serialized with
68+
each other.
6169

6270
### Core behavior:
6371

6472
| Operation | V | A | S | Notes |
6573
|:----------|:-:|:-:|:-:|:-----|
66-
| local variable read/write/definition | - | x | x | Local variables are determined during parsing, they are not usually dinamically added (with exception of `local_variable_set`). Therefore definition is quite rare. |
67-
| instance variable read/write/(un)definition | - | x | x ||
74+
| local variable read/write/definition | - | x | x | Local variables are determined during parsing, they are not usually dynamically added (with exception of `local_variable_set`). Therefore definition is quite rare. |
75+
| instance variable read/write/(un)definition | - | x | x | Newly defined instance variables have to become visible eventually. |
6876
| class variable read/write/(un)definition | x | x | x ||
6977
| global variable read/write/definition | x | x | x | un-define us not possible currently. |
7078
| constant variable read/write/(un)definition | x | x | x ||
71-
| `Thread` local variable read/write/definition | - | x | x | un-define us not possible currently. |
72-
| `Fiber` local variable read/write/definition | - | x | x | un-define us not possible currently. |
79+
| `Thread` local variable read/write/definition | - | x | x | un-define is not possible currently. |
80+
| `Fiber` local variable read/write/definition | - | x | x | un-define is not possible currently. |
7381
| method creation/redefinition/removal | x | x | x ||
7482
| include/extend | x | x | x | If `AClass` is included `AModule`, `AClass` gets all `AModule`'s methods at once. |
7583

@@ -87,14 +95,16 @@ Notes:
8795
- Method invocation does not have any special properties that includes
8896
object initialization.
8997

90-
Implementation differences from the model:
98+
Current Implementation differences from the model:
9199

92100
- MRI: everything is volatile.
93101
- JRuby: `Thread` and `Fiber` local variables are volatile. Instance
94102
variables are volatile on x86 and people may un/intentionally depend
95103
on the fact.
96104
- Class variables require investigation.
97105

106+
> TODO: updated with specific versions of the implementations.
107+
98108
### Source loading:
99109

100110
| Operation | V | A | S | Notes |
@@ -106,7 +116,7 @@ Notes:
106116

107117
- Beware of requiring and autoloading in concurrent programs, it's possible to
108118
see partially defined classes. Eager loading or blocking until class is
109-
fully loaded has should be used to mitigate.
119+
fully loaded should be used to mitigate.
110120

111121
### Core classes
112122

@@ -188,7 +198,7 @@ library cannot alter meaning of `@a_name` expression therefore when a
188198
`a_name` to be volatile, it creates method accessors.
189199
190200
> However there is Ruby [issue](https://redmine.ruby-lang.org/issues/11539)
191-
> filled to address this.
201+
> filed to address this.
192202
193203
``` ruby
194204
# Simple counter with cheap reads.
@@ -215,10 +225,10 @@ class Counter < Concurrent::Synchronization::Object
215225
value
216226
end
217227
218-
# Safely increment the value without loosing updates
228+
# Safely increments the value without loosing updates
219229
# (as it would happen with just += used).
220230
def increment(add)
221-
# Wrap he two volatile operations to make them atomic.
231+
# Wrap the two volatile operations to make them atomic.
222232
@Lock.synchronize do
223233
# volatile write and read
224234
self.value = self.value + add
@@ -229,7 +239,7 @@ end
229239
230240
> This is currently planned to be migrated to a module to be able to add
231241
> volatile fields any object not just `Synchronization::Object` children. The
232-
> instance variable itself is named `@"volatile_#(name)"` to distinguish it and
242+
> instance variable itself is named `"@volatile_#{name}"` to distinguish it and
233243
> to prevent direct access by name.
234244
235245
## Volatile instance variable with compare-and-set
@@ -298,59 +308,6 @@ Three of them were used in the example above.
298308
> Current implementation relies on final instance variables where a instance of
299309
> `AtomicReference` is held to provide compare-and-set operations. That creates
300310
> extra indirection which is hoped to be removed over time when better
301-
> implementation will become available in Ruby implementations.
302-
303-
## Concurrent Ruby Notes
304-
305-
### Locks
306-
307-
Concurrent Ruby also has an internal extension of `Object` called
308-
`LockableObject`, which provides same synchronization primitives as Java's
309-
Object: `synchronize(&block)`, `wait(timeout = nil)`,
310-
`wait_until(timeout = nil, &condition)`, `signal`, `broadcast`. This class is
311-
intended for internal use in `concurrent-ruby` only and it does not support
312-
subclassing (since it cannot protect its lock from its children, for more
313-
details see [this article](http://wiki.apidesign.org/wiki/Java_Monitor)). It has
314-
minimal interface to be able to use directly locking available on given
315-
platforms.
316-
317-
For non-internal use there is `Lock` and `Condition` implementation in
318-
`Synchronization` namespace, a condition can be obtained with `new_condition`
319-
method on `Lock`. So far their implementation is naive and requires more work.
320-
API is not expected to change.
321-
322-
### Method names conventions
323-
324-
Methods starting with `ns_` are marking methods that are not using
325-
synchronization by themselves, they have to be used inside synchronize block.
326-
They are usually used in pairs to separate the synchronization from behavior and
327-
to allow to call methods in the same object without double locking.
328-
329-
``` ruby
330-
class Node
331-
# ...
332-
def left
333-
synchronize { ns_left }
334-
end
335-
336-
def left
337-
synchronize { ns_left }
338-
end
339-
340-
def to_a
341-
# avoids double locking
342-
synchronize { [ns_left, ns_right] }
343-
end
344-
345-
private
346-
347-
def ns_left
348-
@left
349-
end
350-
351-
def ns_right
352-
@right
353-
end
354-
# ...
355-
end
356-
```
311+
> implementation will become available in Ruby implementations. The
312+
> instance variable itself is named `"@VolatileCas#{camelized name}"` to
313+
> distinguish it and to prevent direct access by name.

0 commit comments

Comments
 (0)