Changeset View
Changeset View
Standalone View
Standalone View
src/validationinterface.cpp
Show All 11 Lines | |||||
#include <validation.h> | #include <validation.h> | ||||
#include <boost/signals2/signal.hpp> | #include <boost/signals2/signal.hpp> | ||||
#include <atomic> | #include <atomic> | ||||
#include <future> | #include <future> | ||||
#include <list> | #include <list> | ||||
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 { | struct MainSignalsInstance { | ||||
boost::signals2::signal<void(const CBlockIndex *, const CBlockIndex *, | boost::signals2::signal<void(const CBlockIndex *, const CBlockIndex *, | ||||
bool fInitialDownload)> | bool fInitialDownload)> | ||||
UpdatedBlockTip; | UpdatedBlockTip; | ||||
boost::signals2::signal<void(const CTransactionRef &)> | boost::signals2::signal<void(const CTransactionRef &)> | ||||
TransactionAddedToMempool; | TransactionAddedToMempool; | ||||
boost::signals2::signal<void(const std::shared_ptr<const CBlock> &, | boost::signals2::signal<void(const std::shared_ptr<const CBlock> &, | ||||
const CBlockIndex *pindex, | const CBlockIndex *pindex, | ||||
Show All 11 Lines | struct MainSignalsInstance { | ||||
boost::signals2::signal<void(const CBlockIndex *, | boost::signals2::signal<void(const CBlockIndex *, | ||||
const std::shared_ptr<const CBlock> &)> | const std::shared_ptr<const CBlock> &)> | ||||
NewPoWValidBlock; | NewPoWValidBlock; | ||||
// We are not allowed to assume the scheduler only runs in one thread, | // We are not allowed to assume the scheduler only runs in one thread, | ||||
// but must ensure all callbacks happen in-order, so we end up creating | // but must ensure all callbacks happen in-order, so we end up creating | ||||
// our own queue here :( | // our own queue here :( | ||||
SingleThreadedSchedulerClient m_schedulerClient; | SingleThreadedSchedulerClient m_schedulerClient; | ||||
std::unordered_map<CValidationInterface *, ValidationInterfaceConnections> | |||||
m_connMainSignals; | |||||
explicit MainSignalsInstance(CScheduler *pscheduler) | explicit MainSignalsInstance(CScheduler *pscheduler) | ||||
: m_schedulerClient(pscheduler) {} | : m_schedulerClient(pscheduler) {} | ||||
}; | }; | ||||
static CMainSignals g_signals; | 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<CTxMemPool *, boost::signals2::scoped_connection> | |||||
g_connNotifyEntryRemoved; | |||||
void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler &scheduler) { | void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler &scheduler) { | ||||
assert(!m_internals); | assert(!m_internals); | ||||
m_internals.reset(new MainSignalsInstance(&scheduler)); | m_internals.reset(new MainSignalsInstance(&scheduler)); | ||||
} | } | ||||
void CMainSignals::UnregisterBackgroundSignalScheduler() { | void CMainSignals::UnregisterBackgroundSignalScheduler() { | ||||
m_internals.reset(nullptr); | m_internals.reset(nullptr); | ||||
} | } | ||||
void CMainSignals::FlushBackgroundCallbacks() { | void CMainSignals::FlushBackgroundCallbacks() { | ||||
if (m_internals) { | if (m_internals) { | ||||
m_internals->m_schedulerClient.EmptyQueue(); | m_internals->m_schedulerClient.EmptyQueue(); | ||||
} | } | ||||
} | } | ||||
size_t CMainSignals::CallbacksPending() { | size_t CMainSignals::CallbacksPending() { | ||||
if (!m_internals) { | if (!m_internals) { | ||||
return 0; | return 0; | ||||
} | } | ||||
return m_internals->m_schedulerClient.CallbacksPending(); | return m_internals->m_schedulerClient.CallbacksPending(); | ||||
} | } | ||||
void CMainSignals::RegisterWithMempoolSignals(CTxMemPool &pool) { | void CMainSignals::RegisterWithMempoolSignals(CTxMemPool &pool) { | ||||
pool.NotifyEntryRemoved.connect( | g_connNotifyEntryRemoved.emplace( | ||||
boost::bind(&CMainSignals::MempoolEntryRemoved, this, _1, _2)); | &pool, pool.NotifyEntryRemoved.connect(boost::bind( | ||||
&CMainSignals::MempoolEntryRemoved, this, _1, _2))); | |||||
} | } | ||||
void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool &pool) { | void CMainSignals::UnregisterWithMempoolSignals(CTxMemPool &pool) { | ||||
pool.NotifyEntryRemoved.disconnect( | g_connNotifyEntryRemoved.erase(&pool); | ||||
boost::bind(&CMainSignals::MempoolEntryRemoved, this, _1, _2)); | |||||
} | } | ||||
CMainSignals &GetMainSignals() { | CMainSignals &GetMainSignals() { | ||||
return g_signals; | return g_signals; | ||||
} | } | ||||
void RegisterValidationInterface(CValidationInterface *pwalletIn) { | void RegisterValidationInterface(CValidationInterface *pwalletIn) { | ||||
ValidationInterfaceConnections &conns = | |||||
g_signals.m_internals->m_connMainSignals[pwalletIn]; | |||||
conns.UpdatedBlockTip = | |||||
g_signals.m_internals->UpdatedBlockTip.connect(boost::bind( | g_signals.m_internals->UpdatedBlockTip.connect(boost::bind( | ||||
&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); | &CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); | ||||
conns.TransactionAddedToMempool = | |||||
g_signals.m_internals->TransactionAddedToMempool.connect(boost::bind( | g_signals.m_internals->TransactionAddedToMempool.connect(boost::bind( | ||||
&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); | &CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); | ||||
conns.BlockConnected = | |||||
g_signals.m_internals->BlockConnected.connect(boost::bind( | g_signals.m_internals->BlockConnected.connect(boost::bind( | ||||
&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); | &CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); | ||||
g_signals.m_internals->BlockDisconnected.connect( | conns.BlockDisconnected = g_signals.m_internals->BlockDisconnected.connect( | ||||
boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); | boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); | ||||
g_signals.m_internals->TransactionRemovedFromMempool.connect(boost::bind( | conns.TransactionRemovedFromMempool = | ||||
&CValidationInterface::TransactionRemovedFromMempool, pwalletIn, _1)); | g_signals.m_internals->TransactionRemovedFromMempool.connect( | ||||
g_signals.m_internals->ChainStateFlushed.connect( | boost::bind(&CValidationInterface::TransactionRemovedFromMempool, | ||||
pwalletIn, _1)); | |||||
conns.ChainStateFlushed = g_signals.m_internals->ChainStateFlushed.connect( | |||||
boost::bind(&CValidationInterface::ChainStateFlushed, pwalletIn, _1)); | 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)); | &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)); | boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); | ||||
conns.NewPoWValidBlock = | |||||
g_signals.m_internals->NewPoWValidBlock.connect(boost::bind( | g_signals.m_internals->NewPoWValidBlock.connect(boost::bind( | ||||
&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); | &CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); | ||||
} | } | ||||
void UnregisterValidationInterface(CValidationInterface *pwalletIn) { | void UnregisterValidationInterface(CValidationInterface *pwalletIn) { | ||||
g_signals.m_internals->BlockChecked.disconnect( | g_signals.m_internals->m_connMainSignals.erase(pwalletIn); | ||||
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)); | |||||
} | } | ||||
void UnregisterAllValidationInterfaces() { | void UnregisterAllValidationInterfaces() { | ||||
if (!g_signals.m_internals) { | if (!g_signals.m_internals) { | ||||
return; | return; | ||||
} | } | ||||
g_signals.m_internals->BlockChecked.disconnect_all_slots(); | g_signals.m_internals->m_connMainSignals.clear(); | ||||
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(); | |||||
} | } | ||||
void CallFunctionInValidationInterfaceQueue(std::function<void()> func) { | void CallFunctionInValidationInterfaceQueue(std::function<void()> func) { | ||||
g_signals.m_internals->m_schedulerClient.AddToProcessQueue(std::move(func)); | g_signals.m_internals->m_schedulerClient.AddToProcessQueue(std::move(func)); | ||||
} | } | ||||
void SyncWithValidationInterfaceQueue() { | void SyncWithValidationInterfaceQueue() { | ||||
AssertLockNotHeld(cs_main); | AssertLockNotHeld(cs_main); | ||||
▲ Show 20 Lines • Show All 67 Lines • Show Last 20 Lines |