Use chan struct{} for semaphores

With semaphores we don't actually care about the value passed in. It
makes sense to use a 0 bytes type in these cases.
There is also the added benefit of compiler optimisations for this
specific use case as described here:
https://docs.google.com/document/d/1yIAYmbvL3JxOKOjuCyon7JhW4cSv1wy5hC0ApeGMV9s/pub
This commit is contained in:
Tomás Senart 2014-07-02 17:31:10 +02:00 committed by Dave Collins
parent cc2c486791
commit f439dece37
8 changed files with 47 additions and 47 deletions

View file

@ -338,7 +338,7 @@ type AddrManager struct {
started int32 started int32
shutdown int32 shutdown int32
wg sync.WaitGroup wg sync.WaitGroup
quit chan bool quit chan struct{}
nTried int nTried int
nNew int nNew int
lamtx sync.Mutex lamtx sync.Mutex
@ -759,7 +759,7 @@ func (a *AddrManager) reset() {
func NewAddrManager() *AddrManager { func NewAddrManager() *AddrManager {
am := AddrManager{ am := AddrManager{
rand: rand.New(rand.NewSource(time.Now().UnixNano())), rand: rand.New(rand.NewSource(time.Now().UnixNano())),
quit: make(chan bool), quit: make(chan struct{}),
localAddresses: make(map[string]*localAddress), localAddresses: make(map[string]*localAddress),
} }
am.reset() am.reset()

View file

@ -174,7 +174,7 @@ type blockManager struct {
msgChan chan interface{} msgChan chan interface{}
chainState chainState chainState chainState
wg sync.WaitGroup wg sync.WaitGroup
quit chan bool quit chan struct{}
// The following fields are used for headers-first mode. // The following fields are used for headers-first mode.
headersFirstMode bool headersFirstMode bool
@ -1309,7 +1309,7 @@ func newBlockManager(s *server) (*blockManager, error) {
lastBlockLogTime: time.Now(), lastBlockLogTime: time.Now(),
msgChan: make(chan interface{}, cfg.MaxPeers*3), msgChan: make(chan interface{}, cfg.MaxPeers*3),
headerList: list.New(), headerList: list.New(),
quit: make(chan bool), quit: make(chan struct{}),
} }
bm.blockChain = btcchain.New(s.db, s.netParams, bm.handleNotifyMsg) bm.blockChain = btcchain.New(s.db, s.netParams, bm.handleNotifyMsg)
bm.blockChain.DisableCheckpoints(cfg.DisableCheckpoints) bm.blockChain.DisableCheckpoints(cfg.DisableCheckpoints)

View file

@ -18,7 +18,7 @@ import (
var ( var (
cfg *config cfg *config
shutdownChannel = make(chan bool) shutdownChannel = make(chan struct{})
) )
// winServiceMain is only invoked on Windows. It detects when btcd is running // winServiceMain is only invoked on Windows. It detects when btcd is running
@ -114,7 +114,7 @@ func btcdMain(serverChan chan<- *server) error {
go func() { go func() {
server.WaitForShutdown() server.WaitForShutdown()
srvrLog.Infof("Server shutdown complete") srvrLog.Infof("Server shutdown complete")
shutdownChannel <- true shutdownChannel <- struct{}{}
}() }()
// Wait for shutdown signal from either a graceful server stop or from // Wait for shutdown signal from either a graceful server stop or from

12
peer.go
View file

@ -160,12 +160,12 @@ type peer struct {
continueHash *btcwire.ShaHash continueHash *btcwire.ShaHash
outputQueue chan outMsg outputQueue chan outMsg
sendQueue chan outMsg sendQueue chan outMsg
sendDoneQueue chan bool sendDoneQueue chan struct{}
queueWg sync.WaitGroup // TODO(oga) wg -> single use channel? queueWg sync.WaitGroup // TODO(oga) wg -> single use channel?
outputInvChan chan *btcwire.InvVect outputInvChan chan *btcwire.InvVect
txProcessed chan bool txProcessed chan bool
blockProcessed chan bool blockProcessed chan bool
quit chan bool quit chan struct{}
StatsMtx sync.Mutex // protects all statistics below here. StatsMtx sync.Mutex // protects all statistics below here.
versionKnown bool versionKnown bool
protocolVersion uint32 protocolVersion uint32
@ -1478,7 +1478,7 @@ out:
msg.doneChan <- true msg.doneChan <- true
} }
peerLog.Tracef("%s: acking queuehandler", p) peerLog.Tracef("%s: acking queuehandler", p)
p.sendDoneQueue <- true p.sendDoneQueue <- struct{}{}
peerLog.Tracef("%s: acked queuehandler", p) peerLog.Tracef("%s: acked queuehandler", p)
case <-p.quit: case <-p.quit:
@ -1622,12 +1622,12 @@ func newPeerBase(s *server, inbound bool) *peer {
requestedBlocks: make(map[btcwire.ShaHash]struct{}), requestedBlocks: make(map[btcwire.ShaHash]struct{}),
requestQueue: list.New(), requestQueue: list.New(),
outputQueue: make(chan outMsg, outputBufferSize), outputQueue: make(chan outMsg, outputBufferSize),
sendQueue: make(chan outMsg, 1), // nonblocking sync sendQueue: make(chan outMsg, 1), // nonblocking sync
sendDoneQueue: make(chan bool, 1), // nonblocking sync sendDoneQueue: make(chan struct{}, 1), // nonblocking sync
outputInvChan: make(chan *btcwire.InvVect, outputBufferSize), outputInvChan: make(chan *btcwire.InvVect, outputBufferSize),
txProcessed: make(chan bool, 1), txProcessed: make(chan bool, 1),
blockProcessed: make(chan bool, 1), blockProcessed: make(chan bool, 1),
quit: make(chan bool), quit: make(chan struct{}),
} }
return &p return &p
} }

View file

@ -259,7 +259,7 @@ type notificationUnregisterAddr struct {
// handler and processes one at a time. // handler and processes one at a time.
func (m *wsNotificationManager) notificationHandler() { func (m *wsNotificationManager) notificationHandler() {
// clients is a map of all currently connected websocket clients. // clients is a map of all currently connected websocket clients.
clients := make(map[chan bool]*wsClient) clients := make(map[chan struct{}]*wsClient)
// Maps used to hold lists of websocket clients to be notified on // Maps used to hold lists of websocket clients to be notified on
// certain events. Each websocket client also keeps maps for the events // certain events. Each websocket client also keeps maps for the events
@ -268,10 +268,10 @@ func (m *wsNotificationManager) notificationHandler() {
// //
// Where possible, the quit channel is used as the unique id for a client // Where possible, the quit channel is used as the unique id for a client
// since it is quite a bit more efficient than using the entire struct. // since it is quite a bit more efficient than using the entire struct.
blockNotifications := make(map[chan bool]*wsClient) blockNotifications := make(map[chan struct{}]*wsClient)
txNotifications := make(map[chan bool]*wsClient) txNotifications := make(map[chan struct{}]*wsClient)
watchedOutPoints := make(map[btcwire.OutPoint]map[chan bool]*wsClient) watchedOutPoints := make(map[btcwire.OutPoint]map[chan struct{}]*wsClient)
watchedAddrs := make(map[string]map[chan bool]*wsClient) watchedAddrs := make(map[string]map[chan struct{}]*wsClient)
out: out:
for { for {
@ -398,7 +398,7 @@ func (m *wsNotificationManager) UnregisterBlockUpdates(wsc *wsClient) {
// notifyBlockConnected notifies websocket clients that have registered for // notifyBlockConnected notifies websocket clients that have registered for
// block updates when a block is connected to the main chain. // block updates when a block is connected to the main chain.
func (*wsNotificationManager) notifyBlockConnected(clients map[chan bool]*wsClient, func (*wsNotificationManager) notifyBlockConnected(clients map[chan struct{}]*wsClient,
block *btcutil.Block) { block *btcutil.Block) {
hash, err := block.Sha() hash, err := block.Sha()
@ -423,7 +423,7 @@ func (*wsNotificationManager) notifyBlockConnected(clients map[chan bool]*wsClie
// notifyBlockDisconnected notifies websocket clients that have registered for // notifyBlockDisconnected notifies websocket clients that have registered for
// block updates when a block is disconnected from the main chain (due to a // block updates when a block is disconnected from the main chain (due to a
// reorganize). // reorganize).
func (*wsNotificationManager) notifyBlockDisconnected(clients map[chan bool]*wsClient, block *btcutil.Block) { func (*wsNotificationManager) notifyBlockDisconnected(clients map[chan struct{}]*wsClient, block *btcutil.Block) {
// Skip notification creation if no clients have requested block // Skip notification creation if no clients have requested block
// connected/disconnected notifications. // connected/disconnected notifications.
if len(clients) == 0 { if len(clients) == 0 {
@ -465,7 +465,7 @@ func (m *wsNotificationManager) UnregisterNewMempoolTxsUpdates(wsc *wsClient) {
// notifyForNewTx notifies websocket clients that have registerd for updates // notifyForNewTx notifies websocket clients that have registerd for updates
// when a new transaction is added to the memory pool. // when a new transaction is added to the memory pool.
func (m *wsNotificationManager) notifyForNewTx(clients map[chan bool]*wsClient, tx *btcutil.Tx) { func (m *wsNotificationManager) notifyForNewTx(clients map[chan struct{}]*wsClient, tx *btcutil.Tx) {
txShaStr := tx.Sha().String() txShaStr := tx.Sha().String()
mtx := tx.MsgTx() mtx := tx.MsgTx()
@ -521,7 +521,7 @@ func (m *wsNotificationManager) RegisterSpentRequest(wsc *wsClient, op *btcwire.
// addSpentRequest modifies a map of watched outpoints to sets of websocket // addSpentRequest modifies a map of watched outpoints to sets of websocket
// clients to add a new request watch the outpoint op and create and send // clients to add a new request watch the outpoint op and create and send
// a notification when spent to the websocket client wsc. // a notification when spent to the websocket client wsc.
func (*wsNotificationManager) addSpentRequest(ops map[btcwire.OutPoint]map[chan bool]*wsClient, func (*wsNotificationManager) addSpentRequest(ops map[btcwire.OutPoint]map[chan struct{}]*wsClient,
wsc *wsClient, op *btcwire.OutPoint) { wsc *wsClient, op *btcwire.OutPoint) {
// Track the request in the client as well so it can be quickly be // Track the request in the client as well so it can be quickly be
@ -532,7 +532,7 @@ func (*wsNotificationManager) addSpentRequest(ops map[btcwire.OutPoint]map[chan
// Create the list as needed. // Create the list as needed.
cmap, ok := ops[*op] cmap, ok := ops[*op]
if !ok { if !ok {
cmap = make(map[chan bool]*wsClient) cmap = make(map[chan struct{}]*wsClient)
ops[*op] = cmap ops[*op] = cmap
} }
cmap[wsc.quit] = wsc cmap[wsc.quit] = wsc
@ -552,7 +552,7 @@ func (m *wsNotificationManager) UnregisterSpentRequest(wsc *wsClient, op *btcwir
// websocket client wsc from the set of clients to be notified when a // websocket client wsc from the set of clients to be notified when a
// watched outpoint is spent. If wsc is the last client, the outpoint // watched outpoint is spent. If wsc is the last client, the outpoint
// key is removed from the map. // key is removed from the map.
func (*wsNotificationManager) removeSpentRequest(ops map[btcwire.OutPoint]map[chan bool]*wsClient, func (*wsNotificationManager) removeSpentRequest(ops map[btcwire.OutPoint]map[chan struct{}]*wsClient,
wsc *wsClient, op *btcwire.OutPoint) { wsc *wsClient, op *btcwire.OutPoint) {
// Remove the request tracking from the client. // Remove the request tracking from the client.
@ -609,8 +609,8 @@ func newRedeemingTxNotification(txHex string, index int, block *btcutil.Block) (
// websocket clients of the transaction if an output spends to a watched // websocket clients of the transaction if an output spends to a watched
// address. A spent notification request is automatically registered for // address. A spent notification request is automatically registered for
// the client for each matching output. // the client for each matching output.
func (m *wsNotificationManager) notifyForTxOuts(ops map[btcwire.OutPoint]map[chan bool]*wsClient, func (m *wsNotificationManager) notifyForTxOuts(ops map[btcwire.OutPoint]map[chan struct{}]*wsClient,
addrs map[string]map[chan bool]*wsClient, tx *btcutil.Tx, block *btcutil.Block) { addrs map[string]map[chan struct{}]*wsClient, tx *btcutil.Tx, block *btcutil.Block) {
// Nothing to do if nobody is listening for address notifications. // Nothing to do if nobody is listening for address notifications.
if len(addrs) == 0 { if len(addrs) == 0 {
@ -618,7 +618,7 @@ func (m *wsNotificationManager) notifyForTxOuts(ops map[btcwire.OutPoint]map[cha
} }
txHex := "" txHex := ""
wscNotified := make(map[chan bool]struct{}) wscNotified := make(map[chan struct{}]struct{})
for i, txOut := range tx.MsgTx().TxOut { for i, txOut := range tx.MsgTx().TxOut {
_, txAddrs, _, err := btcscript.ExtractPkScriptAddrs( _, txAddrs, _, err := btcscript.ExtractPkScriptAddrs(
txOut.PkScript, m.server.server.netParams) txOut.PkScript, m.server.server.netParams)
@ -659,8 +659,8 @@ func (m *wsNotificationManager) notifyForTxOuts(ops map[btcwire.OutPoint]map[cha
// notifyForTx examines the inputs and outputs of the passed transaction, // notifyForTx examines the inputs and outputs of the passed transaction,
// notifying websocket clients of outputs spending to a watched address // notifying websocket clients of outputs spending to a watched address
// and inputs spending a watched outpoint. // and inputs spending a watched outpoint.
func (m *wsNotificationManager) notifyForTx(ops map[btcwire.OutPoint]map[chan bool]*wsClient, func (m *wsNotificationManager) notifyForTx(ops map[btcwire.OutPoint]map[chan struct{}]*wsClient,
addrs map[string]map[chan bool]*wsClient, tx *btcutil.Tx, block *btcutil.Block) { addrs map[string]map[chan struct{}]*wsClient, tx *btcutil.Tx, block *btcutil.Block) {
if len(ops) != 0 { if len(ops) != 0 {
m.notifyForTxIns(ops, tx, block) m.notifyForTxIns(ops, tx, block)
@ -674,7 +674,7 @@ func (m *wsNotificationManager) notifyForTx(ops map[btcwire.OutPoint]map[chan bo
// interested websocket clients a redeemingtx notification if any inputs // interested websocket clients a redeemingtx notification if any inputs
// spend a watched output. If block is non-nil, any matching spent // spend a watched output. If block is non-nil, any matching spent
// requests are removed. // requests are removed.
func (m *wsNotificationManager) notifyForTxIns(ops map[btcwire.OutPoint]map[chan bool]*wsClient, func (m *wsNotificationManager) notifyForTxIns(ops map[btcwire.OutPoint]map[chan struct{}]*wsClient,
tx *btcutil.Tx, block *btcutil.Block) { tx *btcutil.Tx, block *btcutil.Block) {
// Nothing to do if nobody is watching outpoints. // Nothing to do if nobody is watching outpoints.
@ -683,7 +683,7 @@ func (m *wsNotificationManager) notifyForTxIns(ops map[btcwire.OutPoint]map[chan
} }
txHex := "" txHex := ""
wscNotified := make(map[chan bool]struct{}) wscNotified := make(map[chan struct{}]struct{})
for _, txIn := range tx.MsgTx().TxIn { for _, txIn := range tx.MsgTx().TxIn {
prevOut := &txIn.PreviousOutpoint prevOut := &txIn.PreviousOutpoint
if cmap, ok := ops[*prevOut]; ok { if cmap, ok := ops[*prevOut]; ok {
@ -721,7 +721,7 @@ func (m *wsNotificationManager) RegisterTxOutAddressRequest(wsc *wsClient, addr
// addAddrRequest adds the websocket client wsc to the address to client set // addAddrRequest adds the websocket client wsc to the address to client set
// addrs so wsc will be notified for any mempool or block transaction outputs // addrs so wsc will be notified for any mempool or block transaction outputs
// spending to addr. // spending to addr.
func (*wsNotificationManager) addAddrRequest(addrs map[string]map[chan bool]*wsClient, func (*wsNotificationManager) addAddrRequest(addrs map[string]map[chan struct{}]*wsClient,
wsc *wsClient, addr string) { wsc *wsClient, addr string) {
// Track the request in the client as well so it can be quickly be // Track the request in the client as well so it can be quickly be
@ -732,7 +732,7 @@ func (*wsNotificationManager) addAddrRequest(addrs map[string]map[chan bool]*wsC
// seen. Create map as needed. // seen. Create map as needed.
cmap, ok := addrs[addr] cmap, ok := addrs[addr]
if !ok { if !ok {
cmap = make(map[chan bool]*wsClient) cmap = make(map[chan struct{}]*wsClient)
addrs[addr] = cmap addrs[addr] = cmap
} }
cmap[wsc.quit] = wsc cmap[wsc.quit] = wsc
@ -750,7 +750,7 @@ func (m *wsNotificationManager) UnregisterTxOutAddressRequest(wsc *wsClient, add
// removeAddrRequest removes the websocket client wsc from the address to // removeAddrRequest removes the websocket client wsc from the address to
// client set addrs so it will no longer receive notification updates for // client set addrs so it will no longer receive notification updates for
// any transaction outputs send to addr. // any transaction outputs send to addr.
func (*wsNotificationManager) removeAddrRequest(addrs map[string]map[chan bool]*wsClient, func (*wsNotificationManager) removeAddrRequest(addrs map[string]map[chan struct{}]*wsClient,
wsc *wsClient, addr string) { wsc *wsClient, addr string) {
// Remove the request tracking from the client. // Remove the request tracking from the client.
@ -909,7 +909,7 @@ type wsClient struct {
asyncChan chan btcjson.Cmd asyncChan chan btcjson.Cmd
ntfnChan chan []byte ntfnChan chan []byte
sendChan chan wsResponse sendChan chan wsResponse
quit chan bool quit chan struct{}
wg sync.WaitGroup wg sync.WaitGroup
} }
@ -1193,7 +1193,7 @@ cleanup:
// serialized. It must be run as a goroutine. Also, this goroutine is not // serialized. It must be run as a goroutine. Also, this goroutine is not
// started until/if the first long-running request is made. // started until/if the first long-running request is made.
func (c *wsClient) asyncHandler() { func (c *wsClient) asyncHandler() {
asyncHandlerDoneChan := make(chan bool, 1) // nonblocking sync asyncHandlerDoneChan := make(chan struct{}, 1) // nonblocking sync
pendingCmds := list.New() pendingCmds := list.New()
waiting := false waiting := false
@ -1226,7 +1226,7 @@ out:
c.wg.Add(1) c.wg.Add(1)
go func(cmd btcjson.Cmd) { go func(cmd btcjson.Cmd) {
runHandler(cmd) runHandler(cmd)
asyncHandlerDoneChan <- true asyncHandlerDoneChan <- struct{}{}
c.wg.Done() c.wg.Done()
}(cmd) }(cmd)
} else { } else {
@ -1249,7 +1249,7 @@ out:
c.wg.Add(1) c.wg.Add(1)
go func(cmd btcjson.Cmd) { go func(cmd btcjson.Cmd) {
runHandler(cmd) runHandler(cmd)
asyncHandlerDoneChan <- true asyncHandlerDoneChan <- struct{}{}
c.wg.Done() c.wg.Done()
}(element.(btcjson.Cmd)) }(element.(btcjson.Cmd))
@ -1375,7 +1375,7 @@ func newWebsocketClient(server *rpcServer, conn *websocket.Conn,
ntfnChan: make(chan []byte, 1), // nonblocking sync ntfnChan: make(chan []byte, 1), // nonblocking sync
asyncChan: make(chan btcjson.Cmd, 1), // nonblocking sync asyncChan: make(chan btcjson.Cmd, 1), // nonblocking sync
sendChan: make(chan wsResponse, websocketSendBufferSize), sendChan: make(chan wsResponse, websocketSendBufferSize),
quit: make(chan bool), quit: make(chan struct{}),
} }
} }

View file

@ -80,12 +80,12 @@ type server struct {
newPeers chan *peer newPeers chan *peer
donePeers chan *peer donePeers chan *peer
banPeers chan *peer banPeers chan *peer
wakeup chan bool wakeup chan struct{}
query chan interface{} query chan interface{}
relayInv chan *btcwire.InvVect relayInv chan *btcwire.InvVect
broadcast chan broadcastMsg broadcast chan broadcastMsg
wg sync.WaitGroup wg sync.WaitGroup
quit chan bool quit chan struct{}
nat NAT nat NAT
db btcdb.Db db btcdb.Db
} }
@ -541,7 +541,7 @@ func (s *server) peerHandler() {
} }
// if nothing else happens, wake us up soon. // if nothing else happens, wake us up soon.
time.AfterFunc(10*time.Second, func() { s.wakeup <- true }) time.AfterFunc(10*time.Second, func() { s.wakeup <- struct{}{} })
out: out:
for { for {
@ -658,7 +658,7 @@ out:
// We we need more peers, wake up in ten seconds and try again. // We we need more peers, wake up in ten seconds and try again.
if state.NeedMoreOutbound() { if state.NeedMoreOutbound() {
time.AfterFunc(10*time.Second, func() { time.AfterFunc(10*time.Second, func() {
s.wakeup <- true s.wakeup <- struct{}{}
}) })
} }
} }
@ -1172,11 +1172,11 @@ func newServer(listenAddrs []string, db btcdb.Db, netParams *btcnet.Params) (*se
newPeers: make(chan *peer, cfg.MaxPeers), newPeers: make(chan *peer, cfg.MaxPeers),
donePeers: make(chan *peer, cfg.MaxPeers), donePeers: make(chan *peer, cfg.MaxPeers),
banPeers: make(chan *peer, cfg.MaxPeers), banPeers: make(chan *peer, cfg.MaxPeers),
wakeup: make(chan bool), wakeup: make(chan struct{}),
query: make(chan interface{}), query: make(chan interface{}),
relayInv: make(chan *btcwire.InvVect, cfg.MaxPeers), relayInv: make(chan *btcwire.InvVect, cfg.MaxPeers),
broadcast: make(chan broadcastMsg, cfg.MaxPeers), broadcast: make(chan broadcastMsg, cfg.MaxPeers),
quit: make(chan bool), quit: make(chan struct{}),
modifyRebroadcastInv: make(chan interface{}), modifyRebroadcastInv: make(chan interface{}),
nat: nat, nat: nat,
db: db, db: db,

View file

@ -36,7 +36,7 @@ func mainInterruptHandler() {
} }
// Signal the main goroutine to shutdown. // Signal the main goroutine to shutdown.
shutdownChannel <- true shutdownChannel <- struct{}{}
case handler := <-addHandlerChannel: case handler := <-addHandlerChannel:
interruptCallbacks = append(interruptCallbacks, handler) interruptCallbacks = append(interruptCallbacks, handler)

View file

@ -36,7 +36,7 @@ type blockImporter struct {
processQueue chan []byte processQueue chan []byte
doneChan chan bool doneChan chan bool
errChan chan error errChan chan error
quit chan bool quit chan struct{}
wg sync.WaitGroup wg sync.WaitGroup
blocksProcessed int64 blocksProcessed int64
blocksImported int64 blocksImported int64
@ -293,7 +293,7 @@ func newBlockImporter(db btcdb.Db, r io.ReadSeeker) *blockImporter {
processQueue: make(chan []byte, 2), processQueue: make(chan []byte, 2),
doneChan: make(chan bool), doneChan: make(chan bool),
errChan: make(chan error), errChan: make(chan error),
quit: make(chan bool), quit: make(chan struct{}),
chain: btcchain.New(db, activeNetwork, nil), chain: btcchain.New(db, activeNetwork, nil),
lastLogTime: time.Now(), lastLogTime: time.Now(),
} }