context: make the examples in the vlib/context/README.md immediately runnable

pull/13836/head
Delyan Angelov 2022-03-26 13:25:45 +02:00
parent 7f28d91190
commit 8c396356bb
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
1 changed files with 26 additions and 18 deletions

View File

@ -28,12 +28,13 @@ In this section you can see some usage examples for this module
### Context With Cancellation ### Context With Cancellation
```v ```v
import time
import context import context
// This example demonstrates the use of a cancelable context to prevent a // This example demonstrates the use of a cancelable context to prevent a
// routine leak. By the end of the example function, the routine started // routine leak. By the end of the example function, the routine started
// by gen will return without leaking. // by gen will return without leaking.
fn example_with_cancel() { fn main() {
// gen generates integers in a separate routine and // gen generates integers in a separate routine and
// sends them to the returned channel. // sends them to the returned channel.
// The callers of gen need to cancel the context once // The callers of gen need to cancel the context once
@ -48,6 +49,7 @@ fn example_with_cancel() {
select { select {
_ := <-ch { _ := <-ch {
// returning not to leak the routine // returning not to leak the routine
eprintln('> go thread returns because ctx was canceled/done')
return return
} }
dst <- v { dst <- v {
@ -63,6 +65,7 @@ fn example_with_cancel() {
mut ctx, cancel := context.with_cancel(mut &background) mut ctx, cancel := context.with_cancel(mut &background)
defer { defer {
cancel() cancel()
time.sleep(2 * time.millisecond) // give a small time window, in which the go thread routine has a chance to return
} }
mut mut_ctx := ctx mut mut_ctx := ctx
@ -70,25 +73,24 @@ fn example_with_cancel() {
ch := gen(mut ctx2) ch := gen(mut ctx2)
for i in 0 .. 5 { for i in 0 .. 5 {
v := <-ch v := <-ch
println('> received value: $v')
assert i == v assert i == v
} }
println('> main is finished here')
} }
``` ```
### Context With Deadline ### Context With Deadline
```v ```v
import context
import time import time
import context
const ( const short_duration = 2 * time.millisecond // a reasonable duration to block in an example
// a reasonable duration to block in an example
short_duration = 1 * time.millisecond
)
// This example passes a context with an arbitrary deadline to tell a blocking // This example passes a context with an arbitrary deadline to tell a blocking
// function that it should abandon its work as soon as it gets to it. // function that it should abandon its work as soon as it gets to it.
fn example_with_deadline() { fn main() {
dur := time.now().add(short_duration) dur := time.now().add(short_duration)
mut background := context.background() mut background := context.background()
mut ctx, cancel := context.with_deadline(mut &background, dur) mut ctx, cancel := context.with_deadline(mut &background, dur)
@ -98,47 +100,53 @@ fn example_with_deadline() {
// cancellation function in any case. Failure to do so may keep the // cancellation function in any case. Failure to do so may keep the
// context and its parent alive longer than necessary. // context and its parent alive longer than necessary.
cancel() cancel()
time.sleep(short_duration) // give a small time window, in which the go thread routine has a chance to return
eprintln('> defer block finishes')
} }
ctx_ch := ctx.done() ctx_ch := ctx.done()
select { select {
_ := <-ctx_ch {} _ := <-ctx_ch {
println('>> read from ctx_ch succeeded')
}
1 * time.second { 1 * time.second {
panic('This should not happen') panic('This should not happen')
} }
} }
eprintln('> main finishes')
} }
``` ```
### Context With Timeout ### Context With Timeout
```v ```v
import context
import time import time
import context
const ( const short_duration = 2 * time.millisecond // a reasonable duration to block in an example
// a reasonable duration to block in an example
short_duration = 1 * time.millisecond
)
// This example passes a context with a timeout to tell a blocking function that // This example passes a context with a timeout to tell a blocking function that
// it should abandon its work after the timeout elapses. // it should abandon its work after the timeout elapses.
fn example_with_timeout() { fn main() {
// Pass a context with a timeout to tell a blocking function that it // Pass a context with a timeout to tell a blocking function that it
// should abandon its work after the timeout elapses. // should abandon its work after the timeout elapses.
mut background := context.background() mut background := context.background()
mut ctx, cancel := context.with_timeout(mut &background, short_duration) mut ctx, cancel := context.with_timeout(mut &background, short_duration)
defer { defer {
cancel() cancel()
eprintln('> defer finishes')
} }
ctx_ch := ctx.done() ctx_ch := ctx.done()
select { select {
_ := <-ctx_ch {} _ := <-ctx_ch {
eprintln('> reading from ctx_ch succeeded')
}
1 * time.second { 1 * time.second {
panic('This should not happen') panic('This should not happen')
} }
} }
eprintln('> main finishes')
} }
``` ```
@ -157,7 +165,7 @@ struct Value {
// This example demonstrates how a value can be passed to the context // This example demonstrates how a value can be passed to the context
// and also how to retrieve it if it exists. // and also how to retrieve it if it exists.
fn example_with_value() { fn main() {
f := fn (ctx context.Context, key context.Key) &Value { f := fn (ctx context.Context, key context.Key) &Value {
if value := ctx.value(key) { if value := ctx.value(key) {
match value { match value {
@ -176,7 +184,7 @@ fn example_with_value() {
} }
ctx := context.with_value(context.background(), key, value) ctx := context.with_value(context.background(), key, value)
assert value == f(ctx, key) assert value == dump(f(ctx, key))
assert not_found_value == f(ctx, 'color') assert not_found_value == dump(f(ctx, 'color'))
} }
``` ```