diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -391,6 +391,7 @@ util/strencodings.cpp util/string.cpp util/system.cpp + util/thread.cpp util/threadnames.cpp util/time.cpp util/url.cpp diff --git a/src/index/base.cpp b/src/index/base.cpp --- a/src/index/base.cpp +++ b/src/index/base.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include // For CChainState #include @@ -371,8 +371,8 @@ return; } - m_thread_sync = std::thread(&TraceThread>, GetName(), - std::bind(&BaseIndex::ThreadSync, this)); + m_thread_sync = + std::thread(&util::TraceThread, GetName(), [this] { ThreadSync(); }); } void BaseIndex::Stop() { diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -64,6 +64,7 @@ #include #include #include +#include #include #include #include @@ -2286,9 +2287,9 @@ node.scheduler = std::make_unique(); // Start the lightweight task scheduler thread - node.scheduler->m_service_thread = std::thread([&] { - TraceThread("scheduler", [&] { node.scheduler->serviceQueue(); }); - }); + node.scheduler->m_service_thread = + std::thread(&util::TraceThread, "scheduler", + [&] { node.scheduler->serviceQueue(); }); // Gather some entropy once per minute. node.scheduler->scheduleEvery( @@ -2944,11 +2945,10 @@ vImportFiles.push_back(fs::PathFromString(strFile)); } - chainman.m_load_block = - std::thread(&TraceThread>, "loadblk", - [=, &config, &chainman, &args] { - ThreadImport(config, chainman, vImportFiles, args); - }); + chainman.m_load_block = std::thread( + &util::TraceThread, "loadblk", [=, &config, &chainman, &args] { + ThreadImport(config, chainman, vImportFiles, args); + }); // Wait for genesis block to be processed { diff --git a/src/net.cpp b/src/net.cpp --- a/src/net.cpp +++ b/src/net.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #ifdef WIN32 @@ -2003,8 +2004,7 @@ void StartMapPort() { if (!g_upnp_thread.joinable()) { assert(!g_upnp_interrupt); - g_upnp_thread = std::thread( - (std::bind(&TraceThread, "upnp", &ThreadMapPort))); + g_upnp_thread = std::thread(&util::TraceThread, "upnp", &ThreadMapPort); } } @@ -3128,24 +3128,19 @@ } // Send and receive from sockets, accept connections - threadSocketHandler = std::thread( - &TraceThread>, "net", - std::function(std::bind(&CConnman::ThreadSocketHandler, this))); + threadSocketHandler = std::thread(&util::TraceThread, "net", + [this] { ThreadSocketHandler(); }); if (!gArgs.GetBoolArg("-dnsseed", DEFAULT_DNSSEED)) { LogPrintf("DNS seeding disabled\n"); } else { - threadDNSAddressSeed = - std::thread(&TraceThread>, "dnsseed", - std::function( - std::bind(&CConnman::ThreadDNSAddressSeed, this))); + threadDNSAddressSeed = std::thread(&util::TraceThread, "dnsseed", + [this] { ThreadDNSAddressSeed(); }); } // Initiate manual connections - threadOpenAddedConnections = - std::thread(&TraceThread>, "addcon", - std::function(std::bind( - &CConnman::ThreadOpenAddedConnections, this))); + threadOpenAddedConnections = std::thread( + &util::TraceThread, "addcon", [this] { ThreadOpenAddedConnections(); }); if (connOptions.m_use_addrman_outgoing && !connOptions.m_specified_outgoing.empty()) { @@ -3160,24 +3155,21 @@ if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty()) { threadOpenConnections = - std::thread(&TraceThread>, "opencon", - std::function(std::bind( - &CConnman::ThreadOpenConnections, this, - connOptions.m_specified_outgoing, nullptr))); + std::thread(&util::TraceThread, "opencon", + [this, connect = connOptions.m_specified_outgoing] { + ThreadOpenConnections(connect, nullptr); + }); } // Process messages - threadMessageHandler = - std::thread(&TraceThread>, "msghand", - std::function( - std::bind(&CConnman::ThreadMessageHandler, this))); + threadMessageHandler = std::thread(&util::TraceThread, "msghand", + [this] { ThreadMessageHandler(); }); if (connOptions.m_i2p_accept_incoming && m_i2p_sam_session.get() != nullptr) { threadI2PAcceptIncoming = - std::thread(&TraceThread>, "i2paccept", - std::function(std::bind( - &CConnman::ThreadI2PAcceptIncoming, this))); + std::thread(&util::TraceThread, "i2paccept", + [this] { ThreadI2PAcceptIncoming(); }); } // Dump network addresses diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include #include #include @@ -156,9 +158,9 @@ // We have to run a scheduler thread to prevent ActivateBestChain // from blocking due to queue overrun. m_node.scheduler = std::make_unique(); - m_node.scheduler->m_service_thread = std::thread([&] { - TraceThread("scheduler", [&] { m_node.scheduler->serviceQueue(); }); - }); + m_node.scheduler->m_service_thread = + std::thread(util::TraceThread, "scheduler", + [&] { m_node.scheduler->serviceQueue(); }); GetMainSignals().RegisterBackgroundSignalScheduler(*m_node.scheduler); pblocktree.reset(new CBlockTreeDB(1 << 20, true)); diff --git a/src/torcontrol.cpp b/src/torcontrol.cpp --- a/src/torcontrol.cpp +++ b/src/torcontrol.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -842,9 +843,10 @@ return; } - torControlThread = std::thread( - &TraceThread>, "torcontrol", - [onion_service_target] { TorControlThread(onion_service_target); }); + torControlThread = + std::thread(&util::TraceThread, "torcontrol", [onion_service_target] { + TorControlThread(onion_service_target); + }); } void InterruptTorControl() { diff --git a/src/txmempool.cpp b/src/txmempool.cpp --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -24,6 +24,7 @@ #include #include +#include CTxMemPoolEntry::CTxMemPoolEntry(const CTransactionRef &_tx, const Amount _nFee, int64_t _nTime, unsigned int _entryHeight, diff --git a/src/util/system.h b/src/util/system.h --- a/src/util/system.h +++ b/src/util/system.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include @@ -475,24 +474,6 @@ */ int GetNumCores(); -/** - * .. and a wrapper that just calls func once - */ -template void TraceThread(const char *name, Callable func) { - util::ThreadRename(name); - try { - LogPrintf("%s thread start\n", name); - func(); - LogPrintf("%s thread exit\n", name); - } catch (const std::exception &e) { - PrintExceptionContinue(&e, name); - throw; - } catch (...) { - PrintExceptionContinue(nullptr, name); - throw; - } -} - std::string CopyrightHolders(const std::string &strPrefix); /** diff --git a/src/util/thread.h b/src/util/thread.h new file mode 100644 --- /dev/null +++ b/src/util/thread.h @@ -0,0 +1,18 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_THREAD_H +#define BITCOIN_UTIL_THREAD_H + +#include + +namespace util { +/** + * A wrapper for do-something-once thread functions. + */ +void TraceThread(const char *thread_name, std::function thread_func); + +} // namespace util + +#endif // BITCOIN_UTIL_THREAD_H diff --git a/src/util/thread.cpp b/src/util/thread.cpp new file mode 100644 --- /dev/null +++ b/src/util/thread.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2021 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include +#include + +#include + +void util::TraceThread(const char *thread_name, + std::function thread_func) { + util::ThreadRename(thread_name); + try { + LogPrintf("%s thread start\n", thread_name); + thread_func(); + LogPrintf("%s thread exit\n", thread_name); + } catch (const std::exception &e) { + PrintExceptionContinue(&e, thread_name); + throw; + } catch (...) { + PrintExceptionContinue(nullptr, thread_name); + throw; + } +}