Skip to content

Commit cd9615a

Browse files
committed
[core] Added SharedLock to srt::sync.
Added srt::sync::ExclusiveLock. Added srt::sync::CSharedObjectPtr.
1 parent 77eed81 commit cd9615a

File tree

2 files changed

+123
-52
lines changed

2 files changed

+123
-52
lines changed

srtcore/sync.h

Lines changed: 123 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -343,15 +343,19 @@ class SRT_ATTR_CAPABILITY("mutex") Mutex
343343
pthread_mutex_t m_mutex;
344344
};
345345

346-
/// A pthread version of std::chrono::scoped_lock<mutex> (or lock_guard for C++11)
346+
/// A pthread version of std::scoped_lock (or lock_guard for C++11).
347347
class SRT_ATTR_SCOPED_CAPABILITY ScopedLock
348348
{
349349
public:
350350
SRT_ATTR_ACQUIRE(m)
351-
explicit ScopedLock(Mutex& m);
351+
explicit ScopedLock(Mutex& m)
352+
: m_mutex(m)
353+
{
354+
m_mutex.lock();
355+
}
352356

353357
SRT_ATTR_RELEASE()
354-
~ScopedLock();
358+
~ScopedLock() { m_mutex.unlock(); }
355359

356360
private:
357361
Mutex& m_mutex;
@@ -481,6 +485,122 @@ class Condition
481485
inline void setupCond(Condition& cv, const char*) { cv.init(); }
482486
inline void releaseCond(Condition& cv) { cv.destroy(); }
483487

488+
///////////////////////////////////////////////////////////////////////////////
489+
//
490+
// Shared Mutex section
491+
//
492+
///////////////////////////////////////////////////////////////////////////////
493+
494+
/// Implementation of a read-write mutex.
495+
/// This allows multiple readers at a time, or a single writer.
496+
/// TODO: The class can be improved if needed to give writer a preference
497+
/// by adding additional m_iWritersWaiting member variable (counter).
498+
/// TODO: The m_iCountRead could be made atomic to make unlok_shared() faster and lock-free.
499+
class SharedMutex
500+
{
501+
public:
502+
SharedMutex();
503+
~SharedMutex();
504+
505+
public:
506+
/// Acquire the lock for writting purposes. Only one thread can acquire this lock at a time
507+
/// Once it is locked, no reader can acquire it
508+
void lock();
509+
bool try_lock();
510+
void unlock();
511+
512+
/// Acquire the lock if no writter already has it. For read purpose only
513+
/// Several readers can lock this at the same time.
514+
void lock_shared();
515+
bool try_lock_shared();
516+
void unlock_shared();
517+
518+
int getReaderCount() const;
519+
520+
protected:
521+
Condition m_LockWriteCond;
522+
Condition m_LockReadCond;
523+
524+
mutable Mutex m_Mutex;
525+
526+
int m_iCountRead;
527+
bool m_bWriterLocked;
528+
};
529+
530+
/// A version of std::scoped_lock<std::shared_mutex> (or lock_guard for C++11).
531+
/// We could have used the srt::sync::ScopedLock making it a template-based class.
532+
/// But in that case all usages would have to be specificed like ScopedLock<Mutex> in C++03.
533+
class SRT_ATTR_SCOPED_CAPABILITY ExclusiveLock
534+
{
535+
public:
536+
SRT_ATTR_ACQUIRE(m)
537+
explicit ExclusiveLock(SharedMutex& m)
538+
: m_mutex(m)
539+
{
540+
m_mutex.lock();
541+
}
542+
543+
SRT_ATTR_RELEASE()
544+
~ExclusiveLock() { m_mutex.unlock(); }
545+
546+
private:
547+
SharedMutex& m_mutex;
548+
};
549+
550+
/// A reduced implementation of the std::shared_lock functionality (available in C++14).
551+
class SRT_ATTR_SCOPED_CAPABILITY SharedLock
552+
{
553+
public:
554+
SRT_ATTR_ACQUIRE_SHARED(m)
555+
explicit SharedLock(SharedMutex& m)
556+
: m_mtx(m)
557+
{
558+
m_mtx.lock_shared();
559+
}
560+
561+
SRT_ATTR_RELEASE_SHARED(m_mtx)
562+
~SharedLock() { m_mtx.unlock_shared(); }
563+
564+
private:
565+
SharedMutex& m_mtx;
566+
};
567+
568+
/// A class template for a shared object. It is a wrapper around a pointer to an object
569+
/// and a shared mutex. It allows multiple readers to access the object at the same time,
570+
/// but only one writer can access the object at a time.
571+
template <class T>
572+
class CSharedObjectPtr : public SharedMutex
573+
{
574+
public:
575+
CSharedObjectPtr<T>()
576+
: m_pObj(NULL)
577+
{
578+
}
579+
580+
bool set(T* pObj)
581+
{
582+
ExclusiveLock lock(*this);
583+
if (m_pObj)
584+
return false;
585+
m_pObj = pObj;
586+
return true;
587+
}
588+
589+
bool clearIf(const T* pObj)
590+
{
591+
ExclusiveLock lock(*this);
592+
if (m_pObj != pObj)
593+
return false;
594+
m_pObj = NULL;
595+
return true;
596+
}
597+
598+
T* getPtrNoLock() const { return m_pObj; }
599+
600+
private:
601+
T* m_pObj;
602+
};
603+
484604
///////////////////////////////////////////////////////////////////////////////
485605
//
486606
// Event (CV) section
@@ -943,43 +1063,6 @@ CUDTException& GetThreadLocalError();
9431063
/// @param[in] maxVal maximum allowed value of the resulting random number.
9441064
int genRandomInt(int minVal, int maxVal);
9451065

946-
947-
/// Implementation of a read-write mutex.
948-
/// This allows multiple readers at a time, or a single writer.
949-
/// TODO: The class can be improved if needed to give writer a preference
950-
/// by adding additional m_iWritersWaiting member variable (counter).
951-
/// TODO: The m_iCountRead could be made atomic to make unlok_shared() faster and lock-free.
952-
class SharedMutex
953-
{
954-
public:
955-
SharedMutex();
956-
~SharedMutex();
957-
958-
private:
959-
Condition m_LockWriteCond;
960-
Condition m_LockReadCond;
961-
962-
mutable Mutex m_Mutex;
963-
964-
int m_iCountRead;
965-
bool m_bWriterLocked;
966-
967-
/// Acquire the lock for writting purposes. Only one thread can acquire this lock at a time
968-
/// Once it is locked, no reader can acquire it
969-
public:
970-
void lock();
971-
bool try_lock();
972-
void unlock();
973-
974-
/// Acquire the lock if no writter already has it. For read purpose only
975-
/// Several readers can lock this at the same time.
976-
void lock_shared();
977-
bool try_lock_shared();
978-
void unlock_shared();
979-
980-
int getReaderCount() const;
981-
};
982-
9831066
} // namespace sync
9841067
} // namespace srt
9851068

srtcore/sync_posix.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -230,18 +230,6 @@ bool srt::sync::Mutex::try_lock()
230230
return (pthread_mutex_trylock(&m_mutex) == 0);
231231
}
232232

233-
srt::sync::ScopedLock::ScopedLock(Mutex& m)
234-
: m_mutex(m)
235-
{
236-
m_mutex.lock();
237-
}
238-
239-
srt::sync::ScopedLock::~ScopedLock()
240-
{
241-
m_mutex.unlock();
242-
}
243-
244-
245233
srt::sync::UniqueLock::UniqueLock(Mutex& m)
246234
: m_Mutex(m)
247235
{

0 commit comments

Comments
 (0)