Skip to content

Commit 038c727

Browse files
authored
Documentation edits (#27)
1 parent 0c947a7 commit 038c727

File tree

1 file changed

+47
-29
lines changed

1 file changed

+47
-29
lines changed

README.md

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,22 @@ A transactional locking implementation for C++. Based on basic ideas from
77
<dd>Dave Dice, Ori Shalev, and Nir Shavit</dd>
88
</dl>
99

10-
this simple variation uses a hash table of locks, a splay tree to maintain an
11-
access set, and attempts locks in address order.
10+
this simple variation uses a hash table of locks, a
11+
[splay tree](https://en.wikipedia.org/wiki/Splay_tree) to maintain an access
12+
set, and attempts locks in address order.
13+
14+
In a nutshell one could describe transactional locking as allowing you to write
15+
concurrent and parallel programs roughly as easily as if you only had a single
16+
global [mutex](https://en.cppreference.com/w/cpp/thread/mutex) and a single
17+
global
18+
[condition variable](https://en.cppreference.com/w/cpp/thread/condition_variable)
19+
while providing a performance profile more like that of highly fine-grained
20+
locking.
1221

1322
The goal of this library is to provide an API that makes transactional locking
1423
work like a natural part of C++ and a portable implementation that can be used
15-
today for prototyping parallel algorithms using transactional memory.
24+
_today_ for prototyping parallel algorithms using
25+
[transactional memory](https://en.wikipedia.org/wiki/Software_transactional_memory).
1626

1727
See [`synopsis.hpp`](provides/include/trade_v1/synopsis.hpp) for the API and
1828
[`queue_tm.hpp`](internals/include/testing/queue_tm.hpp) for a transactional
@@ -48,7 +58,7 @@ cppsm test
4858
```
4959

5060
Without the [C++ submodule manager](https://cppsm.github.io/) you need to
51-
non-recursively update the submodules after cloning and use
61+
**non-recursively** update the submodules after cloning and use
5262
[CMake](https://cmake.org/) to e.g. generate makefiles and use
5363
[make](https://www.gnu.org/software/make/) to build and test:
5464

@@ -109,15 +119,17 @@ multiple times.
109119
### <a id="side-effects"></a> [≡](#contents) [Side-effects](#side-effects)
110120
111121
The action given to `atomically` may be invoked many times. Therefore it is
112-
important that the action does not perform any side-effects that must not be
113-
repeated.
122+
important that the action does not perform any
123+
[side-effects](<https://en.wikipedia.org/wiki/Side_effect_(computer_science)>)
124+
that must not be repeated.
114125
115126
On the other hand, the action will only be invoked from the thread that started
116127
the transaction. So, it is entirely possible to use side-effects safely within
117128
the action.
118129
119-
For example, given a queue with transactional `empty` predicate and `pop_front`
120-
operation, one could write
130+
For example, given a
131+
[queue](<https://en.wikipedia.org/wiki/Queue_(abstract_data_type)>) with
132+
transactional `empty` predicate and `pop_front` operation, one could write
121133
122134
```c++
123135
std::vector<Value> values;
@@ -129,9 +141,9 @@ atomically([&]() {
129141
});
130142
```
131143

132-
to transactionally pop the values off of the queue and push them into a vector.
133-
It is important that the `values` vector is cleared at the beginning of the
134-
action.
144+
to transactionally pop the values off of the queue and push them into a
145+
[vector](https://en.cppreference.com/w/cpp/container/vector). It is important
146+
that the `values` vector is cleared at the beginning of the action.
135147

136148
### <a id="nesting"></a> [](#contents) [Nesting](#nesting)
137149

@@ -156,9 +168,9 @@ other transaction may observe a state where the element is not in either queue.
156168
### <a id="blocking"></a> [](#contents) [Blocking](#blocking)
157169

158170
An atomically block can call `retry` at any point to stop running the
159-
transaction and block waiting for other threads to make changes to atoms read
160-
during the transaction. Once such changes have been made, the transaction will
161-
be restarted.
171+
transaction and [block](<https://en.wikipedia.org/wiki/Blocking_(computing)>)
172+
waiting for other threads to make changes to atoms read during the transaction.
173+
Once such changes have been made, the transaction will be restarted.
162174

163175
For example, given a queue with a transactional `try_pop_front` operation
164176
returning an optional value, one could write
@@ -276,15 +288,18 @@ atomically(stack<64>, [&]() { atom = 101; });
276288
and avoid wasting stack.
277289
278290
In case a transaction runs out of log space, the transaction will be aborted by
279-
raising the `std::bad_alloc` exception.
291+
raising the
292+
[`std::bad_alloc`](https://en.cppreference.com/w/cpp/memory/new/bad_alloc)
293+
exception.
280294
281295
Note that only the allocation configuration of the outermost `atomically` call
282-
is considered in nested transactions.
296+
is considered in [nested transactions](#nesting).
283297
284298
### <a id="atomic-types-only"></a> [≡](#contents) [Atomic types only](#atomic-types-only)
285299
286300
The type argument `T` of `atom<T>` must also be allowed as an argument to
287-
`std::atomic`. Unless the type `T` is
301+
[`std::atomic`](https://en.cppreference.com/w/cpp/atomic/atomic). Unless the
302+
type `T` is
288303
[TriviallyCopyable](https://en.cppreference.com/w/cpp/named_req/TriviallyCopyable)
289304
and `std::atomic<T>` is not always lock-free, an atom stores the value in a
290305
`std::atomic<T>`. This allows efficient implementation of the necessary
@@ -293,10 +308,10 @@ stored in an atom.
293308
294309
### <a id="exceptions"></a> [≡](#contents) [Exceptions](#exceptions)
295310
296-
Invalid accesses and `retry` raise exceptions. User code inside transactions
297-
should let such exceptions fall through to the handler in the outermost
298-
`atomically` block. The action given to `atomically` may throw other exceptions
299-
&mdash; such exceptions will be allowed to fall through and abort the
311+
Invalid accesses and [`retry`](#blocking) raise exceptions. User code inside
312+
transactions should let such exceptions fall through to the handler in the
313+
outermost `atomically` block. The action given to `atomically` may throw other
314+
exceptions &mdash; such exceptions will be allowed to fall through and abort the
300315
transaction.
301316
302317
## <a id="trade-offs"></a> [≡](#contents) [Trade-offs](#trade-offs)
@@ -316,22 +331,25 @@ transaction.
316331
317332
- user code cannot observe inconsistent memory states.
318333
319-
- The use of hashed locks may cause false sharing (as multiple atoms may hash to
320-
a single lock) and in the unlikely worst case performance may degrade to the
321-
point where it is equivalent to having a single global lock.
334+
- The use of hashed locks may cause
335+
[false sharing](https://en.wikipedia.org/wiki/False_sharing) (as multiple
336+
atoms may hash to a single lock) and in the unlikely worst case performance
337+
may degrade to the point where it is equivalent to having a single global
338+
lock.
322339
323340
- The hash computation adds some overhead to every access.
324341
325342
- On the other hand, the size of an `atom<T>` is not larger than the size of
326343
`std::atomic<T>`, which is practically optimal.
327344
328-
- Adds a `retry` capability for blocking. This also takes minor advantage of the
329-
use of hashed locks.
345+
- Adds a [`retry`](#blocking) capability for blocking. This also takes minor
346+
advantage of the use of hashed locks.
330347
331-
- Every access of an atom potentially involves loading a thread-local variable.
348+
- Every access of an atom potentially involves loading a
349+
[thread-local variable](https://en.wikipedia.org/wiki/Thread-local_storage).
332350
Ideally a good compiler would be able to eliminate many thread-local accesses,
333-
but that does not seem to happen. This definitely adds a certain amount of
334-
overhead to accesses.
351+
but that does not seem to happen. This adds a certain amount of overhead to
352+
accesses.
335353
336354
- The use of exceptions for aborting transactions may be expensive and may also
337355
prohibit or complicate use in cases like embedded systems where exception

0 commit comments

Comments
 (0)