r32 *atomic.Int32
}
-/*
-planNum 可以为0 表示无法预知的调用次数,如果在done调用前没有Wait、WithWait时,done将返回ErrNothingWait
-
-ctx,done := WithWait(ctx, time.Second)
-
-defer done()// wait done1 or after one second
-
- go func(){// may be run
- done1 := Wait(ctx)
- defer done1()
- do something..
- }()
-*/
+// planNum 可以为0 表示无法预知的调用次数,如果在mainDone调用前没有Wait、WithWait时,mainDone将返回ErrNothingWait
+//
+// mainCtx, mainDone := WithWait(ctx, 0, time.Second)
+// defer mainDone()// wait done1 or after one second
+//
+// go func(){
+// ctx1, done1 := WaitCtx(mainCtx)
+// defer done1()
+// do something..
+// <-ctx1.Done() // wait mainDone call
+// }()
func WithWait(sctx context.Context, planNum int32, to ...time.Duration) (dctx context.Context, done func() error) {
if ctxp, ok := sctx.Value(ptr).(*Ctx); ok {
ctxp.r32.Add(1)
ctx.Ctx = context.WithValue(sctx, ptr, ctx)
ctx.w32.Add(planNum)
- dctx = ctx.Ctx
+ var doneWait context.CancelFunc
+ dctx, doneWait = context.WithCancel(ctx.Ctx)
done = func() error {
+ doneWait()
if ctxp, ok := sctx.Value(ptr).(*Ctx); ok {
defer func() {
ctxp.r32.Add(-1)
return
}
-/*
- func(ctx context.Context){
- done := Wait(ctx)
- defer done()
- do something..
- }
-*/
-func Wait(ctx context.Context) (done func()) {
- if ctxp, ok := ctx.Value(ptr).(*Ctx); ok {
- ctxp.r32.Add(1)
- ctxp.w32.Add(-1)
- }
- return func() {
- if ctxp, ok := ctx.Value(ptr).(*Ctx); ok {
- ctxp.r32.Add(-1)
- }
- }
-}
-
-/*
- func(ctx context.Context){
- ctx, done := WaitCtx(ctx)
- defer done()
-
- do something..
- select {
- case <-ctx:
- defualt:
- }
- do something..
- }
-*/
+// go func(){
+// ctx1, done1 := WaitCtx(mainCtx)
+// defer done1()
+// do something..
+// <-ctx1.Done() // wait mainDone call
+// }()
func WaitCtx(ctx context.Context) (dctx context.Context, done func()) {
if ctxp, ok := ctx.Value(ptr).(*Ctx); ok {
ctxp.r32.Add(1)
}
}
}
-
-func Done(ctx context.Context) bool {
- select {
- case <-ctx.Done():
- return true
- default:
- }
- return false
-}
)
func TestMain(t *testing.T) {
- ctx, _ := context.WithTimeout(context.Background(), time.Second)
- ctx1, done := WithWait(ctx, 1, time.Second)
+ ctx1, done := WithWait(context.Background(), 1, time.Second)
+ t0 := time.Now()
go func() {
- done := Wait(ctx1)
- defer done()
+ ctx2, done1 := WaitCtx(ctx1)
+ defer done1()
+ <-ctx2.Done()
+ if time.Since(t0) < time.Millisecond*100 {
+ t.Fail()
+ }
}()
+ time.Sleep(time.Second)
if done() != nil {
t.Fatal()
}
}
func TestMain1(t *testing.T) {
- ctx, _ := context.WithTimeout(context.Background(), time.Second)
- ctx1, done := WithWait(ctx, 0, time.Second)
- go func() {
- done := Wait(ctx1)
- defer done()
- time.Sleep(100 * time.Millisecond)
- }()
- if e := done(); !errors.Is(e, ErrNothingWait) {
- t.Fatal(e)
- }
-}
-
-func TestMain2(t *testing.T) {
- ctx, _ := context.WithTimeout(context.Background(), time.Second*2)
- ctx1, done := WithWait(ctx, 1, time.Second)
- go func() {
- done := Wait(ctx1)
- time.Sleep(time.Second * 2)
- defer done()
- }()
- if e := done(); !errors.Is(e, ErrWaitTo) {
- t.Fatal(e)
- }
-}
-
-func TestMain3(t *testing.T) {
- ctx, _ := context.WithTimeout(context.Background(), time.Second*2)
- ctx1, done := WithWait(ctx, 1, time.Second)
+ ctx1, done := WithWait(context.Background(), 1, time.Second)
+ t0 := time.Now()
go func() {
- ctx2, done := WithWait(ctx1, 1, time.Second)
- go func() {
- done := Wait(ctx2)
- defer done()
- }()
- if done() != nil {
+ ctx2, _ := WaitCtx(ctx1)
+ <-ctx2.Done()
+ if time.Since(t0) < time.Millisecond*100 {
t.Fail()
}
}()
time.Sleep(time.Second)
- if done() != nil {
+ if !errors.Is(done(), ErrWaitTo) {
t.Fatal()
}
}
-func TestMain4(t *testing.T) {
- ctx, _ := context.WithTimeout(context.Background(), time.Second*2)
- ctx1, done := WithWait(ctx, 1, time.Second)
+func TestMain2(t *testing.T) {
+ ctx1, done := WithWait(context.Background(), 0, time.Second)
+ t0 := time.Now()
go func() {
- ctx2, done := WithWait(ctx1, 1, time.Second)
- go func() {
- done := Wait(ctx2)
- time.Sleep(time.Second * 2)
- defer done()
- }()
- if e := done(); !errors.Is(e, ErrWaitTo) {
+ time.Sleep(time.Second)
+ ctx2, done := WaitCtx(ctx1)
+ defer done()
+ <-ctx2.Done()
+ if time.Since(t0) < time.Millisecond*100 {
t.Fail()
}
}()
- if e := done(); !errors.Is(e, ErrWaitTo) {
- t.Fatal(e)
- }
-}
-
-func TestMain5(t *testing.T) {
- ctx, can := context.WithTimeout(context.Background(), time.Millisecond*500)
- defer can()
-
- ctx, done := WithWait(ctx, 1)
-
- var gr = func(ctx context.Context, to time.Duration) {
- done := Wait(ctx)
- defer done()
- time.Sleep(to)
+ if !errors.Is(done(), ErrNothingWait) {
+ t.Fatal()
}
-
- bg := time.Now()
-
- go gr(ctx, 0)
- // go gr(ctx, time.Second)
- // go gr(ctx, time.Second*5)
-
- t.Log(done(), time.Since(bg))
}