mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-13 11:25:02 -05:00
sync: modernize CSemaphore / CSemaphoreGrant
This commit is contained in:
parent
c73cd42363
commit
4d265d0342
4 changed files with 66 additions and 36 deletions
23
src/net.cpp
23
src/net.cpp
|
@ -1862,7 +1862,7 @@ bool CConnman::AddConnection(const std::string& address, ConnectionType conn_typ
|
||||||
CSemaphoreGrant grant(*semOutbound, true);
|
CSemaphoreGrant grant(*semOutbound, true);
|
||||||
if (!grant) return false;
|
if (!grant) return false;
|
||||||
|
|
||||||
OpenNetworkConnection(CAddress(), false, &grant, address.c_str(), conn_type, /*use_v2transport=*/false);
|
OpenNetworkConnection(CAddress(), false, std::move(grant), address.c_str(), conn_type, /*use_v2transport=*/false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2294,9 +2294,9 @@ void CConnman::ProcessAddrFetch()
|
||||||
m_addr_fetches.pop_front();
|
m_addr_fetches.pop_front();
|
||||||
}
|
}
|
||||||
CAddress addr;
|
CAddress addr;
|
||||||
CSemaphoreGrant grant(*semOutbound, true);
|
CSemaphoreGrant grant(*semOutbound, /*fTry=*/true);
|
||||||
if (grant) {
|
if (grant) {
|
||||||
OpenNetworkConnection(addr, false, &grant, strDest.c_str(), ConnectionType::ADDR_FETCH, /*use_v2transport=*/false);
|
OpenNetworkConnection(addr, false, std::move(grant), strDest.c_str(), ConnectionType::ADDR_FETCH, /*use_v2transport=*/false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2398,7 +2398,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
|
||||||
for (const std::string& strAddr : connect)
|
for (const std::string& strAddr : connect)
|
||||||
{
|
{
|
||||||
CAddress addr(CService(), NODE_NONE);
|
CAddress addr(CService(), NODE_NONE);
|
||||||
OpenNetworkConnection(addr, false, nullptr, strAddr.c_str(), ConnectionType::MANUAL, /*use_v2transport=*/false);
|
OpenNetworkConnection(addr, false, {}, strAddr.c_str(), ConnectionType::MANUAL, /*use_v2transport=*/false);
|
||||||
for (int i = 0; i < 10 && i < nLoop; i++)
|
for (int i = 0; i < 10 && i < nLoop; i++)
|
||||||
{
|
{
|
||||||
if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
|
if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
|
||||||
|
@ -2703,7 +2703,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
|
||||||
const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(nMaxConnections - 1, 2)};
|
const bool count_failures{((int)outbound_ipv46_peer_netgroups.size() + outbound_privacy_network_peers) >= std::min(nMaxConnections - 1, 2)};
|
||||||
// Use BIP324 transport when both us and them have NODE_V2_P2P set.
|
// Use BIP324 transport when both us and them have NODE_V2_P2P set.
|
||||||
const bool use_v2transport(addrConnect.nServices & GetLocalServices() & NODE_P2P_V2);
|
const bool use_v2transport(addrConnect.nServices & GetLocalServices() & NODE_P2P_V2);
|
||||||
OpenNetworkConnection(addrConnect, count_failures, &grant, /*strDest=*/nullptr, conn_type, use_v2transport);
|
OpenNetworkConnection(addrConnect, count_failures, std::move(grant), /*strDest=*/nullptr, conn_type, use_v2transport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2785,16 +2785,16 @@ void CConnman::ThreadOpenAddedConnections()
|
||||||
bool tried = false;
|
bool tried = false;
|
||||||
for (const AddedNodeInfo& info : vInfo) {
|
for (const AddedNodeInfo& info : vInfo) {
|
||||||
if (!info.fConnected) {
|
if (!info.fConnected) {
|
||||||
if (!grant.TryAcquire()) {
|
if (!grant) {
|
||||||
// If we've used up our semaphore and need a new one, let's not wait here since while we are waiting
|
// If we've used up our semaphore and need a new one, let's not wait here since while we are waiting
|
||||||
// the addednodeinfo state might change.
|
// the addednodeinfo state might change.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tried = true;
|
tried = true;
|
||||||
CAddress addr(CService(), NODE_NONE);
|
CAddress addr(CService(), NODE_NONE);
|
||||||
OpenNetworkConnection(addr, false, &grant, info.m_params.m_added_node.c_str(), ConnectionType::MANUAL, info.m_params.m_use_v2transport);
|
OpenNetworkConnection(addr, false, std::move(grant), info.m_params.m_added_node.c_str(), ConnectionType::MANUAL, info.m_params.m_use_v2transport);
|
||||||
if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
|
if (!interruptNet.sleep_for(std::chrono::milliseconds(500))) return;
|
||||||
return;
|
grant = CSemaphoreGrant(*semAddnode, /*fTry=*/true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Retry every 60 seconds if a connection was attempted, otherwise two seconds
|
// Retry every 60 seconds if a connection was attempted, otherwise two seconds
|
||||||
|
@ -2804,7 +2804,7 @@ void CConnman::ThreadOpenAddedConnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
// if successful, this moves the passed grant to the constructed node
|
// if successful, this moves the passed grant to the constructed node
|
||||||
void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, ConnectionType conn_type, bool use_v2transport)
|
void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant&& grant_outbound, const char *pszDest, ConnectionType conn_type, bool use_v2transport)
|
||||||
{
|
{
|
||||||
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
|
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
|
||||||
assert(conn_type != ConnectionType::INBOUND);
|
assert(conn_type != ConnectionType::INBOUND);
|
||||||
|
@ -2830,8 +2830,7 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
|
||||||
|
|
||||||
if (!pnode)
|
if (!pnode)
|
||||||
return;
|
return;
|
||||||
if (grantOutbound)
|
pnode->grantOutbound = std::move(grant_outbound);
|
||||||
grantOutbound->MoveTo(pnode->grantOutbound);
|
|
||||||
|
|
||||||
m_msgproc->InitializeNode(*pnode, nLocalServices);
|
m_msgproc->InitializeNode(*pnode, nLocalServices);
|
||||||
{
|
{
|
||||||
|
|
|
@ -1107,7 +1107,7 @@ public:
|
||||||
bool GetNetworkActive() const { return fNetworkActive; };
|
bool GetNetworkActive() const { return fNetworkActive; };
|
||||||
bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; };
|
bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; };
|
||||||
void SetNetworkActive(bool active);
|
void SetNetworkActive(bool active);
|
||||||
void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant* grantOutbound, const char* strDest, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
|
void OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant&& grant_outbound, const char* strDest, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
|
||||||
bool CheckIncomingNonce(uint64_t nonce);
|
bool CheckIncomingNonce(uint64_t nonce);
|
||||||
|
|
||||||
// alias for thread safety annotations only, not defined
|
// alias for thread safety annotations only, not defined
|
||||||
|
|
|
@ -317,7 +317,7 @@ static RPCHelpMan addnode()
|
||||||
if (command == "onetry")
|
if (command == "onetry")
|
||||||
{
|
{
|
||||||
CAddress addr;
|
CAddress addr;
|
||||||
connman.OpenNetworkConnection(addr, /*fCountFailure=*/false, /*grantOutbound=*/nullptr, node_arg.c_str(), ConnectionType::MANUAL, use_v2transport);
|
connman.OpenNetworkConnection(addr, /*fCountFailure=*/false, /*grant_outbound=*/{}, node_arg.c_str(), ConnectionType::MANUAL, use_v2transport);
|
||||||
return UniValue::VNULL;
|
return UniValue::VNULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
75
src/sync.h
75
src/sync.h
|
@ -301,6 +301,10 @@ inline MutexType* MaybeCheckNotHeld(MutexType* m) LOCKS_EXCLUDED(m) LOCK_RETURNE
|
||||||
//! gcc and the -Wreturn-stack-address flag in clang, both enabled by default.
|
//! gcc and the -Wreturn-stack-address flag in clang, both enabled by default.
|
||||||
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
|
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
|
||||||
|
|
||||||
|
/** An implementation of a semaphore.
|
||||||
|
*
|
||||||
|
* See https://en.wikipedia.org/wiki/Semaphore_(programming)
|
||||||
|
*/
|
||||||
class CSemaphore
|
class CSemaphore
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -309,25 +313,33 @@ private:
|
||||||
int value;
|
int value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CSemaphore(int init) : value(init) {}
|
explicit CSemaphore(int init) noexcept : value(init) {}
|
||||||
|
|
||||||
void wait()
|
// Disallow default construct, copy, move.
|
||||||
|
CSemaphore() = delete;
|
||||||
|
CSemaphore(const CSemaphore&) = delete;
|
||||||
|
CSemaphore(CSemaphore&&) = delete;
|
||||||
|
CSemaphore& operator=(const CSemaphore&) = delete;
|
||||||
|
CSemaphore& operator=(CSemaphore&&) = delete;
|
||||||
|
|
||||||
|
void wait() noexcept
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(mutex);
|
std::unique_lock<std::mutex> lock(mutex);
|
||||||
condition.wait(lock, [&]() { return value >= 1; });
|
condition.wait(lock, [&]() { return value >= 1; });
|
||||||
value--;
|
value--;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool try_wait()
|
bool try_wait() noexcept
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
if (value < 1)
|
if (value < 1) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
value--;
|
value--;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void post()
|
void post() noexcept
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
@ -345,53 +357,72 @@ private:
|
||||||
bool fHaveGrant;
|
bool fHaveGrant;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Acquire()
|
void Acquire() noexcept
|
||||||
{
|
{
|
||||||
if (fHaveGrant)
|
if (fHaveGrant) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
sem->wait();
|
sem->wait();
|
||||||
fHaveGrant = true;
|
fHaveGrant = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Release()
|
void Release() noexcept
|
||||||
{
|
{
|
||||||
if (!fHaveGrant)
|
if (!fHaveGrant) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
sem->post();
|
sem->post();
|
||||||
fHaveGrant = false;
|
fHaveGrant = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TryAcquire()
|
bool TryAcquire() noexcept
|
||||||
{
|
{
|
||||||
if (!fHaveGrant && sem->try_wait())
|
if (!fHaveGrant && sem->try_wait()) {
|
||||||
fHaveGrant = true;
|
fHaveGrant = true;
|
||||||
|
}
|
||||||
return fHaveGrant;
|
return fHaveGrant;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MoveTo(CSemaphoreGrant& grant)
|
// Disallow copy.
|
||||||
|
CSemaphoreGrant(const CSemaphoreGrant&) = delete;
|
||||||
|
CSemaphoreGrant& operator=(const CSemaphoreGrant&) = delete;
|
||||||
|
|
||||||
|
// Allow move.
|
||||||
|
CSemaphoreGrant(CSemaphoreGrant&& other) noexcept
|
||||||
{
|
{
|
||||||
grant.Release();
|
sem = other.sem;
|
||||||
grant.sem = sem;
|
fHaveGrant = other.fHaveGrant;
|
||||||
grant.fHaveGrant = fHaveGrant;
|
other.fHaveGrant = false;
|
||||||
fHaveGrant = false;
|
other.sem = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSemaphoreGrant() : sem(nullptr), fHaveGrant(false) {}
|
CSemaphoreGrant& operator=(CSemaphoreGrant&& other) noexcept
|
||||||
|
|
||||||
explicit CSemaphoreGrant(CSemaphore& sema, bool fTry = false) : sem(&sema), fHaveGrant(false)
|
|
||||||
{
|
{
|
||||||
if (fTry)
|
Release();
|
||||||
|
sem = other.sem;
|
||||||
|
fHaveGrant = other.fHaveGrant;
|
||||||
|
other.fHaveGrant = false;
|
||||||
|
other.sem = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSemaphoreGrant() noexcept : sem(nullptr), fHaveGrant(false) {}
|
||||||
|
|
||||||
|
explicit CSemaphoreGrant(CSemaphore& sema, bool fTry = false) noexcept : sem(&sema), fHaveGrant(false)
|
||||||
|
{
|
||||||
|
if (fTry) {
|
||||||
TryAcquire();
|
TryAcquire();
|
||||||
else
|
} else {
|
||||||
Acquire();
|
Acquire();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~CSemaphoreGrant()
|
~CSemaphoreGrant()
|
||||||
{
|
{
|
||||||
Release();
|
Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
operator bool() const
|
explicit operator bool() const noexcept
|
||||||
{
|
{
|
||||||
return fHaveGrant;
|
return fHaveGrant;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue