From bc9f8babaa905dac910090979dd968278a07ff9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kr=C3=BCger?= <45282134+UweKrueger@users.noreply.github.com> Date: Sun, 28 Jun 2020 13:58:08 +0200 Subject: [PATCH] docs: describe upcoming concurrency --- doc/upcoming.md | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 doc/upcoming.md diff --git a/doc/upcoming.md b/doc/upcoming.md new file mode 100644 index 0000000000..38ec2b3823 --- /dev/null +++ b/doc/upcoming.md @@ -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.1 +- `c` can be passed to coroutines an accessed + *concurrently*.2 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.3 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 + +1 The owning coroutine will also free the memory space used +for the object when it is no longer needed. +2 For `shared` objects the compiler adds code for reference +counting. Once the counter reaches 0 the object is automatically freed. +3 Since an `atomic` variable is only a few bytes in size +allocation would be an unnecessary overhead. Instead the compiler +creates a global.