mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
vlib: improvements to the context module (#18318)
This commit is contained in:
parent
0e106c9062
commit
02ea6028af
@ -86,8 +86,8 @@ const (
|
|||||||
'do_not_remove',
|
'do_not_remove',
|
||||||
'cmd/tools/vdoc/html_tag_escape_test.v', /* can't locate local module: markdown */
|
'cmd/tools/vdoc/html_tag_escape_test.v', /* can't locate local module: markdown */
|
||||||
'cmd/tools/vdoc/tests/vdoc_file_test.v', /* fails on Windows; order of output is not as expected */
|
'cmd/tools/vdoc/tests/vdoc_file_test.v', /* fails on Windows; order of output is not as expected */
|
||||||
'vlib/context/onecontext/onecontext_test.v',
|
|
||||||
'vlib/context/deadline_test.v' /* sometimes blocks */,
|
'vlib/context/deadline_test.v' /* sometimes blocks */,
|
||||||
|
'vlib/context/onecontext/onecontext_test.v' /* backtrace_symbols is missing. */,
|
||||||
'vlib/db/mysql/mysql_orm_test.v' /* mysql not installed */,
|
'vlib/db/mysql/mysql_orm_test.v' /* mysql not installed */,
|
||||||
'vlib/db/pg/pg_orm_test.v' /* pg not installed */,
|
'vlib/db/pg/pg_orm_test.v' /* pg not installed */,
|
||||||
]
|
]
|
||||||
@ -246,10 +246,6 @@ const (
|
|||||||
]
|
]
|
||||||
skip_on_windows = [
|
skip_on_windows = [
|
||||||
'do_not_remove',
|
'do_not_remove',
|
||||||
'vlib/context/cancel_test.v',
|
|
||||||
'vlib/context/deadline_test.v',
|
|
||||||
'vlib/context/empty_test.v',
|
|
||||||
'vlib/context/value_test.v',
|
|
||||||
'vlib/orm/orm_test.v',
|
'vlib/orm/orm_test.v',
|
||||||
'vlib/v/tests/orm_sub_struct_test.v',
|
'vlib/v/tests/orm_sub_struct_test.v',
|
||||||
'vlib/v/tests/orm_joined_tables_select_test.v',
|
'vlib/v/tests/orm_joined_tables_select_test.v',
|
||||||
|
@ -62,7 +62,7 @@ fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mut background := context.background()
|
mut background := context.background()
|
||||||
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
|
time.sleep(2 * time.millisecond) // give a small time window, in which the go thread routine has a chance to return
|
||||||
@ -93,7 +93,7 @@ const short_duration = 2 * time.millisecond // a reasonable duration to block in
|
|||||||
fn main() {
|
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)
|
||||||
|
|
||||||
defer {
|
defer {
|
||||||
// Even though ctx will be expired, it is good practice to call its
|
// Even though ctx will be expired, it is good practice to call its
|
||||||
@ -131,7 +131,7 @@ 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')
|
eprintln('> defer finishes')
|
||||||
|
@ -32,7 +32,7 @@ fn test_with_cancel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mut background := context.background()
|
mut background := context.background()
|
||||||
mut ctx, cancel := context.with_cancel(mut &background)
|
mut ctx, cancel := context.with_cancel(mut background)
|
||||||
defer {
|
defer {
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,6 @@ module context
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
const (
|
const (
|
||||||
background = EmptyContext(0)
|
|
||||||
todo = EmptyContext(1)
|
|
||||||
|
|
||||||
cancel_context_key = Key('context.CancelContext')
|
cancel_context_key = Key('context.CancelContext')
|
||||||
|
|
||||||
// canceled is the error returned by Context.err when the context is canceled.
|
// canceled is the error returned by Context.err when the context is canceled.
|
||||||
@ -74,22 +71,6 @@ mut:
|
|||||||
err() IError
|
err() IError
|
||||||
}
|
}
|
||||||
|
|
||||||
// background returns an empty Context. It is never canceled, has no
|
|
||||||
// values, and has no deadline. It is typically used by the main function,
|
|
||||||
// initialization, and tests, and as the top-level Context for incoming
|
|
||||||
// requests.
|
|
||||||
pub fn background() Context {
|
|
||||||
return context.background
|
|
||||||
}
|
|
||||||
|
|
||||||
// todo returns an empty Context. Code should use todo when
|
|
||||||
// it's unclear which Context to use or it is not yet available (because the
|
|
||||||
// surrounding function has not yet been extended to accept a Context
|
|
||||||
// parameter).
|
|
||||||
pub fn todo() Context {
|
|
||||||
return context.todo
|
|
||||||
}
|
|
||||||
|
|
||||||
fn context_name(ctx Context) string {
|
fn context_name(ctx Context) string {
|
||||||
return typeof(ctx)
|
return typeof(ctx)
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ const (
|
|||||||
fn test_with_deadline() {
|
fn test_with_deadline() {
|
||||||
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)
|
||||||
|
|
||||||
defer {
|
defer {
|
||||||
// Even though ctx will be expired, it is good practice to call its
|
// Even though ctx will be expired, it is good practice to call its
|
||||||
@ -35,7 +35,7 @@ fn test_with_timeout() {
|
|||||||
// 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()
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,8 @@ module context
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
// An EmptyContext is never canceled, has no values, and has no deadline. It is not
|
// An EmptyContext is never canceled, has no values.
|
||||||
// struct{}, since vars of this type must have distinct addresses.
|
pub struct EmptyContext {}
|
||||||
pub type EmptyContext = int
|
|
||||||
|
|
||||||
pub fn (ctx &EmptyContext) deadline() ?time.Time {
|
pub fn (ctx &EmptyContext) deadline() ?time.Time {
|
||||||
return none
|
return none
|
||||||
@ -16,9 +15,7 @@ pub fn (ctx &EmptyContext) deadline() ?time.Time {
|
|||||||
|
|
||||||
pub fn (ctx &EmptyContext) done() chan int {
|
pub fn (ctx &EmptyContext) done() chan int {
|
||||||
ch := chan int{}
|
ch := chan int{}
|
||||||
defer {
|
|
||||||
ch.close()
|
ch.close()
|
||||||
}
|
|
||||||
return ch
|
return ch
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,11 +28,42 @@ pub fn (ctx &EmptyContext) value(key Key) ?Any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn (ctx &EmptyContext) str() string {
|
pub fn (ctx &EmptyContext) str() string {
|
||||||
if ctx == background {
|
|
||||||
return 'context.Background'
|
|
||||||
}
|
|
||||||
if ctx == todo {
|
|
||||||
return 'context.TODO'
|
|
||||||
}
|
|
||||||
return 'unknown empty Context'
|
return 'unknown empty Context'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A BackgroundContext is never canceled, has no values.
|
||||||
|
struct BackgroundContext {
|
||||||
|
EmptyContext
|
||||||
|
}
|
||||||
|
|
||||||
|
// str returns a string describing the Context.
|
||||||
|
pub fn (ctx &BackgroundContext) str() string {
|
||||||
|
return 'context.Background'
|
||||||
|
}
|
||||||
|
|
||||||
|
// background returns an empty Context. It is never canceled, has no
|
||||||
|
// values, and has no deadline. It is typically used by the main function,
|
||||||
|
// initialization, and tests, and as the top-level Context for incoming
|
||||||
|
// requests.
|
||||||
|
pub fn background() Context {
|
||||||
|
return &BackgroundContext{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A TodoContext is never canceled, has no values, and has no deadline. It is
|
||||||
|
// never used for real work.
|
||||||
|
struct TodoContext {
|
||||||
|
EmptyContext
|
||||||
|
}
|
||||||
|
|
||||||
|
// str returns a string describing the Context.
|
||||||
|
pub fn (ctx &TodoContext) str() string {
|
||||||
|
return 'context.TODO'
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo returns an empty Context. Code should use todo when
|
||||||
|
// it's unclear which Context to use or it is not yet available (because the
|
||||||
|
// surrounding function has not yet been extended to accept a Context
|
||||||
|
// parameter).
|
||||||
|
pub fn todo() Context {
|
||||||
|
return &TodoContext{}
|
||||||
|
}
|
||||||
|
@ -92,7 +92,7 @@ pub fn (mut octx OneContext) run() {
|
|||||||
|
|
||||||
octx.run_multiple_contexts(mut wrapped_ctx)
|
octx.run_multiple_contexts(mut wrapped_ctx)
|
||||||
for mut ctx in octx.ctxs {
|
for mut ctx in octx.ctxs {
|
||||||
octx.run_multiple_contexts(mut &ctx)
|
octx.run_multiple_contexts(mut ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import time
|
|||||||
|
|
||||||
fn eventually(ch chan int) bool {
|
fn eventually(ch chan int) bool {
|
||||||
mut background := context.background()
|
mut background := context.background()
|
||||||
mut timeout, cancel := context.with_timeout(mut &background, 30 * time.millisecond)
|
mut timeout, cancel := context.with_timeout(mut background, 30 * time.millisecond)
|
||||||
defer {
|
defer {
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
@ -27,32 +27,32 @@ struct Value {
|
|||||||
val string
|
val string
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_merge_nomilan() {
|
fn test_merge_nominal() {
|
||||||
mut background := context.background()
|
mut background := context.background()
|
||||||
foo := &Value{
|
foo := 'foo'
|
||||||
val: 'foo'
|
|
||||||
}
|
|
||||||
mut value_ctx1 := context.with_value(background, 'foo', foo)
|
mut value_ctx1 := context.with_value(background, 'foo', foo)
|
||||||
mut ctx1, cancel := context.with_cancel(mut &value_ctx1)
|
mut ctx1, cancel := context.with_cancel(mut value_ctx1)
|
||||||
defer {
|
defer {
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
bar := &Value{
|
bar := 'bar'
|
||||||
val: 'bar'
|
|
||||||
}
|
|
||||||
mut value_ctx2 := context.with_value(background, 'bar', bar)
|
mut value_ctx2 := context.with_value(background, 'bar', bar)
|
||||||
mut ctx2, _ := context.with_cancel(mut &value_ctx2)
|
mut ctx2, _ := context.with_cancel(mut value_ctx2)
|
||||||
|
|
||||||
mut ctx, cancel2 := merge(ctx1, ctx2)
|
mut ctx, cancel2 := merge(ctx1, ctx2)
|
||||||
|
|
||||||
if deadline := ctx.deadline() {
|
if deadline := ctx.deadline() {
|
||||||
panic('this should never happen')
|
assert false
|
||||||
|
}
|
||||||
|
|
||||||
|
val1 := ctx.value('foo') or {
|
||||||
|
assert false
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val1 := ctx.value('foo') or { panic('wrong value access for key `foo`') }
|
|
||||||
match val1 {
|
match val1 {
|
||||||
Value {
|
string {
|
||||||
assert foo == val1
|
assert foo == val1
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -60,9 +60,12 @@ fn test_merge_nomilan() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val2 := ctx.value('bar') or { panic('wrong value access for key `bar`') }
|
val2 := ctx.value('bar') or {
|
||||||
|
assert false
|
||||||
|
return
|
||||||
|
}
|
||||||
match val2 {
|
match val2 {
|
||||||
Value {
|
string {
|
||||||
assert bar == val2
|
assert bar == val2
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -71,7 +74,7 @@ fn test_merge_nomilan() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _ := ctx.value('baz') {
|
if _ := ctx.value('baz') {
|
||||||
panic('this should never happen')
|
assert false
|
||||||
}
|
}
|
||||||
|
|
||||||
assert !eventually(ctx.done())
|
assert !eventually(ctx.done())
|
||||||
@ -79,12 +82,12 @@ fn test_merge_nomilan() {
|
|||||||
|
|
||||||
cancel2()
|
cancel2()
|
||||||
assert eventually(ctx.done())
|
assert eventually(ctx.done())
|
||||||
assert ctx.err() is Error
|
assert ctx.err().str() == 'canceled context'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_merge_deadline_context_1() {
|
fn test_merge_deadline_context_1() {
|
||||||
mut background := context.background()
|
mut background := context.background()
|
||||||
mut ctx1, cancel := context.with_timeout(mut &background, time.second)
|
mut ctx1, cancel := context.with_timeout(mut background, time.second)
|
||||||
defer {
|
defer {
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
@ -94,14 +97,14 @@ fn test_merge_deadline_context_1() {
|
|||||||
if deadline := ctx.deadline() {
|
if deadline := ctx.deadline() {
|
||||||
assert deadline.unix_time() != 0
|
assert deadline.unix_time() != 0
|
||||||
} else {
|
} else {
|
||||||
panic('this should never happen')
|
assert false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_merge_deadline_context_2() {
|
fn test_merge_deadline_context_2() {
|
||||||
mut background := context.background()
|
mut background := context.background()
|
||||||
ctx1 := context.background()
|
ctx1 := context.background()
|
||||||
mut ctx2, cancel := context.with_timeout(mut &background, time.second)
|
mut ctx2, cancel := context.with_timeout(mut background, time.second)
|
||||||
defer {
|
defer {
|
||||||
cancel()
|
cancel()
|
||||||
}
|
}
|
||||||
@ -110,7 +113,7 @@ fn test_merge_deadline_context_2() {
|
|||||||
if deadline := ctx.deadline() {
|
if deadline := ctx.deadline() {
|
||||||
assert deadline.unix_time() != 0
|
assert deadline.unix_time() != 0
|
||||||
} else {
|
} else {
|
||||||
panic('this should never happen')
|
assert false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +125,7 @@ fn test_merge_deadline_context_n() {
|
|||||||
for i in 0 .. 10 {
|
for i in 0 .. 10 {
|
||||||
ctxs << context.background()
|
ctxs << context.background()
|
||||||
}
|
}
|
||||||
mut ctx_n, _ := context.with_timeout(mut &background, time.second)
|
mut ctx_n, _ := context.with_timeout(mut background, time.second)
|
||||||
ctxs << ctx_n
|
ctxs << ctx_n
|
||||||
|
|
||||||
for i in 0 .. 10 {
|
for i in 0 .. 10 {
|
||||||
@ -135,7 +138,7 @@ fn test_merge_deadline_context_n() {
|
|||||||
assert ctx.err() is none
|
assert ctx.err() is none
|
||||||
cancel()
|
cancel()
|
||||||
assert eventually(ctx.done())
|
assert eventually(ctx.done())
|
||||||
assert ctx.err() is Error
|
assert ctx.err().str() == 'canceled context'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_merge_deadline_none() {
|
fn test_merge_deadline_none() {
|
||||||
@ -145,7 +148,7 @@ fn test_merge_deadline_none() {
|
|||||||
mut ctx, _ := merge(ctx1, ctx2)
|
mut ctx, _ := merge(ctx1, ctx2)
|
||||||
|
|
||||||
if _ := ctx.deadline() {
|
if _ := ctx.deadline() {
|
||||||
panic('this should never happen')
|
assert false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +160,7 @@ fn test_merge_cancel_two() {
|
|||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
assert eventually(ctx.done())
|
assert eventually(ctx.done())
|
||||||
assert ctx.err() is Error
|
assert ctx.err().str() == 'canceled context'
|
||||||
assert ctx.err().str() == 'canceled context'
|
assert ctx.err().str() == 'canceled context'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,6 +173,6 @@ fn test_merge_cancel_multiple() {
|
|||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
assert eventually(ctx.done())
|
assert eventually(ctx.done())
|
||||||
assert ctx.err() is Error
|
assert ctx.err().str() == 'canceled context'
|
||||||
assert ctx.err().str() == 'canceled context'
|
assert ctx.err().str() == 'canceled context'
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user