diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -539,11 +539,9 @@ std::vector CRPCTable::listCommands() const { std::vector commandList; - typedef std::map commandMap; - - std::transform(mapCommands.begin(), mapCommands.end(), - std::back_inserter(commandList), - boost::bind(&commandMap::value_type::first, _1)); + for (const auto &i : mapCommands) { + commandList.emplace_back(i.first); + } return commandList; } diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2318,15 +2318,11 @@ private: std::vector blocksConnected; CTxMemPool &pool; + boost::signals2::scoped_connection m_connNotifyEntryRemoved; public: explicit ConnectTrace(CTxMemPool &_pool) : blocksConnected(1), pool(_pool) { - pool.NotifyEntryRemoved.connect( - boost::bind(&ConnectTrace::NotifyEntryRemoved, this, _1, _2)); - } - - ~ConnectTrace() { - pool.NotifyEntryRemoved.disconnect( + m_connNotifyEntryRemoved = pool.NotifyEntryRemoved.connect( boost::bind(&ConnectTrace::NotifyEntryRemoved, this, _1, _2)); } diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -17,6 +17,18 @@ #include #include +struct ValidationInterfaceConnections { + boost::signals2::scoped_connection UpdatedBlockTip; + boost::signals2::scoped_connection TransactionAddedToMempool; + boost::signals2::scoped_connection BlockConnected; + boost::signals2::scoped_connection BlockDisconnected; + boost::signals2::scoped_connection TransactionRemovedFromMempool; + boost::signals2::scoped_connection ChainStateFlushed; + boost::signals2::scoped_connection Broadcast; + boost::signals2::scoped_connection BlockChecked; + boost::signals2::scoped_connection NewPoWValidBlock; +}; + struct MainSignalsInstance { boost::signals2::signal @@ -44,6 +56,8 @@ // but must ensure all callbacks happen in-order, so we end up creating // our own queue here :( SingleThreadedSchedulerClient m_schedulerClient; + std::unordered_map + m_connMainSignals; explicit MainSignalsInstance(CScheduler *pscheduler) : m_schedulerClient(pscheduler) {} @@ -51,6 +65,13 @@ static CMainSignals g_signals; +// This map has to be a separate global instead of a member of +// MainSignalsInstance, because RegisterWithMempoolSignals is currently called +// before RegisterBackgroundSignalScheduler, so MainSignalsInstance hasn't been +// created yet. +static std::unordered_map + g_connNotifyEntryRemoved; + void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler &scheduler) { assert(!m_internals); m_internals.reset(new MainSignalsInstance(&scheduler)); @@ -74,13 +95,13 @@ } void CMainSignals::RegisterWithMempoolSignals(CTxMemPool &pool) { - pool.NotifyEntryRemoved.connect( - boost::bind(&CMainSignals::MempoolEntryRemoved, this, _1, _2)); + g_connNotifyEntryRemoved.emplace( + &pool, pool.NotifyEntryRemoved.connect(boost::bind( + &CMainSignals::MempoolEntryRemoved, this, _1, _2))); } void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool &pool) { - pool.NotifyEntryRemoved.disconnect( - boost::bind(&CMainSignals::MempoolEntryRemoved, this, _1, _2)); + g_connNotifyEntryRemoved.erase(&pool); } CMainSignals &GetMainSignals() { @@ -88,60 +109,43 @@ } void RegisterValidationInterface(CValidationInterface *pwalletIn) { - g_signals.m_internals->UpdatedBlockTip.connect(boost::bind( - &CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); - g_signals.m_internals->TransactionAddedToMempool.connect(boost::bind( - &CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); - g_signals.m_internals->BlockConnected.connect(boost::bind( - &CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); - g_signals.m_internals->BlockDisconnected.connect( + ValidationInterfaceConnections &conns = + g_signals.m_internals->m_connMainSignals[pwalletIn]; + conns.UpdatedBlockTip = + g_signals.m_internals->UpdatedBlockTip.connect(boost::bind( + &CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); + conns.TransactionAddedToMempool = + g_signals.m_internals->TransactionAddedToMempool.connect(boost::bind( + &CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); + conns.BlockConnected = + g_signals.m_internals->BlockConnected.connect(boost::bind( + &CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); + conns.BlockDisconnected = g_signals.m_internals->BlockDisconnected.connect( boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); - g_signals.m_internals->TransactionRemovedFromMempool.connect(boost::bind( - &CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1)); - g_signals.m_internals->ChainStateFlushed.connect( + conns.TransactionRemovedFromMempool = + g_signals.m_internals->TransactionRemovedFromMempool.connect( + boost::bind(&CValidationInterface::TransactionRemovedFromMempool, + pwalletIn, _1)); + conns.ChainStateFlushed = g_signals.m_internals->ChainStateFlushed.connect( boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1)); - g_signals.m_internals->Broadcast.connect(boost::bind( + conns.Broadcast = g_signals.m_internals->Broadcast.connect(boost::bind( &CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); - g_signals.m_internals->BlockChecked.connect( + conns.BlockChecked = g_signals.m_internals->BlockChecked.connect( boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); - g_signals.m_internals->NewPoWValidBlock.connect(boost::bind( - &CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); + conns.NewPoWValidBlock = + g_signals.m_internals->NewPoWValidBlock.connect(boost::bind( + &CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); } void UnregisterValidationInterface(CValidationInterface *pwalletIn) { - g_signals.m_internals->BlockChecked.disconnect( - boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); - g_signals.m_internals->Broadcast.disconnect(boost::bind( - &CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); - g_signals.m_internals->ChainStateFlushed.disconnect( - boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1)); - g_signals.m_internals->TransactionAddedToMempool.disconnect(boost::bind( - &CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); - g_signals.m_internals->BlockConnected.disconnect(boost::bind( - &CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); - g_signals.m_internals->BlockDisconnected.disconnect( - boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); - g_signals.m_internals->TransactionRemovedFromMempool.disconnect(boost::bind( - &CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1)); - g_signals.m_internals->UpdatedBlockTip.disconnect(boost::bind( - &CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); - g_signals.m_internals->NewPoWValidBlock.disconnect(boost::bind( - &CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); + g_signals.m_internals->m_connMainSignals.erase(pwalletIn); } void UnregisterAllValidationInterfaces() { if (!g_signals.m_internals) { return; } - g_signals.m_internals->BlockChecked.disconnect_all_slots(); - g_signals.m_internals->Broadcast.disconnect_all_slots(); - g_signals.m_internals->ChainStateFlushed.disconnect_all_slots(); - g_signals.m_internals->TransactionAddedToMempool.disconnect_all_slots(); - g_signals.m_internals->BlockConnected.disconnect_all_slots(); - g_signals.m_internals->BlockDisconnected.disconnect_all_slots(); - g_signals.m_internals->TransactionRemovedFromMempool.disconnect_all_slots(); - g_signals.m_internals->UpdatedBlockTip.disconnect_all_slots(); - g_signals.m_internals->NewPoWValidBlock.disconnect_all_slots(); + g_signals.m_internals->m_connMainSignals.clear(); } void CallFunctionInValidationInterfaceQueue(std::function func) {