e8f0fa2d27
- C3d aggiornamento delle librerie.
280 lines
12 KiB
C++
280 lines
12 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
\file
|
|
\brief \ru Системозависимые атомарные операции.
|
|
Если требуются атомарные операции, должен использоваться этот файл (<atomic> не использовать!!!).
|
|
\en System-dependent atomic operations.
|
|
If atomic operations are required, this file should used (<atomic> must not be used!!!).\~
|
|
*/
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#ifndef __SYSTEM_ATOMIC_H
|
|
#define __SYSTEM_ATOMIC_H
|
|
|
|
#include <system_types.h>
|
|
#include <system_cpp_standard.h>
|
|
#include <tool_mutex.h>
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Использование атомарных операций согласно стандарту C++11.
|
|
// \en Using atomic operations according to C++11 standard.
|
|
//
|
|
//---
|
|
|
|
#ifdef C3D_STANDARD_CXX_11_PARTIAL
|
|
#ifndef _NOT_USE_ATOMIC
|
|
#define C3D_USE_CXX11_ATOMIC
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef C3D_USE_CXX11_ATOMIC
|
|
|
|
#include <atomic>
|
|
|
|
typedef std::atomic_ptrdiff_t use_count_type; ///< \ru Потокобезопасный тип счётчика ссылок. \en Thread-safe references count type.
|
|
typedef std::atomic_size_t serial_type; ///< \ru Потокобезопасный тип счётчика ссылок. \en Thread-safe references count type.
|
|
typedef std::atomic_schar flag_type; ///< \ru Потокобезопасный тип флага. \en Thread-safe flag type.
|
|
typedef std::atomic<bool> atomic_bool; ///< \ru Потокобезопасный логический тип. \en Thread-safe boolean type.
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \ru Получить значение. \en Get value.
|
|
*/
|
|
//---
|
|
template <class AtomicType, class Type>
|
|
Type LoadTypeValue( const AtomicType & v ) {
|
|
return v.load();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \ru Установить значение. \en Get value.
|
|
*/
|
|
//---
|
|
template <class AtomicType>
|
|
void StoreTypeValue( const AtomicType & src, AtomicType & dst ) {
|
|
dst.store( src.load() );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \ru Установить значение. \en Get value.
|
|
*/
|
|
//---
|
|
template <class AtomicType, class Type>
|
|
void StoreTypeValue( const Type src, AtomicType & dst ) {
|
|
dst.store( src );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \ru Получить значение. \en Get value.
|
|
*/
|
|
//---
|
|
inline size_t SerialTypeValue( const serial_type & v ) {
|
|
return v.load();
|
|
}
|
|
inline ptrdiff_t UseCountValue( const use_count_type & v ) {
|
|
return v.load();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Шаблонный класс для перечислений (Type - тип перечисления).
|
|
// \en Template class for enums (Type - a type of enum).
|
|
//--
|
|
template< class Type >
|
|
class atomic_enum_type
|
|
{
|
|
use_count_type m_value;
|
|
|
|
public:
|
|
atomic_enum_type() :m_value (0) {}
|
|
atomic_enum_type( const Type & val ) : m_value (val) {}
|
|
atomic_enum_type( const atomic_enum_type<Type> & val ) : m_value( val.m_value.load() ) {}
|
|
|
|
// \ru Операторы присваивания. \en Assignment operators.
|
|
atomic_enum_type & operator = ( const atomic_enum_type & t ) { m_value.store( t.m_value.load() ); return *this; }
|
|
atomic_enum_type & operator = ( const Type & t ) { m_value.store( t ); return *this; }
|
|
|
|
// \ru Операторы сравнения. \en Comparison operators.
|
|
bool operator == ( const atomic_enum_type & t ) const { return m_value.load() == t.m_value.load(); }
|
|
bool operator == ( const Type & t ) const { return m_value.load() == t; }
|
|
bool operator != ( const atomic_enum_type & t ) const { return m_value.load() != t.m_value.load(); }
|
|
bool operator != ( const Type & t ) const { return m_value.load() != t; }
|
|
bool operator < ( const atomic_enum_type & t ) const { return m_value.load() < t.m_value.load(); }
|
|
bool operator < ( Type t ) const { return m_value.load() < t; }
|
|
bool operator > ( const atomic_enum_type & t ) const { return m_value.load() > t.m_value; }
|
|
bool operator > ( const Type & t ) const { return m_value.load() > t; }
|
|
bool operator <= ( const atomic_enum_type & t ) const { return m_value.load() <= t.m_value.load(); }
|
|
bool operator <= ( const Type & t ) const { return m_value.load() <= t; }
|
|
bool operator >= ( const atomic_enum_type & t ) const { return m_value.load() >= t.m_value.load(); }
|
|
bool operator >= ( const Type & t ) const { return m_value.load() >= t; }
|
|
|
|
// \ru Доступ к данным. \en Data access.
|
|
Type operator()() const { return static_cast<Type>( m_value.load() ); }
|
|
};
|
|
|
|
#else
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Шаблонный класс, работающий с целочисленными типами данных. Базовый класс для потокобезопасных счётчиков.
|
|
// \en Template class working with integer data types. Base class for thread-safe counters.
|
|
//--
|
|
template< class Type >
|
|
class atomic_itype
|
|
{
|
|
protected:
|
|
CommonMutex m_lock;
|
|
Type m_value;
|
|
public:
|
|
atomic_itype() {}
|
|
atomic_itype( const atomic_itype & t ) : m_value( t.m_value ) {}
|
|
atomic_itype( const Type & t ) : m_value( t ) {}
|
|
|
|
// \ru Операторы присваивания. \en Assignment operators.
|
|
atomic_itype & operator = ( const atomic_itype & t ) { ScopedLock l( &m_lock ); m_value = t.m_value; return *this; }
|
|
atomic_itype & operator = ( Type t ) { ScopedLock l( &m_lock ); m_value = t; return *this; }
|
|
|
|
// \ru Операторы инкремента и декремента. \en Increment and decrement operators.
|
|
atomic_itype & operator ++ () { ScopedLock l( &m_lock ); ++m_value; return *this; } // prefix ++
|
|
atomic_itype & operator -- () { ScopedLock l( &m_lock ); --m_value; return *this; } // prefix --
|
|
Type operator ++ ( int ) { // postfix ++
|
|
Type t = m_value;
|
|
{
|
|
ScopedLock l( &m_lock );
|
|
++m_value;
|
|
}
|
|
return t;
|
|
}
|
|
Type operator -- ( int ) { // postfix --
|
|
Type t = m_value;
|
|
{
|
|
ScopedLock l( &m_lock );
|
|
--m_value;
|
|
}
|
|
return t;
|
|
}
|
|
|
|
// \ru Операторы сравнения. \en Comparison operators.
|
|
bool operator == ( const atomic_itype & t ) const { return m_value == t.m_value; }
|
|
bool operator != ( const atomic_itype & t ) const { return m_value != t.m_value; }
|
|
bool operator < ( const atomic_itype & t ) const { return m_value < t.m_value; }
|
|
bool operator > ( const atomic_itype & t ) const { return m_value > t.m_value; }
|
|
bool operator <= ( const atomic_itype & t ) const { return m_value <= t.m_value; }
|
|
bool operator >= ( const atomic_itype & t ) const { return m_value >= t.m_value; }
|
|
|
|
// \ru Доступ к данным. \en Data access.
|
|
Type operator()() const { return m_value; }
|
|
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Потокобезопасный логический тип. \en Thread-safe boolean type.
|
|
//--
|
|
class atomic_bool : public atomic_itype<int>
|
|
{
|
|
public:
|
|
atomic_bool() {}
|
|
|
|
atomic_bool( const atomic_bool & t ) : atomic_itype<int>( t.m_value ) {}
|
|
atomic_bool( const bool t ) : atomic_itype<int>( t ? 1 : 0 ) {}
|
|
atomic_bool( const int t ) : atomic_itype<int>( t != 0 ? 1 : 0 ) {}
|
|
|
|
// \ru Операторы присваивания. \en Assignment operators.
|
|
atomic_bool & operator = ( const atomic_bool & t ) { ScopedLock l( &m_lock ); m_value = t.m_value; return *this; }
|
|
atomic_bool & operator = ( bool t ) { ScopedLock l( &m_lock ); m_value = t ? 1 : 0; return *this; }
|
|
atomic_bool & operator = ( int t ) { ScopedLock l( &m_lock ); m_value = t != 0 ? 1 : 0; return *this; }
|
|
|
|
bool operator && ( bool t ) { return t == !!m_value; }
|
|
bool operator || ( bool t ) { return t || !!m_value; }
|
|
|
|
// \ru Доступ к данным. \en Data access.
|
|
bool operator()() const { return !!m_value; }
|
|
|
|
private:
|
|
// \ru Операторы инкремента и декремента не разрешены. \en Increment and decrement operators not allowed.
|
|
atomic_bool & operator ++ ();
|
|
atomic_bool & operator -- ();
|
|
bool operator ++ ( int );
|
|
bool operator -- ( int );
|
|
};
|
|
|
|
typedef atomic_itype<size_t> serial_type; // \ru Потокобезопасный тип счётчика ссылок. \en Thread-safe references count type.
|
|
typedef atomic_itype<ptrdiff_t> use_count_type; // \ru Потокобезопасный тип счётчика ссылок. \en Thread-safe references count type.
|
|
typedef atomic_itype<int8> flag_type; ///< \ru Потокобезопасный тип флага. \en Thread-safe flag type.
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \ru Получить значение. \en Get value.
|
|
*/
|
|
//---
|
|
template <class AtomicType, class Type>
|
|
Type LoadTypeValue( const AtomicType & v ) {
|
|
return v();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \ru Установить значение. \en Get value.
|
|
*/
|
|
//---
|
|
template <class AtomicType>
|
|
void StoreTypeValue( const AtomicType & src, AtomicType & dst ) {
|
|
dst = src;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \ru Установить значение. \en Get value.
|
|
*/
|
|
//---
|
|
template <class AtomicType, class Type>
|
|
void StoreTypeValue( const Type src, AtomicType & dst ) {
|
|
dst = src;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/** \ru Получить значение. \en Get value.
|
|
*/
|
|
//---
|
|
inline size_t SerialTypeValue( const serial_type & v ) {
|
|
return v();
|
|
}
|
|
inline ptrdiff_t UseCountValue( const use_count_type & v ) {
|
|
return v();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// \ru Шаблонный класс для перечислений (Type - тип перечисления).
|
|
// \en Template class for enums (Type - a type of enum).
|
|
//--
|
|
template< class Type >
|
|
class atomic_enum_type : public atomic_itype<ptrdiff_t>
|
|
{
|
|
public:
|
|
atomic_enum_type() : atomic_itype<ptrdiff_t>() {}
|
|
atomic_enum_type( Type & val ) : atomic_itype<ptrdiff_t>( val ) {}
|
|
atomic_enum_type( const Type & val ) : atomic_itype<ptrdiff_t>( val ) {}
|
|
atomic_enum_type( const atomic_enum_type & val ) : atomic_itype<ptrdiff_t>( val.m_value ) {}
|
|
atomic_enum_type( atomic_enum_type & val ) : atomic_itype<ptrdiff_t>( val.m_value ) {}
|
|
|
|
// \ru Операторы присваивания. \en Assignment operators.
|
|
atomic_enum_type & operator = ( const atomic_enum_type & t ) { ScopedLock l( &m_lock ); m_value = t.m_value; return *this; }
|
|
atomic_enum_type & operator = ( const Type & t ) { ScopedLock l( &m_lock ); m_value = t; return *this; }
|
|
|
|
// \ru Операторы сравнения. \en Comparison operators.
|
|
bool operator == ( const atomic_enum_type & t ) const { return m_value == t.m_value; }
|
|
bool operator == ( const Type & t ) const { return m_value == t; }
|
|
bool operator != ( const atomic_enum_type & t ) const { return m_value != t.m_value; }
|
|
bool operator != ( const Type & t ) const { return m_value != t; }
|
|
bool operator < ( const atomic_enum_type & t ) const { return m_value < t.m_value; }
|
|
bool operator < ( Type t ) const { return m_value < t; }
|
|
bool operator > ( const atomic_enum_type & t ) const { return m_value > t.m_value; }
|
|
bool operator > ( const Type & t ) const { return m_value > t; }
|
|
bool operator <= ( const atomic_enum_type & t ) const { return m_value <= t.m_value; }
|
|
bool operator <= ( const Type & t ) const { return m_value <= t; }
|
|
bool operator >= ( const atomic_enum_type & t ) const { return m_value >= t.m_value; }
|
|
bool operator >= ( const Type & t ) const { return m_value >= t; }
|
|
|
|
// \ru Доступ к данным. \en Data access.
|
|
Type operator()() const { return static_cast<Type>( m_value ); }
|
|
};
|
|
|
|
#endif // C3D_USE_CXX11_ATOMIC
|
|
|
|
|
|
#endif // __SYSTEM_ATOMIC_H
|