150 lines
3.8 KiB
C++
150 lines
3.8 KiB
C++
/******************************************************************************/
|
|
/* THREADING ******************************************************************/
|
|
/******************************************************************************/
|
|
|
|
#ifndef _H_LW_LIB_THREADING
|
|
#define _H_LW_LIB_THREADING
|
|
|
|
#include <lw/lib/Pointers.hh>
|
|
#include <lw/lib/Arrays.hh>
|
|
namespace lw {
|
|
|
|
|
|
/*= ALIASES ==================================================================*/
|
|
|
|
using T_Mutex = std::mutex;
|
|
using T_ScopeLock = std::lock_guard< std::mutex >;
|
|
using T_ExclusiveLock = std::unique_lock< std::mutex >;
|
|
using T_Condition = std::condition_variable;
|
|
using T_Thread = std::thread;
|
|
|
|
M_CLASS_POINTERS( Mutex );
|
|
M_CLASS_POINTERS( ExclusiveLock );
|
|
M_CLASS_POINTERS( Condition );
|
|
M_CLASS_POINTERS( Thread );
|
|
|
|
|
|
/*= READ/WRITE LOCKING =======================================================*/
|
|
|
|
// A mutex that supports multiple readers and one writer. Based on the
|
|
// implementation from G++ 6's standard library.
|
|
class T_ReadWriteMutex
|
|
{
|
|
private:
|
|
static constexpr uint32_t C_WLOCKED_ = 1 << 31;
|
|
static constexpr uint32_t C_READERS_ = ~C_WLOCKED_;
|
|
|
|
T_Mutex mutex_;
|
|
T_Condition readerBlock_;
|
|
T_Condition writerBlock_;
|
|
uint32_t state_;
|
|
|
|
public:
|
|
T_ReadWriteMutex( );
|
|
T_ReadWriteMutex( T_ReadWriteMutex const& ) = delete;
|
|
T_ReadWriteMutex( T_ReadWriteMutex&& ) = default;
|
|
~T_ReadWriteMutex( );
|
|
|
|
T_ReadWriteMutex& operator=( T_ReadWriteMutex const& ) = delete;
|
|
T_ReadWriteMutex& operator=( T_ReadWriteMutex&& ) = default;
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Write lock
|
|
void lock( );
|
|
bool try_lock( );
|
|
void unlock( );
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
// Read lock
|
|
void lock_shared( );
|
|
bool try_lock_shared( );
|
|
void unlock_shared( );
|
|
|
|
// ---------------------------------------------------------------------
|
|
|
|
void upgradeLock( );
|
|
};
|
|
M_CLASS_POINTERS( ReadWriteMutex );
|
|
|
|
|
|
// Write lock / scoped write lock aliases
|
|
using T_WriteLock = std::unique_lock< T_ReadWriteMutex >;
|
|
using T_ScopeWriteLock = std::lock_guard< T_ReadWriteMutex >;
|
|
M_CLASS_POINTERS( WriteLock );
|
|
|
|
|
|
// Read lock based on std::shared_lock, but that can be
|
|
// upgraded to a write lock without releasing
|
|
class T_ReadLock : public std::shared_lock< T_ReadWriteMutex >
|
|
{
|
|
public:
|
|
T_ReadLock( ) noexcept;
|
|
T_ReadLock( T_ReadLock&& other );
|
|
explicit T_ReadLock( T_ReadWriteMutex& m );
|
|
T_ReadLock( T_ReadWriteMutex& m , std::defer_lock_t t );
|
|
T_ReadLock( T_ReadWriteMutex& m , std::try_to_lock_t t );
|
|
T_ReadLock( T_ReadWriteMutex& m , std::adopt_lock_t t );
|
|
|
|
T_WriteLock upgrade( );
|
|
};
|
|
M_CLASS_POINTERS( ReadLock );
|
|
|
|
|
|
/*= RING BUFFER ==============================================================*/
|
|
|
|
template< typename ElementType >
|
|
class T_RingBuffer
|
|
{
|
|
private:
|
|
typedef T_RingBuffer< ElementType > T_Self;
|
|
|
|
uint32_t expand_;
|
|
ElementType * data_;
|
|
uint32_t allocated_;
|
|
uint32_t used_;
|
|
uint32_t readPos_;
|
|
|
|
public:
|
|
M_TEMPLATE_POINTERS( T_Self );
|
|
|
|
explicit T_RingBuffer( uint32_t expand = 64 );
|
|
|
|
T_RingBuffer( T_Self const& other );
|
|
T_RingBuffer( T_Self&& other ) noexcept;
|
|
|
|
~T_RingBuffer( );
|
|
|
|
T_Self& operator=( T_Self const& other );
|
|
T_Self& operator=( T_Self&& other ) noexcept;
|
|
|
|
template< typename T >
|
|
friend void swap( T_RingBuffer< T >& lhs , T_RingBuffer< T >& rhs ) noexcept;
|
|
|
|
void free( );
|
|
|
|
uint32_t size( ) const;
|
|
uint32_t capacity( ) const;
|
|
uint32_t growth( ) const;
|
|
|
|
bool readNext( ElementType& output );
|
|
bool readAll( T_Array< ElementType >& output );
|
|
|
|
void put( ElementType const& input );
|
|
void put( ElementType&& input );
|
|
|
|
template< typename... ArgTypes >
|
|
void putNew( ArgTypes&&... arguments );
|
|
|
|
private:
|
|
void expand( );
|
|
};
|
|
|
|
template< typename T >
|
|
void swap( T_RingBuffer< T >& lhs , T_RingBuffer< T >& rhs ) noexcept;
|
|
|
|
|
|
}
|
|
#endif // _H_LW_LIB_THREADING
|
|
#include <lw/lib/inline/Threading.hh>
|