Skip to content

Commit 80cc1a9

Browse files
committed
Annotate Peer class
1 parent 712f3f3 commit 80cc1a9

File tree

5 files changed

+60
-35
lines changed

5 files changed

+60
-35
lines changed

src/overlay/Hmac.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55
// of this distribution or at http://www.apache.org/licenses/LICENSE-2.0
66

77
#include "Tracy.hpp"
8+
#include "util/ThreadAnnotations.h"
89
#include "xdr/Stellar-overlay.h"
910
#include "xdr/Stellar-types.h"
10-
#include <mutex>
1111

1212
using namespace stellar;
1313

1414
class Hmac
1515
{
1616
#ifndef USE_TRACY
17-
std::mutex mMutex;
17+
Mutex mMutex;
1818
#else
1919
TracyLockable(std::mutex, mMutex);
2020
#endif

src/overlay/Peer.h

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "overlay/PeerBareAddress.h"
1414
#include "transactions/TransactionFrameBase.h"
1515
#include "util/NonCopyable.h"
16+
#include "util/ThreadAnnotations.h"
1617
#include "util/Timer.h"
1718
#include "xdrpp/message.h"
1819
#include <medida/counter.h>
@@ -187,13 +188,16 @@ class Peer : public std::enable_shared_from_this<Peer>,
187188

188189
PeerRole const mRole;
189190
OverlayMetrics& mOverlayMetrics;
191+
// No need for GUARDED_BY, PeerMettrics is thread-safe
190192
PeerMetrics mPeerMetrics;
191-
std::string mDropReason;
193+
#ifdef BUILD_TESTS
194+
std::string mDropReason GUARDED_BY(mStateMutex);
195+
#endif
192196

193197
// Mutex to protect PeerState, which can be accessed and modified from
194198
// multiple threads
195199
#ifndef USE_TRACY
196-
std::recursive_mutex mutable mStateMutex;
200+
RecursiveMutex mutable mStateMutex;
197201
#else
198202
mutable TracyLockable(std::recursive_mutex, mStateMutex);
199203
#endif
@@ -217,10 +221,12 @@ class Peer : public std::enable_shared_from_this<Peer>,
217221
// they all take a LockGuard that should be holding mStateMutex,
218222
// but do not lock that mutex themselves (to allow atomic
219223
// read-modify-write cycles or similar patterns in callers).
220-
bool shouldAbort(RecursiveLockGuard const& stateGuard) const;
221-
void setState(RecursiveLockGuard const& stateGuard, PeerState newState);
224+
bool shouldAbort(RecursiveLockGuard const& stateGuard) const
225+
REQUIRES(mStateMutex);
226+
void setState(RecursiveLockGuard const& stateGuard, PeerState newState)
227+
REQUIRES(mStateMutex);
222228
PeerState
223-
getState(RecursiveLockGuard const& stateGuard) const
229+
getState(RecursiveLockGuard const& stateGuard) const REQUIRES(mStateMutex)
224230
{
225231
return mState;
226232
}
@@ -248,7 +254,7 @@ class Peer : public std::enable_shared_from_this<Peer>,
248254
// IOW, all methods using these private variables and functions below must
249255
// synchronize access manually
250256
private:
251-
PeerState mState;
257+
PeerState mState GUARDED_BY(mStateMutex);
252258
NodeID mPeerID;
253259
uint256 mSendNonce;
254260
uint256 mRecvNonce;
@@ -424,8 +430,10 @@ class Peer : public std::enable_shared_from_this<Peer>,
424430

425431
/* The following functions can be called from background thread, so they
426432
* must be thread-safe */
427-
bool isConnected(RecursiveLockGuard const& stateGuard) const;
428-
bool isAuthenticated(RecursiveLockGuard const& stateGuard) const;
433+
bool isConnected(RecursiveLockGuard const& stateGuard) const
434+
REQUIRES(mStateMutex);
435+
bool isAuthenticated(RecursiveLockGuard const& stateGuard) const
436+
REQUIRES(mStateMutex);
429437

430438
PeerMetrics&
431439
getPeerMetrics()

src/overlay/test/LoopbackPeer.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ namespace stellar
2222
// pair of them wrapped in a LoopbackPeerConnection that explicitly manages the
2323
// lifecycle of the connection.
2424

25+
// This class is not thread-safe and is not meant to utilize multi-threading. It
26+
// is only safe to call its methods from the main thread.
2527
class LoopbackPeer : public Peer
2628
{
2729
private:
@@ -57,7 +59,7 @@ class LoopbackPeer : public Peer
5759
std::shared_ptr<StellarMessage const> msg) override;
5860
AuthCert getAuthCert() override;
5961

60-
void processInQueue();
62+
void processInQueue() NO_THREAD_SAFETY_ANALYSIS;
6163
void recvMessage(xdr::msg_ptr const& xdrBytes);
6264

6365
public:
@@ -70,11 +72,12 @@ class LoopbackPeer : public Peer
7072

7173
static std::pair<std::shared_ptr<LoopbackPeer>,
7274
std::shared_ptr<LoopbackPeer>>
73-
initiate(Application& app, Application& otherApp);
75+
initiate(Application& app, Application& otherApp) NO_THREAD_SAFETY_ANALYSIS;
7476

75-
void drop(std::string const& reason, DropDirection dropDirection) override;
77+
void drop(std::string const& reason,
78+
DropDirection dropDirection) NO_THREAD_SAFETY_ANALYSIS override;
7679

77-
void deliverOne();
80+
void deliverOne() NO_THREAD_SAFETY_ANALYSIS;
7881
void deliverAll();
7982
void dropAll();
8083
size_t getBytesQueued() const;

src/util/GlobalChecks.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#pragma once
66

7+
#include "util/ThreadAnnotations.h"
78
#include <Tracy.hpp>
89
#include <mutex>
910

@@ -46,8 +47,8 @@ void dbgAbort();
4647
#endif
4748

4849
#ifndef USE_TRACY
49-
using RecursiveLockGuard = std::lock_guard<std::recursive_mutex>;
50-
using LockGuard = std::lock_guard<std::mutex>;
50+
using RecursiveLockGuard = RecursiveMutexLocker;
51+
using LockGuard = MutexLocker;
5152
#else
5253
using RecursiveLockGuard = std::lock_guard<LockableBase(std::recursive_mutex)>;
5354
using LockGuard = std::lock_guard<LockableBase(std::mutex)>;

src/util/ThreadAnnotations.h

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -157,17 +157,17 @@ class LOCKABLE Mutex
157157

158158
// MutexLocker is an RAII class that acquires a mutex in its constructor, and
159159
// releases it in its destructor.
160-
class SCOPED_LOCKABLE MutexLocker
160+
template <typename MutexType> class SCOPED_LOCKABLE MutexLockerT
161161
{
162162
private:
163-
Mutex& mut;
163+
MutexType& mut;
164164

165165
public:
166-
MutexLocker(Mutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mut(mu)
166+
MutexLockerT(MutexType& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mut(mu)
167167
{
168168
mu.Lock();
169169
}
170-
~MutexLocker() UNLOCK_FUNCTION()
170+
~MutexLockerT() UNLOCK_FUNCTION()
171171
{
172172
mut.Unlock();
173173
}
@@ -213,40 +213,53 @@ class LOCKABLE SharedMutex
213213
}
214214
};
215215

216-
// SharedLockExclusive is an RAII class that acquires a shared mutex in
217-
// exclusive mode in its constructor, and releases it in its destructor.
218-
class SCOPED_LOCKABLE SharedLockExclusive
216+
// SharedLockShared is an RAII class that acquires a shared mutex in shared
217+
// mode in its constructor, and releases it in its destructor.
218+
class SCOPED_LOCKABLE SharedLockShared
219219
{
220220
private:
221221
SharedMutex& mut;
222222

223223
public:
224-
SharedLockExclusive(SharedMutex& mu) EXCLUSIVE_LOCK_FUNCTION(mu) : mut(mu)
224+
SharedLockShared(SharedMutex& mu) SHARED_LOCK_FUNCTION(mu) : mut(mu)
225225
{
226-
mu.Lock();
226+
mu.LockShared();
227227
}
228-
~SharedLockExclusive() UNLOCK_FUNCTION()
228+
~SharedLockShared() UNLOCK_FUNCTION()
229229
{
230-
mut.Unlock();
230+
mut.UnlockShared();
231231
}
232232
};
233233

234-
// SharedLockShared is an RAII class that acquires a shared mutex in shared
235-
// mode in its constructor, and releases it in its destructor.
236-
class SCOPED_LOCKABLE SharedLockShared
234+
// Defines an annotated interface for recursive mutexes.
235+
// These methods can be implemented to use any internal recursive_mutex
236+
// implementation.
237+
class LOCKABLE RecursiveMutex
237238
{
238239
private:
239-
SharedMutex& mut;
240+
std::recursive_mutex mRecursiveMutex;
240241

241242
public:
242-
SharedLockShared(SharedMutex& mu) SHARED_LOCK_FUNCTION(mu) : mut(mu)
243+
// Acquire/lock this mutex exclusively. The same thread may acquire the
244+
// mutex multiple times without blocking. The owning thread must release the
245+
// mutex the same number of times it was acquired.
246+
void
247+
Lock() EXCLUSIVE_LOCK_FUNCTION()
243248
{
244-
mu.LockShared();
249+
mRecursiveMutex.lock();
245250
}
246-
~SharedLockShared() UNLOCK_FUNCTION()
251+
252+
// Release/unlock the mutex. Only the owning thread can release the mutex,
253+
// and the mutex must be released as many times as it was acquired.
254+
void
255+
Unlock() UNLOCK_FUNCTION()
247256
{
248-
mut.UnlockShared();
257+
mRecursiveMutex.unlock();
249258
}
250259
};
251260

261+
using MutexLocker = MutexLockerT<Mutex>;
262+
using RecursiveMutexLocker = MutexLockerT<RecursiveMutex>;
263+
using SharedLockExclusive = MutexLockerT<SharedMutex>;
264+
252265
#endif // THREAD_ANNOTATIONS_H_

0 commit comments

Comments
 (0)