From 3a19fed9db558a5f666d965b6f602f7faf74ab73 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 19 Jan 2017 16:17:14 -0500 Subject: Make ValidationInterface signals-type-agnostic (by hiding boost::signals stuff in the .cpp) This allows us to give it a bit more intelligence as we move forward, including routing some signals through CScheduler. While the introduction of a "internals" pointer in the class is pretty ugly, the fact that we no longer need to include boost/signals directly from validationinterface.h is very much worth the loss. --- src/validationinterface.cpp | 108 +++++++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 27 deletions(-) (limited to 'src/validationinterface.cpp') diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index be2f20b86..7d0ab756e 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -5,45 +5,99 @@ #include "validationinterface.h" +#include + +struct MainSignalsInstance { + boost::signals2::signal UpdatedBlockTip; + boost::signals2::signal TransactionAddedToMempool; + boost::signals2::signal &, const CBlockIndex *pindex, const std::vector&)> BlockConnected; + boost::signals2::signal &)> BlockDisconnected; + boost::signals2::signal SetBestChain; + boost::signals2::signal Inventory; + boost::signals2::signal Broadcast; + boost::signals2::signal BlockChecked; + boost::signals2::signal&)> NewPoWValidBlock; +}; + static CMainSignals g_signals; +CMainSignals::CMainSignals() { + m_internals.reset(new MainSignalsInstance()); +} + CMainSignals& GetMainSignals() { return g_signals; } void RegisterValidationInterface(CValidationInterface* pwalletIn) { - g_signals.UpdatedBlockTip.connect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); - g_signals.TransactionAddedToMempool.connect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); - g_signals.BlockConnected.connect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); - g_signals.BlockDisconnected.connect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); - g_signals.SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); - g_signals.Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); - g_signals.Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); - g_signals.BlockChecked.connect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); - g_signals.NewPoWValidBlock.connect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); + 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(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); + g_signals.m_internals->SetBestChain.connect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); + g_signals.m_internals->Inventory.connect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); + g_signals.m_internals->Broadcast.connect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); + 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)); } void UnregisterValidationInterface(CValidationInterface* pwalletIn) { - g_signals.BlockChecked.disconnect(boost::bind(&CValidationInterface::BlockChecked, pwalletIn, _1, _2)); - g_signals.Broadcast.disconnect(boost::bind(&CValidationInterface::ResendWalletTransactions, pwalletIn, _1, _2)); - g_signals.Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); - g_signals.SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, pwalletIn, _1)); - g_signals.TransactionAddedToMempool.disconnect(boost::bind(&CValidationInterface::TransactionAddedToMempool, pwalletIn, _1)); - g_signals.BlockConnected.disconnect(boost::bind(&CValidationInterface::BlockConnected, pwalletIn, _1, _2, _3)); - g_signals.BlockDisconnected.disconnect(boost::bind(&CValidationInterface::BlockDisconnected, pwalletIn, _1)); - g_signals.UpdatedBlockTip.disconnect(boost::bind(&CValidationInterface::UpdatedBlockTip, pwalletIn, _1, _2, _3)); - g_signals.NewPoWValidBlock.disconnect(boost::bind(&CValidationInterface::NewPoWValidBlock, pwalletIn, _1, _2)); + 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->Inventory.disconnect(boost::bind(&CValidationInterface::Inventory, pwalletIn, _1)); + g_signals.m_internals->SetBestChain.disconnect(boost::bind(&CValidationInterface::SetBestChain, 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->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() { - g_signals.BlockChecked.disconnect_all_slots(); - g_signals.Broadcast.disconnect_all_slots(); - g_signals.Inventory.disconnect_all_slots(); - g_signals.SetBestChain.disconnect_all_slots(); - g_signals.TransactionAddedToMempool.disconnect_all_slots(); - g_signals.BlockConnected.disconnect_all_slots(); - g_signals.BlockDisconnected.disconnect_all_slots(); - g_signals.UpdatedBlockTip.disconnect_all_slots(); - g_signals.NewPoWValidBlock.disconnect_all_slots(); + g_signals.m_internals->BlockChecked.disconnect_all_slots(); + g_signals.m_internals->Broadcast.disconnect_all_slots(); + g_signals.m_internals->Inventory.disconnect_all_slots(); + g_signals.m_internals->SetBestChain.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->UpdatedBlockTip.disconnect_all_slots(); + g_signals.m_internals->NewPoWValidBlock.disconnect_all_slots(); +} + +void CMainSignals::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) { + m_internals->UpdatedBlockTip(pindexNew, pindexFork, fInitialDownload); +} + +void CMainSignals::TransactionAddedToMempool(const CTransactionRef &ptx) { + m_internals->TransactionAddedToMempool(ptx); +} + +void CMainSignals::BlockConnected(const std::shared_ptr &pblock, const CBlockIndex *pindex, const std::vector& vtxConflicted) { + m_internals->BlockConnected(pblock, pindex, vtxConflicted); +} + +void CMainSignals::BlockDisconnected(const std::shared_ptr &pblock) { + m_internals->BlockDisconnected(pblock); +} + +void CMainSignals::SetBestChain(const CBlockLocator &locator) { + m_internals->SetBestChain(locator); +} + +void CMainSignals::Inventory(const uint256 &hash) { + m_internals->Inventory(hash); +} + +void CMainSignals::Broadcast(int64_t nBestBlockTime, CConnman* connman) { + m_internals->Broadcast(nBestBlockTime, connman); +} + +void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) { + m_internals->BlockChecked(block, state); +} + +void CMainSignals::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr &block) { + m_internals->NewPoWValidBlock(pindex, block); } -- cgit v1.2.3 From cda1429d5bfee129a0d1f6f1c65962b30251bafb Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 19 Jan 2017 16:49:22 -0500 Subject: Give CMainSignals a reference to the global scheduler ...so that it can run some signals in the background later --- src/validationinterface.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/validationinterface.cpp') diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 7d0ab756e..a17a08eee 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -4,6 +4,8 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "validationinterface.h" +#include "init.h" +#include "scheduler.h" #include @@ -17,6 +19,8 @@ struct MainSignalsInstance { boost::signals2::signal Broadcast; boost::signals2::signal BlockChecked; boost::signals2::signal&)> NewPoWValidBlock; + + CScheduler *m_scheduler = NULL; }; static CMainSignals g_signals; @@ -25,6 +29,15 @@ CMainSignals::CMainSignals() { m_internals.reset(new MainSignalsInstance()); } +void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) { + assert(!m_internals->m_scheduler); + m_internals->m_scheduler = &scheduler; +} + +void CMainSignals::UnregisterBackgroundSignalScheduler() { + m_internals->m_scheduler = NULL; +} + CMainSignals& GetMainSignals() { return g_signals; -- cgit v1.2.3 From 08096bbbc6d6fef86943ca8ce5e6de18744d58ea Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 10 Apr 2017 14:55:49 -0400 Subject: Support more than one CScheduler thread for serial clients This will be used by CValidationInterface soon. This requires a bit of work as we need to ensure that most of our callbacks happen in-order (to avoid synchronization issues in wallet) - we keep our own internal queue and push things onto it, scheduling a queue-draining function immediately upon new callbacks. --- src/validationinterface.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'src/validationinterface.cpp') diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index a17a08eee..8edc7c398 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -6,6 +6,11 @@ #include "validationinterface.h" #include "init.h" #include "scheduler.h" +#include "sync.h" +#include "util.h" + +#include +#include #include @@ -20,22 +25,23 @@ struct MainSignalsInstance { boost::signals2::signal BlockChecked; boost::signals2::signal&)> NewPoWValidBlock; - CScheduler *m_scheduler = NULL; + // 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 + // our own queue here :( + SingleThreadedSchedulerClient m_schedulerClient; + + MainSignalsInstance(CScheduler *pscheduler) : m_schedulerClient(pscheduler) {} }; static CMainSignals g_signals; -CMainSignals::CMainSignals() { - m_internals.reset(new MainSignalsInstance()); -} - void CMainSignals::RegisterBackgroundSignalScheduler(CScheduler& scheduler) { - assert(!m_internals->m_scheduler); - m_internals->m_scheduler = &scheduler; + assert(!m_internals); + m_internals.reset(new MainSignalsInstance(&scheduler)); } void CMainSignals::UnregisterBackgroundSignalScheduler() { - m_internals->m_scheduler = NULL; + m_internals.reset(nullptr); } CMainSignals& GetMainSignals() -- cgit v1.2.3 From 3192975f1d177aa9f0bbd823c6387cfbfa943610 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 27 Jun 2017 19:07:52 -0400 Subject: Flush CValidationInterface callbacks prior to destruction Note that the CScheduler thread cant be running at this point, it has already been stopped with the rest of the init threadgroup. Thus, just calling any remaining loose callbacks during Shutdown() is sane. --- src/validationinterface.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/validationinterface.cpp') diff --git a/src/validationinterface.cpp b/src/validationinterface.cpp index 8edc7c398..bf20d606f 100644 --- a/src/validationinterface.cpp +++ b/src/validationinterface.cpp @@ -44,6 +44,10 @@ void CMainSignals::UnregisterBackgroundSignalScheduler() { m_internals.reset(nullptr); } +void CMainSignals::FlushBackgroundCallbacks() { + m_internals->m_schedulerClient.EmptyQueue(); +} + CMainSignals& GetMainSignals() { return g_signals; -- cgit v1.2.3