mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
This commit is contained in:
@ -39,9 +39,9 @@ fn example_with_cancel() {
|
||||
// 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.
|
||||
gen := fn (ctx context.Context) chan int {
|
||||
gen := fn (mut ctx context.Context) chan int {
|
||||
dst := chan int{}
|
||||
go fn (ctx context.Context, dst chan int) {
|
||||
go fn (mut ctx context.Context, dst chan int) {
|
||||
mut v := 0
|
||||
ch := ctx.done()
|
||||
for {
|
||||
@ -55,16 +55,20 @@ fn example_with_cancel() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}(ctx, dst)
|
||||
}(mut ctx, dst)
|
||||
return dst
|
||||
}
|
||||
|
||||
ctx, cancel := context.with_cancel(context.background())
|
||||
mut background := context.background()
|
||||
mut b := &background
|
||||
mut ctx, cancel := context.with_cancel(mut b)
|
||||
defer {
|
||||
cancel()
|
||||
}
|
||||
|
||||
ch := gen(ctx)
|
||||
mut mut_ctx := ctx
|
||||
mut ctx2 := &mut_ctx
|
||||
ch := gen(mut ctx2)
|
||||
for i in 0 .. 5 {
|
||||
v := <-ch
|
||||
assert i == v
|
||||
@ -87,7 +91,9 @@ const (
|
||||
// function that it should abandon its work as soon as it gets to it.
|
||||
fn example_with_deadline() {
|
||||
dur := time.now().add(short_duration)
|
||||
ctx, cancel := context.with_deadline(context.background(), dur)
|
||||
mut background := context.background()
|
||||
mut b := &background
|
||||
mut ctx, cancel := context.with_deadline(mut b, dur)
|
||||
|
||||
defer {
|
||||
// Even though ctx will be expired, it is good practice to call its
|
||||
@ -122,7 +128,9 @@ const (
|
||||
fn example_with_timeout() {
|
||||
// Pass a context with a timeout to tell a blocking function that it
|
||||
// should abandon its work after the timeout elapses.
|
||||
ctx, cancel := context.with_timeout(context.background(), short_duration)
|
||||
mut background := context.background()
|
||||
mut b := &background
|
||||
mut ctx, cancel := context.with_timeout(mut b, short_duration)
|
||||
defer {
|
||||
cancel()
|
||||
}
|
||||
|
@ -43,23 +43,6 @@ pub interface Context {
|
||||
// should be canceled. deadline returns none when no deadline is
|
||||
// set. Successive calls to deadline return the same results.
|
||||
deadline() ?time.Time
|
||||
// done returns a channel that's closed when work done on behalf of this
|
||||
// context should be canceled. done may return nil if this context can
|
||||
// never be canceled. Successive calls to done return the same value.
|
||||
// The close of the done channel may happen asynchronously,
|
||||
// after the cancel function returns.
|
||||
//
|
||||
// with_cancel arranges for done to be closed when cancel is called;
|
||||
// with_deadline arranges for done to be closed when the deadline
|
||||
// expires; with_timeout arranges for done to be closed when the timeout
|
||||
// elapses.
|
||||
done() chan int
|
||||
// If done is not yet closed, err returns nil.
|
||||
// If done is closed, err returns a non-nil error explaining why:
|
||||
// canceled if the context was canceled
|
||||
// or deadline_exceeded if the context's deadline passed.
|
||||
// After err returns a non-nil error, successive calls to err return the same error.
|
||||
err() IError
|
||||
// Value returns the value associated with this context for key, or nil
|
||||
// if no value is associated with key. Successive calls to Value with
|
||||
// the same key returns the same result.
|
||||
@ -76,6 +59,24 @@ pub interface Context {
|
||||
// collisions.
|
||||
value(key Key) ?Any
|
||||
str() string
|
||||
// done returns a channel that's closed when work done on behalf of this
|
||||
// context should be canceled. done may return nil if this context can
|
||||
// never be canceled. Successive calls to done return the same value.
|
||||
// The close of the done channel may happen asynchronously,
|
||||
// after the cancel function returns.
|
||||
//
|
||||
// with_cancel arranges for done to be closed when cancel is called;
|
||||
// with_deadline arranges for done to be closed when the deadline
|
||||
// expires; with_timeout arranges for done to be closed when the timeout
|
||||
// elapses.
|
||||
mut:
|
||||
done() chan int
|
||||
// If done is not yet closed, err returns nil.
|
||||
// If done is closed, err returns a non-nil error explaining why:
|
||||
// canceled if the context was canceled
|
||||
// or deadline_exceeded if the context's deadline passed.
|
||||
// After err returns a non-nil error, successive calls to err return the same error.
|
||||
err() IError
|
||||
}
|
||||
|
||||
// background returns an empty Context. It is never canceled, has no
|
||||
|
@ -12,12 +12,13 @@ pub type CancelFn = fn ()
|
||||
|
||||
pub interface Canceler {
|
||||
id string
|
||||
mut:
|
||||
cancel(remove_from_parent bool, err IError)
|
||||
done() chan int
|
||||
}
|
||||
|
||||
[deprecated]
|
||||
pub fn cancel(ctx Context) {
|
||||
pub fn cancel(mut ctx Context) {
|
||||
match mut ctx {
|
||||
CancelContext {
|
||||
ctx.cancel(true, canceled)
|
||||
@ -47,9 +48,9 @@ mut:
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete.
|
||||
pub fn with_cancel(parent Context) (Context, CancelFn) {
|
||||
pub fn with_cancel(mut parent Context) (Context, CancelFn) {
|
||||
mut c := new_cancel_context(parent)
|
||||
propagate_cancel(parent, c)
|
||||
propagate_cancel(mut parent, mut c)
|
||||
return Context(c), fn [mut c] () {
|
||||
c.cancel(true, canceled)
|
||||
}
|
||||
@ -116,18 +117,20 @@ fn (mut ctx CancelContext) cancel(remove_from_parent bool, err IError) {
|
||||
|
||||
for _, child in ctx.children {
|
||||
// NOTE: acquiring the child's lock while holding parent's lock.
|
||||
child.cancel(false, err)
|
||||
mut c := child
|
||||
c.cancel(false, err)
|
||||
}
|
||||
|
||||
ctx.children = map[string]Canceler{}
|
||||
ctx.mutex.unlock()
|
||||
|
||||
if remove_from_parent {
|
||||
remove_child(ctx.context, ctx)
|
||||
mut cc := &ctx.context
|
||||
remove_child(mut cc, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
fn propagate_cancel(parent Context, child Canceler) {
|
||||
fn propagate_cancel(mut parent Context, mut child Canceler) {
|
||||
done := parent.done()
|
||||
select {
|
||||
_ := <-done {
|
||||
@ -136,15 +139,15 @@ fn propagate_cancel(parent Context, child Canceler) {
|
||||
return
|
||||
}
|
||||
}
|
||||
mut p := parent_cancel_context(parent) or {
|
||||
go fn (parent Context, child Canceler) {
|
||||
mut p := parent_cancel_context(mut parent) or {
|
||||
go fn (mut parent Context, mut child Canceler) {
|
||||
pdone := parent.done()
|
||||
select {
|
||||
_ := <-pdone {
|
||||
child.cancel(false, parent.err())
|
||||
}
|
||||
}
|
||||
}(parent, child)
|
||||
}(mut parent, mut child)
|
||||
return
|
||||
}
|
||||
|
||||
@ -162,7 +165,7 @@ fn propagate_cancel(parent Context, child Canceler) {
|
||||
// parent.done() matches that CancelContext. (If not, the CancelContext
|
||||
// has been wrapped in a custom implementation providing a
|
||||
// different done channel, in which case we should not bypass it.)
|
||||
fn parent_cancel_context(parent Context) ?&CancelContext {
|
||||
fn parent_cancel_context(mut parent Context) ?&CancelContext {
|
||||
done := parent.done()
|
||||
if done.closed {
|
||||
return none
|
||||
@ -181,7 +184,7 @@ fn parent_cancel_context(parent Context) ?&CancelContext {
|
||||
}
|
||||
|
||||
// remove_child removes a context from its parent.
|
||||
fn remove_child(parent Context, child Canceler) {
|
||||
mut p := parent_cancel_context(parent) or { return }
|
||||
fn remove_child(mut parent Context, child Canceler) {
|
||||
mut p := parent_cancel_context(mut parent) or { return }
|
||||
p.children.delete(child.id)
|
||||
}
|
||||
|
@ -10,9 +10,9 @@ fn test_with_cancel() {
|
||||
// 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.
|
||||
gen := fn (ctx context.Context) chan int {
|
||||
gen := fn (mut ctx context.Context) chan int {
|
||||
dst := chan int{}
|
||||
go fn (ctx context.Context, dst chan int) {
|
||||
go fn (mut ctx context.Context, dst chan int) {
|
||||
mut v := 0
|
||||
ch := ctx.done()
|
||||
for {
|
||||
@ -26,16 +26,20 @@ fn test_with_cancel() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}(ctx, dst)
|
||||
}(mut ctx, dst)
|
||||
return dst
|
||||
}
|
||||
|
||||
ctx, cancel := context.with_cancel(context.background())
|
||||
mut background := context.background()
|
||||
mut b := &background
|
||||
mut ctx, cancel := context.with_cancel(mut b)
|
||||
defer {
|
||||
cancel()
|
||||
}
|
||||
|
||||
ch := gen(ctx)
|
||||
mut mut_ctx := ctx
|
||||
mut ctx2 := &mut_ctx
|
||||
ch := gen(mut ctx2)
|
||||
for i in 0 .. 5 {
|
||||
v := <-ch
|
||||
assert i == v
|
||||
|
@ -26,12 +26,12 @@ mut:
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete.
|
||||
pub fn with_deadline(parent Context, d time.Time) (Context, CancelFn) {
|
||||
pub fn with_deadline(mut parent Context, d time.Time) (Context, CancelFn) {
|
||||
id := rand.uuid_v4()
|
||||
if cur := parent.deadline() {
|
||||
if cur < d {
|
||||
// The current deadline is already sooner than the new one.
|
||||
return with_cancel(parent)
|
||||
return with_cancel(mut parent)
|
||||
}
|
||||
}
|
||||
cancel_ctx := new_cancel_context(parent)
|
||||
@ -40,7 +40,7 @@ pub fn with_deadline(parent Context, d time.Time) (Context, CancelFn) {
|
||||
deadline: d
|
||||
id: id
|
||||
}
|
||||
propagate_cancel(parent, ctx)
|
||||
propagate_cancel(mut parent, mut ctx)
|
||||
dur := d - time.now()
|
||||
if dur.nanoseconds() <= 0 {
|
||||
ctx.cancel(true, deadline_exceeded) // deadline has already passed
|
||||
@ -64,8 +64,8 @@ pub fn with_deadline(parent Context, d time.Time) (Context, CancelFn) {
|
||||
//
|
||||
// Canceling this context releases resources associated with it, so code should
|
||||
// call cancel as soon as the operations running in this Context complete
|
||||
pub fn with_timeout(parent Context, timeout time.Duration) (Context, CancelFn) {
|
||||
return with_deadline(parent, time.now().add(timeout))
|
||||
pub fn with_timeout(mut parent Context, timeout time.Duration) (Context, CancelFn) {
|
||||
return with_deadline(mut parent, time.now().add(timeout))
|
||||
}
|
||||
|
||||
pub fn (ctx &TimerContext) deadline() ?time.Time {
|
||||
@ -88,7 +88,8 @@ pub fn (mut ctx TimerContext) cancel(remove_from_parent bool, err IError) {
|
||||
ctx.cancel_ctx.cancel(false, err)
|
||||
if remove_from_parent {
|
||||
// Remove this TimerContext from its parent CancelContext's children.
|
||||
remove_child(ctx.cancel_ctx.context, ctx)
|
||||
mut cc := &ctx.cancel_ctx.context
|
||||
remove_child(mut cc, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,9 @@ const (
|
||||
// function that it should abandon its work as soon as it gets to it.
|
||||
fn test_with_deadline() {
|
||||
dur := time.now().add(short_duration)
|
||||
ctx, cancel := context.with_deadline(context.background(), dur)
|
||||
mut background := context.background()
|
||||
mut b := &background
|
||||
mut ctx, cancel := context.with_deadline(mut b, dur)
|
||||
|
||||
defer {
|
||||
// Even though ctx will be expired, it is good practice to call its
|
||||
@ -33,7 +35,9 @@ fn test_with_deadline() {
|
||||
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.
|
||||
ctx, cancel := context.with_timeout(context.background(), short_duration)
|
||||
mut background := context.background()
|
||||
mut b := &background
|
||||
mut ctx, cancel := context.with_timeout(mut b, short_duration)
|
||||
defer {
|
||||
cancel()
|
||||
}
|
||||
|
@ -37,11 +37,11 @@ pub fn (ctx &ValueContext) deadline() ?time.Time {
|
||||
return ctx.context.deadline()
|
||||
}
|
||||
|
||||
pub fn (ctx &ValueContext) done() chan int {
|
||||
pub fn (mut ctx ValueContext) done() chan int {
|
||||
return ctx.context.done()
|
||||
}
|
||||
|
||||
pub fn (ctx &ValueContext) err() IError {
|
||||
pub fn (mut ctx ValueContext) err() IError {
|
||||
return ctx.context.err()
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user