mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
docs: describe upcoming concurrency
This commit is contained in:
parent
0138f46797
commit
bc9f8babaa
106
doc/upcoming.md
Normal file
106
doc/upcoming.md
Normal file
@ -0,0 +1,106 @@
|
||||
# V Work In Progress
|
||||
|
||||
***This document describes features that are not implemented, yet.
|
||||
Please refer to [docs.md](https://github.com/vlang/v/blob/master/doc/docs.md)
|
||||
for the current state of V***
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Concurrency](#concurrency)
|
||||
* [Variable Declarations](#concurrency-variable-declarations)
|
||||
|
||||
## Concurrency
|
||||
|
||||
### Variable Declarations
|
||||
|
||||
Objects that are supposed to be used to exchange data between
|
||||
coroutines have to be declared with special care. Exactly one of the following
|
||||
4 kinds of declaration has to be chosen:
|
||||
|
||||
```v
|
||||
a := ...
|
||||
mut b := ...
|
||||
shared c := ...
|
||||
atomic d := ...
|
||||
```
|
||||
|
||||
- `a` is declared as *constant* that can be passed to
|
||||
other coroutines and read without limitations. However
|
||||
it cannot be changed.
|
||||
- `b` can be accessed reading and writing but only from one
|
||||
coroutine. That coroutine *owns* the object. A `mut` variable can
|
||||
be passed to another coroutine (as receiver or function argument in
|
||||
the `go` statement or via a channel) but then ownership is passed,
|
||||
too, and only the other coroutine can access the object.<sup>1</sup>
|
||||
- `c` can be passed to coroutines an accessed
|
||||
*concurrently*.<sup>2</sup> In order to avoid data races it has to
|
||||
be locked before access can occur and unlocked to allow access to
|
||||
other coroutines. This is done by the following block structure:
|
||||
```v
|
||||
lock c {
|
||||
// read, modify, write c
|
||||
...
|
||||
}
|
||||
```
|
||||
Several variables may be specified: `lock x, y, z { ... }`.
|
||||
They are unlocked in the opposite order.
|
||||
- `d` can be passed to coroutines and accessed *concurrently*,
|
||||
too.<sup>3</sup> No lock is needed in this case, however
|
||||
`atomic` variables can only be 32/64 bit integers (or pointers)
|
||||
and access is limited to a small set of predefined idioms that have
|
||||
native hardware support.
|
||||
|
||||
To help making the correct decision the following table summarizes the
|
||||
different capabilities:
|
||||
|
||||
| | *default* | `mut` | `shared` | `atomic` |
|
||||
| :--- | :---: | :---: | :---: | :---: |
|
||||
| write access | | + | + | + |
|
||||
| concurrent access | + | | + | + |
|
||||
| performance | ++ | ++ | | + |
|
||||
| sophisticated operations | + | + | + | |
|
||||
| structured data types | + | + | + | |
|
||||
|
||||
### Strengths
|
||||
#### default
|
||||
- very fast
|
||||
- unlimited access from different coroutines
|
||||
- easy to handle
|
||||
|
||||
#### `mut`
|
||||
- very fast
|
||||
- easy to handle
|
||||
|
||||
#### `shared`
|
||||
- concurrent access from different coroutines
|
||||
- data type may be complex structure
|
||||
- sophisticated access possible (several statements within one `lock`
|
||||
block)
|
||||
|
||||
#### `atomic`
|
||||
- concurrent access from different coroutines
|
||||
- reasonably fast
|
||||
|
||||
### Weaknesses
|
||||
#### default
|
||||
- read only
|
||||
|
||||
#### `mut`
|
||||
- access only from one coroutine at a time
|
||||
|
||||
#### `shared`
|
||||
- lock/unlock are slow
|
||||
- moderately difficult to handle (needs `lock` block)
|
||||
|
||||
#### `atomic`
|
||||
- limited to single (max. 64 bit) integers (and pointers)
|
||||
- only a small set of predefined operations possible
|
||||
- very difficult to handle correctly
|
||||
|
||||
<sup>1</sup> The owning coroutine will also free the memory space used
|
||||
for the object when it is no longer needed.
|
||||
<sup>2</sup> For `shared` objects the compiler adds code for reference
|
||||
counting. Once the counter reaches 0 the object is automatically freed.
|
||||
<sup>3</sup> Since an `atomic` variable is only a few bytes in size
|
||||
allocation would be an unnecessary overhead. Instead the compiler
|
||||
creates a global.
|
Loading…
Reference in New Issue
Block a user