Skip to content

Instantly share code, notes, and snippets.

@ad
Last active July 13, 2018 13:43
Show Gist options
  • Save ad/7d77f15c651f9cdff84b344a129b9968 to your computer and use it in GitHub Desktop.
Save ad/7d77f15c651f9cdff84b344a129b9968 to your computer and use it in GitHub Desktop.
goroutine lifetime (start/stop goroutine)
package main
import (
"fmt"
"runtime"
"sync"
"time"
"github.com/tevino/abool"
)
var (
isStarted = abool.New()
wg sync.WaitGroup
)
func main() {
startChan, outerChan, innerChan, stopChan := manager()
go func() {
time.Sleep(3 * time.Second)
startChan <- true
innerChan <- "first ping"
time.Sleep(3 * time.Second)
startChan <- true
if isStarted.IsSet() {
stopChan <- true
}
time.Sleep(1 * time.Second)
startChan <- true
startChan <- true
time.Sleep(3 * time.Second)
innerChan <- "second ping"
time.Sleep(3 * time.Second)
startChan <- true
if isStarted.IsSet() {
stopChan <- true
}
time.Sleep(1 * time.Second)
startChan <- true
time.Sleep(3 * time.Second)
if isStarted.IsSet() {
stopChan <- true
}
wg.Done()
}()
wg.Add(1)
startChan <- true
outerChan <- "test"
wg.Wait()
}
func manager() (startChan chan bool, outerChan chan string, innerChan chan string, stopChan chan bool) {
startChan = make(chan bool)
outerChan = make(chan string)
innerChan = make(chan string)
stopChan = make(chan bool)
i := 0
go func() {
for {
select {
case <-startChan:
fmt.Println("received command 'start'")
if !isStarted.IsSet() {
isStarted.Set()
i++
go innerFunc(i, innerChan, stopChan)
} else {
fmt.Println("can't start task, task", i, "already running!")
}
case msg := <-outerChan:
fmt.Println(i, ": outerChan <- ", msg)
default:
}
}
}()
return startChan, outerChan, innerChan, stopChan
}
func innerFunc(i int, innerChan chan string, stopChan chan bool) {
wg.Add(1)
fmt.Println("task", i, "started")
defer fmt.Println("task", i, "finished!")
defer isStarted.UnSet()
for {
select {
case msg := <-innerChan:
fmt.Println(i, ": innerChan <- ", msg)
go func() {
for {
runtime.Gosched()
}
}()
case <-stopChan:
fmt.Println("task", i, "received command 'die'")
wg.Done()
fmt.Println("task", i, "done!")
return
default:
time.Sleep(100 * time.Millisecond)
}
}
}
@ad
Copy link
Author

ad commented Jul 13, 2018

received command 'start'
1 : outerChan <-  test
task 1 started
received command 'start'
can't start task, task 1 already running!
1 : innerChan <-  first ping
received command 'start'
can't start task, task 1 already running!
task 1 received command 'die'
task 1 done!
task 1 finished!
received command 'start'
received command 'start'
can't start task, task 2 already running!
task 2 started
2 : innerChan <-  second ping
received command 'start'
can't start task, task 2 already running!
task 2 received command 'die'
task 2 done!
task 2 finished!
received command 'start'
task 3 started
task 3 received command 'die'
task 3 done!
task 3 finished!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment