From f439dece37c8b4383c4433bc61cc2618a7af373b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Senart?= Date: Wed, 2 Jul 2014 17:31:10 +0200 Subject: [PATCH] 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 --- addrmanager.go | 4 ++-- blockmanager.go | 4 ++-- btcd.go | 4 ++-- peer.go | 12 +++++----- rpcwebsocket.go | 52 ++++++++++++++++++++--------------------- server.go | 12 +++++----- signal.go | 2 +- util/addblock/import.go | 4 ++-- 8 files changed, 47 insertions(+), 47 deletions(-) diff --git a/addrmanager.go b/addrmanager.go index b93f05ce..7ae57700 100644 --- a/addrmanager.go +++ b/addrmanager.go @@ -338,7 +338,7 @@ type AddrManager struct { started int32 shutdown int32 wg sync.WaitGroup - quit chan bool + quit chan struct{} nTried int nNew int lamtx sync.Mutex @@ -759,7 +759,7 @@ func (a *AddrManager) reset() { func NewAddrManager() *AddrManager { am := AddrManager{ rand: rand.New(rand.NewSource(time.Now().UnixNano())), - quit: make(chan bool), + quit: make(chan struct{}), localAddresses: make(map[string]*localAddress), } am.reset() diff --git a/blockmanager.go b/blockmanager.go index 59c5bbe8..fa102cb0 100644 --- a/blockmanager.go +++ b/blockmanager.go @@ -174,7 +174,7 @@ type blockManager struct { msgChan chan interface{} chainState chainState wg sync.WaitGroup - quit chan bool + quit chan struct{} // The following fields are used for headers-first mode. headersFirstMode bool @@ -1309,7 +1309,7 @@ func newBlockManager(s *server) (*blockManager, error) { lastBlockLogTime: time.Now(), msgChan: make(chan interface{}, cfg.MaxPeers*3), headerList: list.New(), - quit: make(chan bool), + quit: make(chan struct{}), } bm.blockChain = btcchain.New(s.db, s.netParams, bm.handleNotifyMsg) bm.blockChain.DisableCheckpoints(cfg.DisableCheckpoints) diff --git a/btcd.go b/btcd.go index 94d7a32b..6fbd2702 100644 --- a/btcd.go +++ b/btcd.go @@ -18,7 +18,7 @@ import ( var ( cfg *config - shutdownChannel = make(chan bool) + shutdownChannel = make(chan struct{}) ) // winServiceMain is only invoked on Windows. It detects when btcd is running @@ -114,7 +114,7 @@ func btcdMain(serverChan chan<- *server) error { go func() { server.WaitForShutdown() srvrLog.Infof("Server shutdown complete") - shutdownChannel <- true + shutdownChannel <- struct{}{} }() // Wait for shutdown signal from either a graceful server stop or from diff --git a/peer.go b/peer.go index eb476360..58a090fc 100644 --- a/peer.go +++ b/peer.go @@ -160,12 +160,12 @@ type peer struct { continueHash *btcwire.ShaHash outputQueue chan outMsg sendQueue chan outMsg - sendDoneQueue chan bool + sendDoneQueue chan struct{} queueWg sync.WaitGroup // TODO(oga) wg -> single use channel? outputInvChan chan *btcwire.InvVect txProcessed chan bool blockProcessed chan bool - quit chan bool + quit chan struct{} StatsMtx sync.Mutex // protects all statistics below here. versionKnown bool protocolVersion uint32 @@ -1478,7 +1478,7 @@ out: msg.doneChan <- true } peerLog.Tracef("%s: acking queuehandler", p) - p.sendDoneQueue <- true + p.sendDoneQueue <- struct{}{} peerLog.Tracef("%s: acked queuehandler", p) case <-p.quit: @@ -1622,12 +1622,12 @@ func newPeerBase(s *server, inbound bool) *peer { requestedBlocks: make(map[btcwire.ShaHash]struct{}), requestQueue: list.New(), outputQueue: make(chan outMsg, outputBufferSize), - sendQueue: make(chan outMsg, 1), // nonblocking sync - sendDoneQueue: make(chan bool, 1), // nonblocking sync + sendQueue: make(chan outMsg, 1), // nonblocking sync + sendDoneQueue: make(chan struct{}, 1), // nonblocking sync outputInvChan: make(chan *btcwire.InvVect, outputBufferSize), txProcessed: make(chan bool, 1), blockProcessed: make(chan bool, 1), - quit: make(chan bool), + quit: make(chan struct{}), } return &p } diff --git a/rpcwebsocket.go b/rpcwebsocket.go index 1ecb8078..5dcebdf1 100644 --- a/rpcwebsocket.go +++ b/rpcwebsocket.go @@ -259,7 +259,7 @@ type notificationUnregisterAddr struct { // handler and processes one at a time. func (m *wsNotificationManager) notificationHandler() { // 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 // 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 // since it is quite a bit more efficient than using the entire struct. - blockNotifications := make(map[chan bool]*wsClient) - txNotifications := make(map[chan bool]*wsClient) - watchedOutPoints := make(map[btcwire.OutPoint]map[chan bool]*wsClient) - watchedAddrs := make(map[string]map[chan bool]*wsClient) + blockNotifications := make(map[chan struct{}]*wsClient) + txNotifications := make(map[chan struct{}]*wsClient) + watchedOutPoints := make(map[btcwire.OutPoint]map[chan struct{}]*wsClient) + watchedAddrs := make(map[string]map[chan struct{}]*wsClient) out: for { @@ -398,7 +398,7 @@ func (m *wsNotificationManager) UnregisterBlockUpdates(wsc *wsClient) { // notifyBlockConnected notifies websocket clients that have registered for // 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) { hash, err := block.Sha() @@ -423,7 +423,7 @@ func (*wsNotificationManager) notifyBlockConnected(clients map[chan bool]*wsClie // notifyBlockDisconnected notifies websocket clients that have registered for // block updates when a block is disconnected from the main chain (due to a // 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 // connected/disconnected notifications. if len(clients) == 0 { @@ -465,7 +465,7 @@ func (m *wsNotificationManager) UnregisterNewMempoolTxsUpdates(wsc *wsClient) { // notifyForNewTx notifies websocket clients that have registerd for updates // 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() 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 // clients to add a new request watch the outpoint op and create and send // 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) { // 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. cmap, ok := ops[*op] if !ok { - cmap = make(map[chan bool]*wsClient) + cmap = make(map[chan struct{}]*wsClient) ops[*op] = cmap } 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 // watched outpoint is spent. If wsc is the last client, the outpoint // 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) { // 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 // address. A spent notification request is automatically registered for // the client for each matching output. -func (m *wsNotificationManager) notifyForTxOuts(ops map[btcwire.OutPoint]map[chan bool]*wsClient, - addrs map[string]map[chan bool]*wsClient, tx *btcutil.Tx, block *btcutil.Block) { +func (m *wsNotificationManager) notifyForTxOuts(ops map[btcwire.OutPoint]map[chan struct{}]*wsClient, + addrs map[string]map[chan struct{}]*wsClient, tx *btcutil.Tx, block *btcutil.Block) { // Nothing to do if nobody is listening for address notifications. if len(addrs) == 0 { @@ -618,7 +618,7 @@ func (m *wsNotificationManager) notifyForTxOuts(ops map[btcwire.OutPoint]map[cha } txHex := "" - wscNotified := make(map[chan bool]struct{}) + wscNotified := make(map[chan struct{}]struct{}) for i, txOut := range tx.MsgTx().TxOut { _, txAddrs, _, err := btcscript.ExtractPkScriptAddrs( 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, // notifying websocket clients of outputs spending to a watched address // and inputs spending a watched outpoint. -func (m *wsNotificationManager) notifyForTx(ops map[btcwire.OutPoint]map[chan bool]*wsClient, - addrs map[string]map[chan bool]*wsClient, tx *btcutil.Tx, block *btcutil.Block) { +func (m *wsNotificationManager) notifyForTx(ops map[btcwire.OutPoint]map[chan struct{}]*wsClient, + addrs map[string]map[chan struct{}]*wsClient, tx *btcutil.Tx, block *btcutil.Block) { if len(ops) != 0 { 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 // spend a watched output. If block is non-nil, any matching spent // 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) { // Nothing to do if nobody is watching outpoints. @@ -683,7 +683,7 @@ func (m *wsNotificationManager) notifyForTxIns(ops map[btcwire.OutPoint]map[chan } txHex := "" - wscNotified := make(map[chan bool]struct{}) + wscNotified := make(map[chan struct{}]struct{}) for _, txIn := range tx.MsgTx().TxIn { prevOut := &txIn.PreviousOutpoint 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 // addrs so wsc will be notified for any mempool or block transaction outputs // 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) { // 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. cmap, ok := addrs[addr] if !ok { - cmap = make(map[chan bool]*wsClient) + cmap = make(map[chan struct{}]*wsClient) addrs[addr] = cmap } 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 // client set addrs so it will no longer receive notification updates for // 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) { // Remove the request tracking from the client. @@ -909,7 +909,7 @@ type wsClient struct { asyncChan chan btcjson.Cmd ntfnChan chan []byte sendChan chan wsResponse - quit chan bool + quit chan struct{} wg sync.WaitGroup } @@ -1193,7 +1193,7 @@ cleanup: // serialized. It must be run as a goroutine. Also, this goroutine is not // started until/if the first long-running request is made. func (c *wsClient) asyncHandler() { - asyncHandlerDoneChan := make(chan bool, 1) // nonblocking sync + asyncHandlerDoneChan := make(chan struct{}, 1) // nonblocking sync pendingCmds := list.New() waiting := false @@ -1226,7 +1226,7 @@ out: c.wg.Add(1) go func(cmd btcjson.Cmd) { runHandler(cmd) - asyncHandlerDoneChan <- true + asyncHandlerDoneChan <- struct{}{} c.wg.Done() }(cmd) } else { @@ -1249,7 +1249,7 @@ out: c.wg.Add(1) go func(cmd btcjson.Cmd) { runHandler(cmd) - asyncHandlerDoneChan <- true + asyncHandlerDoneChan <- struct{}{} c.wg.Done() }(element.(btcjson.Cmd)) @@ -1375,7 +1375,7 @@ func newWebsocketClient(server *rpcServer, conn *websocket.Conn, ntfnChan: make(chan []byte, 1), // nonblocking sync asyncChan: make(chan btcjson.Cmd, 1), // nonblocking sync sendChan: make(chan wsResponse, websocketSendBufferSize), - quit: make(chan bool), + quit: make(chan struct{}), } } diff --git a/server.go b/server.go index f6e22467..60fd7f06 100644 --- a/server.go +++ b/server.go @@ -80,12 +80,12 @@ type server struct { newPeers chan *peer donePeers chan *peer banPeers chan *peer - wakeup chan bool + wakeup chan struct{} query chan interface{} relayInv chan *btcwire.InvVect broadcast chan broadcastMsg wg sync.WaitGroup - quit chan bool + quit chan struct{} nat NAT db btcdb.Db } @@ -541,7 +541,7 @@ func (s *server) peerHandler() { } // 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: for { @@ -658,7 +658,7 @@ out: // We we need more peers, wake up in ten seconds and try again. if state.NeedMoreOutbound() { 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), donePeers: make(chan *peer, cfg.MaxPeers), banPeers: make(chan *peer, cfg.MaxPeers), - wakeup: make(chan bool), + wakeup: make(chan struct{}), query: make(chan interface{}), relayInv: make(chan *btcwire.InvVect, cfg.MaxPeers), broadcast: make(chan broadcastMsg, cfg.MaxPeers), - quit: make(chan bool), + quit: make(chan struct{}), modifyRebroadcastInv: make(chan interface{}), nat: nat, db: db, diff --git a/signal.go b/signal.go index 9bd94d3b..61f77a61 100644 --- a/signal.go +++ b/signal.go @@ -36,7 +36,7 @@ func mainInterruptHandler() { } // Signal the main goroutine to shutdown. - shutdownChannel <- true + shutdownChannel <- struct{}{} case handler := <-addHandlerChannel: interruptCallbacks = append(interruptCallbacks, handler) diff --git a/util/addblock/import.go b/util/addblock/import.go index 69a2017e..728ccda6 100644 --- a/util/addblock/import.go +++ b/util/addblock/import.go @@ -36,7 +36,7 @@ type blockImporter struct { processQueue chan []byte doneChan chan bool errChan chan error - quit chan bool + quit chan struct{} wg sync.WaitGroup blocksProcessed int64 blocksImported int64 @@ -293,7 +293,7 @@ func newBlockImporter(db btcdb.Db, r io.ReadSeeker) *blockImporter { processQueue: make(chan []byte, 2), doneChan: make(chan bool), errChan: make(chan error), - quit: make(chan bool), + quit: make(chan struct{}), chain: btcchain.New(db, activeNetwork, nil), lastLogTime: time.Now(), }