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',
|
||||
'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 */
|
||||
'vlib/context/onecontext/onecontext_test.v',
|
||||
'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/pg/pg_orm_test.v' /* pg not installed */,
|
||||
]
|
||||
@ -246,10 +246,6 @@ const (
|
||||
]
|
||||
skip_on_windows = [
|
||||
'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/v/tests/orm_sub_struct_test.v',
|
||||
'vlib/v/tests/orm_joined_tables_select_test.v',
|
||||
|
@ -62,7 +62,7 @@ fn main() {
|
||||
}
|
||||
|
||||
mut background := context.background()
|
||||
mut ctx, cancel := context.with_cancel(mut &background)
|
||||
mut ctx, cancel := context.with_cancel(mut background)
|
||||
defer {
|
||||
cancel()
|
||||
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() {
|
||||
dur := time.now().add(short_duration)
|
||||
mut background := context.background()
|
||||
mut ctx, cancel := context.with_deadline(mut &background, dur)
|
||||
mut ctx, cancel := context.with_deadline(mut background, dur)
|
||||
|
||||
defer {
|
||||
// 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
|
||||
// should abandon its work after the timeout elapses.
|
||||
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 {
|
||||
cancel()
|
||||
eprintln('> defer finishes')
|
||||
|
@ -32,7 +32,7 @@ fn test_with_cancel() {
|
||||
}
|
||||
|
||||
mut background := context.background()
|
||||
mut ctx, cancel := context.with_cancel(mut &background)
|
||||
mut ctx, cancel := context.with_cancel(mut background)
|
||||
defer {
|
||||
cancel()
|
||||
}
|
||||
|
@ -7,9 +7,6 @@ module context
|
||||
import time
|
||||
|
||||
const (
|
||||
background = EmptyContext(0)
|
||||
todo = EmptyContext(1)
|
||||
|
||||
cancel_context_key = Key('context.CancelContext')
|
||||
|
||||
// canceled is the error returned by Context.err when the context is canceled.
|
||||
@ -74,22 +71,6 @@ mut:
|
||||
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 {
|
||||
return typeof(ctx)
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ const (
|
||||
fn test_with_deadline() {
|
||||
dur := time.now().add(short_duration)
|
||||
mut background := context.background()
|
||||
mut ctx, cancel := context.with_deadline(mut &background, dur)
|
||||
mut ctx, cancel := context.with_deadline(mut background, dur)
|
||||
|
||||
defer {
|
||||
// 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
|
||||
// should abandon its work after the timeout elapses.
|
||||
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 {
|
||||
cancel()
|
||||
}
|
||||
|
@ -6,9 +6,8 @@ module context
|
||||
|
||||
import time
|
||||
|
||||
// An EmptyContext is never canceled, has no values, and has no deadline. It is not
|
||||
// struct{}, since vars of this type must have distinct addresses.
|
||||
pub type EmptyContext = int
|
||||
// An EmptyContext is never canceled, has no values.
|
||||
pub struct EmptyContext {}
|
||||
|
||||
pub fn (ctx &EmptyContext) deadline() ?time.Time {
|
||||
return none
|
||||
@ -16,9 +15,7 @@ pub fn (ctx &EmptyContext) deadline() ?time.Time {
|
||||
|
||||
pub fn (ctx &EmptyContext) done() chan int {
|
||||
ch := chan int{}
|
||||
defer {
|
||||
ch.close()
|
||||
}
|
||||
ch.close()
|
||||
return ch
|
||||
}
|
||||
|
||||
@ -31,11 +28,42 @@ pub fn (ctx &EmptyContext) value(key Key) ?Any {
|
||||
}
|
||||
|
||||
pub fn (ctx &EmptyContext) str() string {
|
||||
if ctx == background {
|
||||
return 'context.Background'
|
||||
}
|
||||
if ctx == todo {
|
||||
return 'context.TODO'
|
||||
}
|
||||
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)
|
||||
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 {
|
||||
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 {
|
||||
cancel()
|
||||
}
|
||||
@ -27,32 +27,32 @@ struct Value {
|
||||
val string
|
||||
}
|
||||
|
||||
fn test_merge_nomilan() {
|
||||
fn test_merge_nominal() {
|
||||
mut background := context.background()
|
||||
foo := &Value{
|
||||
val: 'foo'
|
||||
}
|
||||
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 {
|
||||
cancel()
|
||||
}
|
||||
|
||||
bar := &Value{
|
||||
val: 'bar'
|
||||
}
|
||||
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)
|
||||
|
||||
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 {
|
||||
Value {
|
||||
string {
|
||||
assert foo == val1
|
||||
}
|
||||
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 {
|
||||
Value {
|
||||
string {
|
||||
assert bar == val2
|
||||
}
|
||||
else {
|
||||
@ -71,7 +74,7 @@ fn test_merge_nomilan() {
|
||||
}
|
||||
|
||||
if _ := ctx.value('baz') {
|
||||
panic('this should never happen')
|
||||
assert false
|
||||
}
|
||||
|
||||
assert !eventually(ctx.done())
|
||||
@ -79,12 +82,12 @@ fn test_merge_nomilan() {
|
||||
|
||||
cancel2()
|
||||
assert eventually(ctx.done())
|
||||
assert ctx.err() is Error
|
||||
assert ctx.err().str() == 'canceled context'
|
||||
}
|
||||
|
||||
fn test_merge_deadline_context_1() {
|
||||
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 {
|
||||
cancel()
|
||||
}
|
||||
@ -94,14 +97,14 @@ fn test_merge_deadline_context_1() {
|
||||
if deadline := ctx.deadline() {
|
||||
assert deadline.unix_time() != 0
|
||||
} else {
|
||||
panic('this should never happen')
|
||||
assert false
|
||||
}
|
||||
}
|
||||
|
||||
fn test_merge_deadline_context_2() {
|
||||
mut background := 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 {
|
||||
cancel()
|
||||
}
|
||||
@ -110,7 +113,7 @@ fn test_merge_deadline_context_2() {
|
||||
if deadline := ctx.deadline() {
|
||||
assert deadline.unix_time() != 0
|
||||
} else {
|
||||
panic('this should never happen')
|
||||
assert false
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,7 +125,7 @@ fn test_merge_deadline_context_n() {
|
||||
for i in 0 .. 10 {
|
||||
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
|
||||
|
||||
for i in 0 .. 10 {
|
||||
@ -135,7 +138,7 @@ fn test_merge_deadline_context_n() {
|
||||
assert ctx.err() is none
|
||||
cancel()
|
||||
assert eventually(ctx.done())
|
||||
assert ctx.err() is Error
|
||||
assert ctx.err().str() == 'canceled context'
|
||||
}
|
||||
|
||||
fn test_merge_deadline_none() {
|
||||
@ -145,7 +148,7 @@ fn test_merge_deadline_none() {
|
||||
mut ctx, _ := merge(ctx1, ctx2)
|
||||
|
||||
if _ := ctx.deadline() {
|
||||
panic('this should never happen')
|
||||
assert false
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,7 +160,7 @@ fn test_merge_cancel_two() {
|
||||
cancel()
|
||||
|
||||
assert eventually(ctx.done())
|
||||
assert ctx.err() is Error
|
||||
assert ctx.err().str() == 'canceled context'
|
||||
assert ctx.err().str() == 'canceled context'
|
||||
}
|
||||
|
||||
@ -170,6 +173,6 @@ fn test_merge_cancel_multiple() {
|
||||
cancel()
|
||||
|
||||
assert eventually(ctx.done())
|
||||
assert ctx.err() is Error
|
||||
assert ctx.err().str() == 'canceled context'
|
||||
assert ctx.err().str() == 'canceled context'
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user