Skip to content

Commit

Permalink
[core] Added SharedLock to srt::sync.
Browse files Browse the repository at this point in the history
Added srt::sync::ExclusiveLock.
Added srt::sync::CSharedObjectPtr.
  • Loading branch information
maxsharabayko committed Aug 7, 2024
1 parent 77eed81 commit cd9615a
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 52 deletions.
163 changes: 123 additions & 40 deletions srtcore/sync.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,15 +343,19 @@ class SRT_ATTR_CAPABILITY("mutex") Mutex
pthread_mutex_t m_mutex;
};

/// A pthread version of std::chrono::scoped_lock<mutex> (or lock_guard for C++11)
/// A pthread version of std::scoped_lock (or lock_guard for C++11).
class SRT_ATTR_SCOPED_CAPABILITY ScopedLock
{
public:
SRT_ATTR_ACQUIRE(m)
explicit ScopedLock(Mutex& m);
explicit ScopedLock(Mutex& m)
: m_mutex(m)
{
m_mutex.lock();
}

SRT_ATTR_RELEASE()
~ScopedLock();
~ScopedLock() { m_mutex.unlock(); }

private:
Mutex& m_mutex;
Expand Down Expand Up @@ -481,6 +485,122 @@ class Condition
inline void setupCond(Condition& cv, const char*) { cv.init(); }
inline void releaseCond(Condition& cv) { cv.destroy(); }

///////////////////////////////////////////////////////////////////////////////
//
// Shared Mutex section
//
///////////////////////////////////////////////////////////////////////////////

/// Implementation of a read-write mutex.
/// This allows multiple readers at a time, or a single writer.
/// TODO: The class can be improved if needed to give writer a preference
/// by adding additional m_iWritersWaiting member variable (counter).
/// TODO: The m_iCountRead could be made atomic to make unlok_shared() faster and lock-free.
class SharedMutex
{
public:
SharedMutex();
~SharedMutex();

public:
/// Acquire the lock for writting purposes. Only one thread can acquire this lock at a time
/// Once it is locked, no reader can acquire it
void lock();
bool try_lock();
void unlock();

/// Acquire the lock if no writter already has it. For read purpose only
/// Several readers can lock this at the same time.
void lock_shared();
bool try_lock_shared();
void unlock_shared();

int getReaderCount() const;

protected:
Condition m_LockWriteCond;
Condition m_LockReadCond;

mutable Mutex m_Mutex;

int m_iCountRead;
bool m_bWriterLocked;
};

/// A version of std::scoped_lock<std::shared_mutex> (or lock_guard for C++11).
/// We could have used the srt::sync::ScopedLock making it a template-based class.
/// But in that case all usages would have to be specificed like ScopedLock<Mutex> in C++03.
class SRT_ATTR_SCOPED_CAPABILITY ExclusiveLock
{
public:
SRT_ATTR_ACQUIRE(m)
explicit ExclusiveLock(SharedMutex& m)
: m_mutex(m)
{
m_mutex.lock();
}

SRT_ATTR_RELEASE()
~ExclusiveLock() { m_mutex.unlock(); }

private:
SharedMutex& m_mutex;
};

/// A reduced implementation of the std::shared_lock functionality (available in C++14).
class SRT_ATTR_SCOPED_CAPABILITY SharedLock
{
public:
SRT_ATTR_ACQUIRE_SHARED(m)
explicit SharedLock(SharedMutex& m)
: m_mtx(m)
{
m_mtx.lock_shared();
}

SRT_ATTR_RELEASE_SHARED(m_mtx)
~SharedLock() { m_mtx.unlock_shared(); }

private:
SharedMutex& m_mtx;
};

/// A class template for a shared object. It is a wrapper around a pointer to an object
/// and a shared mutex. It allows multiple readers to access the object at the same time,
/// but only one writer can access the object at a time.
template <class T>
class CSharedObjectPtr : public SharedMutex
{
public:
CSharedObjectPtr<T>()
: m_pObj(NULL)
{
}

bool set(T* pObj)
{
ExclusiveLock lock(*this);
if (m_pObj)
return false;
m_pObj = pObj;
return true;
}

bool clearIf(const T* pObj)
{
ExclusiveLock lock(*this);
if (m_pObj != pObj)
return false;
m_pObj = NULL;
return true;
}

T* getPtrNoLock() const { return m_pObj; }

private:
T* m_pObj;
};

///////////////////////////////////////////////////////////////////////////////
//
// Event (CV) section
Expand Down Expand Up @@ -943,43 +1063,6 @@ CUDTException& GetThreadLocalError();
/// @param[in] maxVal maximum allowed value of the resulting random number.
int genRandomInt(int minVal, int maxVal);


/// Implementation of a read-write mutex.
/// This allows multiple readers at a time, or a single writer.
/// TODO: The class can be improved if needed to give writer a preference
/// by adding additional m_iWritersWaiting member variable (counter).
/// TODO: The m_iCountRead could be made atomic to make unlok_shared() faster and lock-free.
class SharedMutex
{
public:
SharedMutex();
~SharedMutex();

private:
Condition m_LockWriteCond;
Condition m_LockReadCond;

mutable Mutex m_Mutex;

int m_iCountRead;
bool m_bWriterLocked;

/// Acquire the lock for writting purposes. Only one thread can acquire this lock at a time
/// Once it is locked, no reader can acquire it
public:
void lock();
bool try_lock();
void unlock();

/// Acquire the lock if no writter already has it. For read purpose only
/// Several readers can lock this at the same time.
void lock_shared();
bool try_lock_shared();
void unlock_shared();

int getReaderCount() const;
};

} // namespace sync
} // namespace srt

Expand Down
12 changes: 0 additions & 12 deletions srtcore/sync_posix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,18 +230,6 @@ bool srt::sync::Mutex::try_lock()
return (pthread_mutex_trylock(&m_mutex) == 0);
}

srt::sync::ScopedLock::ScopedLock(Mutex& m)
: m_mutex(m)
{
m_mutex.lock();
}

srt::sync::ScopedLock::~ScopedLock()
{
m_mutex.unlock();
}


srt::sync::UniqueLock::UniqueLock(Mutex& m)
: m_Mutex(m)
{
Expand Down

0 comments on commit cd9615a

Please sign in to comment.