docs: document `go` with handle and `wait()` (#8142)
parent
1d1fda9522
commit
2f7a66386e
67
doc/docs.md
67
doc/docs.md
|
@ -96,7 +96,9 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h
|
|||
* [Option/Result types & error handling](#optionresult-types-and-error-handling)
|
||||
* [Generics](#generics)
|
||||
* [Concurrency](#concurrency)
|
||||
* [Spawning Concurrent Tasks](#spawning-concurrent-tasks)
|
||||
* [Channels](#channels)
|
||||
* [Shared Objects](#shared-objects)
|
||||
* [Decoding JSON](#decoding-json)
|
||||
* [Testing](#testing)
|
||||
* [Memory management](#memory-management)
|
||||
|
@ -2191,10 +2193,67 @@ println(compare(1.1, 1.2)) // -1
|
|||
|
||||
|
||||
## Concurrency
|
||||
### Spawning Concurrent Tasks
|
||||
V's model of concurrency is very similar to Go's. To run `foo()` concurrently in
|
||||
a different thread, just call it with `go foo()`:
|
||||
|
||||
V's model of concurrency is very similar to Go's. To run `foo()` concurrently, just
|
||||
call it with `go foo()`. Right now, it launches the function on a new system
|
||||
thread. Soon coroutines and a scheduler will be implemented.
|
||||
```v
|
||||
import math
|
||||
|
||||
fn p(a f64, b f64) { // ordinary function without return value
|
||||
c := math.sqrt(a * a + b * b)
|
||||
println(c)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
go p(3, 4)
|
||||
// p will be run in parallel thread
|
||||
}
|
||||
```
|
||||
|
||||
Sometimes it is necessary to wait until a parallel thread has finished. This can
|
||||
be done by assigning a *handle* to the started thread and calling the `wait()` method
|
||||
to this handle later:
|
||||
|
||||
```v
|
||||
import math
|
||||
|
||||
fn p(a f64, b f64) { // ordinary function without return value
|
||||
c := math.sqrt(a * a + b * b)
|
||||
println(c) // prints `5`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
h := go p(3, 4)
|
||||
// p() runs in parallel thread
|
||||
h.wait()
|
||||
// p() has definitely finished
|
||||
}
|
||||
```
|
||||
|
||||
This approach can also be used to get a return value from a function that is run in a
|
||||
parallel thread. There is no need to modify the function itself to be able to call it
|
||||
concurrently.
|
||||
|
||||
```v
|
||||
import math { sqrt }
|
||||
|
||||
fn get_hypot(a f64, b f64) f64 { // ordinary function returning a value
|
||||
c := sqrt(a * a + b * b)
|
||||
return c
|
||||
}
|
||||
|
||||
fn main() {
|
||||
g := go get_hypot(54.06, 2.08) // spawn thread and get handle to it
|
||||
h1 := get_hypot(2.32, 16.74) // do some other calculation here
|
||||
h2 := g.wait() // get result from spawned thread
|
||||
println('Results: $h1, $h2') // prints `Results: 16.9, 54.1`
|
||||
}
|
||||
```
|
||||
|
||||
If there is a large number of tasks that do not return a value it might be easier to manage
|
||||
them using a wait group. However, for this approach the function(s) called concurrently have
|
||||
to be designed with this wait group in mind:
|
||||
|
||||
```v
|
||||
import sync
|
||||
|
@ -2369,6 +2428,8 @@ the reason why not.
|
|||
Usage of these methods and properties in production is not recommended -
|
||||
algorithms based on them are often subject to race conditions. Use `select` instead.
|
||||
|
||||
### Shared Objects
|
||||
|
||||
Data can be exchanged between a coroutine and the calling thread via a shared variable.
|
||||
Such variables should be created as `shared` and passed to the coroutine as such, too.
|
||||
The underlying `struct` contains a hidden *mutex* that allows locking concurrent access
|
||||
|
|
|
@ -404,7 +404,7 @@ pub fn (mut f Fmt) stmt(node ast.Stmt) {
|
|||
f.global_decl(node)
|
||||
}
|
||||
ast.GoStmt {
|
||||
f.go_stmt(node)
|
||||
f.go_stmt(node, false)
|
||||
}
|
||||
ast.GotoLabel {
|
||||
f.writeln('$node.name:')
|
||||
|
@ -893,7 +893,7 @@ pub fn (mut f Fmt) expr(node ast.Expr) {
|
|||
f.write(node.val)
|
||||
}
|
||||
ast.GoExpr {
|
||||
f.stmt(node.go_stmt)
|
||||
f.go_stmt(node.go_stmt, true)
|
||||
}
|
||||
ast.IfExpr {
|
||||
f.if_expr(node)
|
||||
|
@ -2294,10 +2294,12 @@ pub fn (mut f Fmt) for_stmt(node ast.ForStmt) {
|
|||
f.writeln('}')
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) go_stmt(node ast.GoStmt) {
|
||||
pub fn (mut f Fmt) go_stmt(node ast.GoStmt, is_expr bool) {
|
||||
f.write('go ')
|
||||
f.expr(node.call_expr)
|
||||
f.writeln('')
|
||||
if !is_expr {
|
||||
f.writeln('')
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut f Fmt) return_stmt(node ast.Return) {
|
||||
|
|
Loading…
Reference in New Issue