Skip to content

Commit

Permalink
feat: add MonoChild
Browse files Browse the repository at this point in the history
  • Loading branch information
moul committed Aug 5, 2020
1 parent 0baad1f commit 485219a
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
31 changes: 31 additions & 0 deletions concurrency.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package u

import "context"

// MonoChild is a goroutine manager (parent) that can only have one child at a time.
// When you call MonoChild.SetChild(), MonoChild cancels the previous child context (if any), then run a new child.
// The child needs to auto-kill itself when its context is done.
type MonoChild interface {
SetChild(childFn func(context.Context))
}

func NewMonoChild(ctx context.Context) MonoChild { return &monoChild{ctx: ctx} }

type monoChild struct {
ctx context.Context
lastChildCancelFn func()
}

func (parent *monoChild) SetChild(childFn func(context.Context)) {
if parent.ctx == nil {
panic("requires a parent context")
}
if parent.lastChildCancelFn != nil {
parent.lastChildCancelFn()
}

var childCtx context.Context
childCtx, parent.lastChildCancelFn = context.WithCancel(parent.ctx)

go childFn(childCtx)
}
45 changes: 45 additions & 0 deletions concurrency_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package u_test

import (
"context"
"fmt"
"time"

"moul.io/u"
)

func ExampleMonoChild() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
parent := u.NewMonoChild(ctx)

parent.SetChild(func(ctx context.Context) {
select {
case <-time.After(50 * time.Millisecond):
fmt.Print("A")
case <-ctx.Done():
}
})

time.Sleep(100 * time.Millisecond)

parent.SetChild(func(ctx context.Context) {
select {
case <-time.After(50 * time.Millisecond):
fmt.Print("B")
case <-ctx.Done():
}
})

parent.SetChild(func(ctx context.Context) {
select {
case <-time.After(50 * time.Millisecond):
fmt.Print("C")
case <-ctx.Done():
}
})

time.Sleep(100 * time.Millisecond)

// Output: AC
}

0 comments on commit 485219a

Please sign in to comment.