2022-04-30 12:27:50 +02:00
|
|
|
// vtest flaky: true
|
2021-09-23 13:55:04 +02:00
|
|
|
// vtest retry: 3
|
2021-04-12 18:32:51 +02:00
|
|
|
import context
|
|
|
|
|
|
|
|
// This example demonstrates the use of a cancelable context to prevent a
|
|
|
|
// routine leak. By the end of the example function, the routine started
|
|
|
|
// by gen will return without leaking.
|
|
|
|
fn test_with_cancel() {
|
|
|
|
// gen generates integers in a separate routine and
|
|
|
|
// sends them to the returned channel.
|
|
|
|
// The callers of gen need to cancel the context once
|
|
|
|
// they are done consuming generated integers not to leak
|
|
|
|
// the internal routine started by gen.
|
2021-10-11 14:41:31 +02:00
|
|
|
gen := fn (mut ctx context.Context) chan int {
|
2021-04-12 18:32:51 +02:00
|
|
|
dst := chan int{}
|
2021-10-11 14:41:31 +02:00
|
|
|
go fn (mut ctx context.Context, dst chan int) {
|
2021-04-13 06:04:13 +02:00
|
|
|
mut v := 0
|
2021-04-12 18:32:51 +02:00
|
|
|
ch := ctx.done()
|
2021-04-13 06:04:13 +02:00
|
|
|
for {
|
2021-04-12 18:32:51 +02:00
|
|
|
select {
|
|
|
|
_ := <-ch {
|
|
|
|
// returning not to leak the routine
|
2021-04-13 06:04:13 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
dst <- v {
|
|
|
|
v++
|
2021-04-12 18:32:51 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-10-11 14:41:31 +02:00
|
|
|
}(mut ctx, dst)
|
2021-04-12 18:32:51 +02:00
|
|
|
return dst
|
|
|
|
}
|
|
|
|
|
2021-10-11 14:41:31 +02:00
|
|
|
mut background := context.background()
|
2021-10-14 12:32:42 +02:00
|
|
|
mut ctx, cancel := context.with_cancel(mut &background)
|
2021-04-12 18:32:51 +02:00
|
|
|
defer {
|
2021-09-27 16:52:20 +02:00
|
|
|
cancel()
|
2021-04-12 18:32:51 +02:00
|
|
|
}
|
|
|
|
|
2021-10-11 14:41:31 +02:00
|
|
|
mut mut_ctx := ctx
|
|
|
|
mut ctx2 := &mut_ctx
|
|
|
|
ch := gen(mut ctx2)
|
2021-04-12 18:32:51 +02:00
|
|
|
for i in 0 .. 5 {
|
|
|
|
v := <-ch
|
|
|
|
assert i == v
|
|
|
|
}
|
|
|
|
}
|