107 lines
3.5 KiB
Markdown
107 lines
3.5 KiB
Markdown
|
# 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.
|