diff options
author | Russ Cox <rsc@golang.org> | 2014-09-08 00:08:51 -0400 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2014-09-08 00:08:51 -0400 |
commit | 8528da672cc093d4dd06732819abc1f7b6b5a46e (patch) | |
tree | 334be80d4a4c85b77db6f6fdb67cbf0528cba5f5 /src/os/signal/signal.go | |
parent | 73bcb69f272cbf34ddcc9daa56427a8683b5a95d (diff) | |
download | go-8528da672cc093d4dd06732819abc1f7b6b5a46e.tar.gz |
build: move package sources from src/pkg to src
Preparation was in CL 134570043.
This CL contains only the effect of 'hg mv src/pkg/* src'.
For more about the move, see golang.org/s/go14nopkg.
Diffstat (limited to 'src/os/signal/signal.go')
-rw-r--r-- | src/os/signal/signal.go | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/src/os/signal/signal.go b/src/os/signal/signal.go new file mode 100644 index 000000000..300427549 --- /dev/null +++ b/src/os/signal/signal.go @@ -0,0 +1,131 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package signal implements access to incoming signals. +package signal + +// BUG(rsc): This package is not yet implemented on Plan 9. + +import ( + "os" + "sync" +) + +var handlers struct { + sync.Mutex + m map[chan<- os.Signal]*handler + ref [numSig]int64 +} + +type handler struct { + mask [(numSig + 31) / 32]uint32 +} + +func (h *handler) want(sig int) bool { + return (h.mask[sig/32]>>uint(sig&31))&1 != 0 +} + +func (h *handler) set(sig int) { + h.mask[sig/32] |= 1 << uint(sig&31) +} + +// Notify causes package signal to relay incoming signals to c. +// If no signals are listed, all incoming signals will be relayed to c. +// Otherwise, just the listed signals will. +// +// Package signal will not block sending to c: the caller must ensure +// that c has sufficient buffer space to keep up with the expected +// signal rate. For a channel used for notification of just one signal value, +// a buffer of size 1 is sufficient. +// +// It is allowed to call Notify multiple times with the same channel: +// each call expands the set of signals sent to that channel. +// The only way to remove signals from the set is to call Stop. +// +// It is allowed to call Notify multiple times with different channels +// and the same signals: each channel receives copies of incoming +// signals independently. +func Notify(c chan<- os.Signal, sig ...os.Signal) { + if c == nil { + panic("os/signal: Notify using nil channel") + } + + handlers.Lock() + defer handlers.Unlock() + + h := handlers.m[c] + if h == nil { + if handlers.m == nil { + handlers.m = make(map[chan<- os.Signal]*handler) + } + h = new(handler) + handlers.m[c] = h + } + + add := func(n int) { + if n < 0 { + return + } + if !h.want(n) { + h.set(n) + if handlers.ref[n] == 0 { + enableSignal(n) + } + handlers.ref[n]++ + } + } + + if len(sig) == 0 { + for n := 0; n < numSig; n++ { + add(n) + } + } else { + for _, s := range sig { + add(signum(s)) + } + } +} + +// Stop causes package signal to stop relaying incoming signals to c. +// It undoes the effect of all prior calls to Notify using c. +// When Stop returns, it is guaranteed that c will receive no more signals. +func Stop(c chan<- os.Signal) { + handlers.Lock() + defer handlers.Unlock() + + h := handlers.m[c] + if h == nil { + return + } + delete(handlers.m, c) + + for n := 0; n < numSig; n++ { + if h.want(n) { + handlers.ref[n]-- + if handlers.ref[n] == 0 { + disableSignal(n) + } + } + } +} + +func process(sig os.Signal) { + n := signum(sig) + if n < 0 { + return + } + + handlers.Lock() + defer handlers.Unlock() + + for c, h := range handlers.m { + if h.want(n) { + // send but do not block for it + select { + case c <- sig: + default: + } + } + } +} |