mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			132 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
	
// 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:
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |