corelib/include/ebcl/Threading.hh

150 lines
3.8 KiB
C++

/******************************************************************************/
/* THREADING ******************************************************************/
/******************************************************************************/
#ifndef _H_EBCL_THREADING
#define _H_EBCL_THREADING
#include <ebcl/Pointers.hh>
#include <ebcl/Arrays.hh>
namespace ebcl {
/*= 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_EBCL_THREADING
#include <ebcl/inline/Threading.hh>