Skip to content

Instantly share code, notes, and snippets.

@Code-Hex
Last active April 15, 2018 04:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Code-Hex/6c8b55ed73b62723fcaf87f56dbf29a0 to your computer and use it in GitHub Desktop.
Save Code-Hex/6c8b55ed73b62723fcaf87f56dbf29a0 to your computer and use it in GitHub Desktop.
Goroutine meets a signal @go Conference 2018 Spring
package main
import (
"fmt"
"os"
"os/signal"
"sync"
"syscall"
)
type NotifySignal struct {
signal os.Signal
sigchan chan os.Signal
notify chan struct{}
mu sync.Mutex
}
func (n *NotifySignal) Recv() <-chan struct{} {
return n.notify
}
func (n *NotifySignal) notifySignal() {
for {
select {
case n.signal = <-n.sigchan:
close(n.notify)
n.mu.Lock()
n.notify = make(chan struct{})
n.mu.Unlock()
}
}
}
func main() {
ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
n := &NotifySignal{
sigchan: ch,
notify: make(chan struct{}),
}
go n.notifySignal()
var wg sync.WaitGroup
wg.Add(3)
for i := 0; i < 3; i++ {
go func(i int) {
defer wg.Done()
select {
case <-n.Recv():
fmt.Printf("%d: %s\n", i, n.signal)
}
}(i)
}
wg.Wait()
}
package main
import (
"context"
"fmt"
"os"
"os/signal"
"sync"
"syscall"
"time"
)
type NotifySignal struct {
signal os.Signal
sigchan chan os.Signal
notify chan struct{}
mu sync.Mutex
ctx context.Context
}
func NewNotifySignal(ctx context.Context, ch chan os.Signal) context.Context {
n := &NotifySignal{
sigchan: ch,
notify: make(chan struct{}),
ctx: ctx,
}
go n.notifySignal()
return n
}
func (n *NotifySignal) Signal() os.Signal {
return n.signal
}
// Deadline is implemented for context.Context
func (n *NotifySignal) Deadline() (deadline time.Time, ok bool) {
return n.ctx.Deadline()
}
// Done is implemented for context.Context
func (n *NotifySignal) Done() <-chan struct{} {
return n.ctx.Done()
}
// Err is implemented for context.Context
func (n *NotifySignal) Err() error {
return n.ctx.Err()
}
// Value is implemented for context.Context
func (n *NotifySignal) Value(key interface{}) interface{} {
return n.ctx.Value(key)
}
func (n *NotifySignal) Recv() <-chan struct{} {
return n.notify
}
func (n *NotifySignal) notifySignal() {
for {
select {
case n.signal = <-n.sigchan:
close(n.notify)
n.mu.Lock()
n.notify = make(chan struct{})
n.mu.Unlock()
}
}
}
func main() {
d := time.Now().Add(3 * time.Second)
ctx, cancel := context.WithDeadline(context.Background(), d)
defer cancel()
ch := make(chan os.Signal)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
n := NewNotifySignal(ctx, ch)
var wg sync.WaitGroup
wg.Add(3)
for i := 0; i < 3; i++ {
go func(ctx context.Context, i int) {
c := ctx.(*NotifySignal)
defer wg.Done()
select {
case <-c.Recv():
fmt.Printf("%d: %s\n", i, c.signal)
case <-c.Done():
fmt.Printf("%d: context canceled\n", i)
}
}(n, i)
}
wg.Wait()
}
@Code-Hex
Copy link
Author

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