From Mathias Froehlich, OpenThreads::Atomic support
This commit is contained in:
parent
7cfe00d3d9
commit
d7e9e5e495
102
CMakeModules/CheckAtomicOps.cmake
Normal file
102
CMakeModules/CheckAtomicOps.cmake
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# Check for availability of atomic operations
|
||||||
|
# This module defines
|
||||||
|
# OPENTHREADS_HAVE_ATOMIC_OPS
|
||||||
|
|
||||||
|
INCLUDE(CheckCXXSourceRuns)
|
||||||
|
|
||||||
|
# Do step by step checking,
|
||||||
|
CHECK_CXX_SOURCE_RUNS("
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
#ifdef __i386__
|
||||||
|
// Bad, gcc behaves dependent on the compilers -march=... flags.
|
||||||
|
// Since the osg::Referenced stuff is code distributed in headers, it is
|
||||||
|
// unclear if we will have this feature available at compile time of the
|
||||||
|
// headers. So just do not use this feature for 32 bit code.
|
||||||
|
// May be we can implement around that limitation at some time..
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
#else
|
||||||
|
unsigned value = 0;
|
||||||
|
void* ptr = &value;
|
||||||
|
__sync_add_and_fetch(&value, 1);
|
||||||
|
__sync_synchronize();
|
||||||
|
__sync_sub_and_fetch(&value, 1);
|
||||||
|
if (!__sync_bool_compare_and_swap(&value, 0, 1))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
if (!__sync_bool_compare_and_swap(&ptr, ptr, ptr))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
" _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
|
||||||
|
|
||||||
|
CHECK_CXX_SOURCE_RUNS("
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
int main(int, const char**)
|
||||||
|
{
|
||||||
|
unsigned value = 0;
|
||||||
|
void* ptr = &value;
|
||||||
|
__add_and_fetch(&value, 1);
|
||||||
|
__synchronize(value);
|
||||||
|
__sub_and_fetch(&value, 1);
|
||||||
|
if (!__sync_compare_and_swap(&value, 0, 1))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
if (!__sync_compare_and_swap(&ptr, ptr, ptr))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
" _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
|
||||||
|
|
||||||
|
CHECK_CXX_SOURCE_RUNS("
|
||||||
|
#include <atomic.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
int main(int, const char**)
|
||||||
|
{
|
||||||
|
uint_t value = 0;
|
||||||
|
void* ptr = &value;
|
||||||
|
atomic_inc_uint_nv(&value);
|
||||||
|
membar_consumer();
|
||||||
|
atomic_dec_uint_nv(&value);
|
||||||
|
if (0 != atomic_cas_uint(&value, 0, 1))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
if (ptr != atomic_cas_ptr(&ptr, ptr, ptr))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
" _OPENTHREADS_ATOMIC_USE_SUN)
|
||||||
|
|
||||||
|
CHECK_CXX_SOURCE_RUNS("
|
||||||
|
#include <windows.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
int main(int, const char**)
|
||||||
|
{
|
||||||
|
__declspec(align(32)) volatile long value = 0;
|
||||||
|
__declspec(align(32)) volatile void* ptr = &value;
|
||||||
|
|
||||||
|
InterlockedIncrement(&value);
|
||||||
|
InterlockedDecrement(&value);
|
||||||
|
|
||||||
|
if (0 != InterlockedCompareExchange(&value, 1, 0))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
if (ptr != InterlockedCompareExchangePointer(&ptr, ptr, ptr))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
" _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
|
||||||
|
|
||||||
|
IF(NOT _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_SUN AND NOT _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
|
||||||
|
SET(_OPENTHREADS_ATOMIC_USE_MUTEX)
|
||||||
|
ENDIF(NOT _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS AND NOT _OPENTHREADS_ATOMIC_USE_SUN AND NOT _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
|
182
include/OpenThreads/Atomic
Normal file
182
include/OpenThreads/Atomic
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/* -*-c++-*- OpenThreads library, Copyright (C) 2008 The Open Thread Group
|
||||||
|
*
|
||||||
|
* This library is open source and may be redistributed and/or modified under
|
||||||
|
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
|
||||||
|
* (at your option) any later version. The full license is in LICENSE file
|
||||||
|
* included with this distribution, and on the openscenegraph.org website.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* OpenSceneGraph Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _OPENTHREADS_ATOMIC_
|
||||||
|
#define _OPENTHREADS_ATOMIC_
|
||||||
|
|
||||||
|
#include <OpenThreads/Config>
|
||||||
|
|
||||||
|
#if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
|
||||||
|
# include <windows.h>
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
|
||||||
|
# include <atomic.h>
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
|
||||||
|
# include "Mutex"
|
||||||
|
# include "ScopedLock"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace OpenThreads {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class Atomic
|
||||||
|
* @brief This class provides an atomic increment and decrement operation.
|
||||||
|
*/
|
||||||
|
class OPENTHREAD_EXPORT_DIRECTIVE Atomic {
|
||||||
|
public:
|
||||||
|
Atomic(unsigned value = 0) : _value(value)
|
||||||
|
{ }
|
||||||
|
unsigned operator++()
|
||||||
|
{
|
||||||
|
#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
|
||||||
|
return __sync_add_and_fetch(&_value, 1);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
|
||||||
|
return __add_and_fetch(&_value, 1);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
|
||||||
|
return atomic_inc_uint_nv(&_value);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
|
||||||
|
return InterlockedIncrement(&_value);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
|
||||||
|
ScopedLock<Mutex> lock(_mutex);
|
||||||
|
return ++_value;
|
||||||
|
#else
|
||||||
|
return ++_value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
unsigned operator--()
|
||||||
|
{
|
||||||
|
#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
|
||||||
|
return __sync_sub_and_fetch(&_value, 1);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
|
||||||
|
return __sub_and_fetch(&_value, 1);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
|
||||||
|
return atomic_dec_uint_nv(&_value);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
|
||||||
|
return InterlockedDecrement(&_value);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
|
||||||
|
ScopedLock<Mutex> lock(_mutex);
|
||||||
|
return --_value;
|
||||||
|
#else
|
||||||
|
return --_value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
operator unsigned() const
|
||||||
|
{
|
||||||
|
#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
|
||||||
|
__sync_synchronize();
|
||||||
|
return _value;
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
|
||||||
|
__synchronize(_value);
|
||||||
|
return _value;
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
|
||||||
|
membar_consumer(); // Hmm, do we need???
|
||||||
|
return _value;
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
|
||||||
|
return static_cast<unsigned const volatile &>(_value);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
|
||||||
|
ScopedLock<Mutex> lock(_mutex);
|
||||||
|
return _value;
|
||||||
|
#else
|
||||||
|
return _value;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Atomic(const Atomic&);
|
||||||
|
Atomic& operator=(const Atomic&);
|
||||||
|
|
||||||
|
#if defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
|
||||||
|
mutable Mutex _mutex;
|
||||||
|
#endif
|
||||||
|
#if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
|
||||||
|
__declspec(align(32)) volatile long _value;
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
|
||||||
|
volatile uint_t _value;
|
||||||
|
#else
|
||||||
|
volatile unsigned _value;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class AtomicPtr
|
||||||
|
* @brief This class provides an atomic pointer assignment using cas operations.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
class OPENTHREAD_EXPORT_DIRECTIVE AtomicPtr {
|
||||||
|
public:
|
||||||
|
AtomicPtr(T* ptr = 0) : _ptr(ptr)
|
||||||
|
{ }
|
||||||
|
~AtomicPtr()
|
||||||
|
{ _ptr = 0; }
|
||||||
|
|
||||||
|
// assigns a new pointer
|
||||||
|
bool assign(T* ptrNew, const T* const ptrOld)
|
||||||
|
{
|
||||||
|
#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
|
||||||
|
return __sync_bool_compare_and_swap(&_ptr, ptrOld, ptrNew);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
|
||||||
|
return __compare_and_swap(&_ptr, ptrOld, ptrNew);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
|
||||||
|
return ptrOld == atomic_cas_ptr(&_ptr, ptrOld, ptrNew);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
|
||||||
|
return ptrOld == InterlockedCompareExchangePointer(&_ptr, ptrNew, ptrOld);
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
|
||||||
|
ScopedLock<Mutex> lock(_mutex);
|
||||||
|
if (_ptr != oldPtr)
|
||||||
|
return false;
|
||||||
|
_ptr = ptrNew;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
if (_ptr != oldPtr)
|
||||||
|
return false;
|
||||||
|
_ptr = ptrNew;
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
T* get() const
|
||||||
|
{
|
||||||
|
#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS)
|
||||||
|
__sync_synchronize();
|
||||||
|
return _ptr;
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS)
|
||||||
|
__synchronize(_ptr);
|
||||||
|
return _ptr;
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_SUN)
|
||||||
|
membar_consumer(); // Hmm, do we need???
|
||||||
|
return _ptr;
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
|
||||||
|
return _ptr;
|
||||||
|
#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
|
||||||
|
ScopedLock<Mutex> lock(_mutex);
|
||||||
|
return _ptr;
|
||||||
|
#else
|
||||||
|
return _ptr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
AtomicPtr(const AtomicPtr&);
|
||||||
|
AtomicPtr& operator=(const AtomicPtr&);
|
||||||
|
|
||||||
|
#if defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
|
||||||
|
mutable Mutex _mutex;
|
||||||
|
#endif
|
||||||
|
#if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED)
|
||||||
|
__declspec(align(32))
|
||||||
|
#endif
|
||||||
|
T* volatile _ptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // _OPENTHREADS_ATOMIC_
|
@ -11,6 +11,7 @@ SET(OPENTHREADS_VERSION ${OPENTHREADS_MAJOR_VERSION}.${OPENTHREADS_MINOR_VERSION
|
|||||||
|
|
||||||
SET(HEADER_PATH ${OpenThreads_SOURCE_DIR}/include/OpenThreads)
|
SET(HEADER_PATH ${OpenThreads_SOURCE_DIR}/include/OpenThreads)
|
||||||
SET(OpenThreads_PUBLIC_HEADERS
|
SET(OpenThreads_PUBLIC_HEADERS
|
||||||
|
${HEADER_PATH}/Atomic
|
||||||
${HEADER_PATH}/Barrier
|
${HEADER_PATH}/Barrier
|
||||||
${HEADER_PATH}/Block
|
${HEADER_PATH}/Block
|
||||||
${HEADER_PATH}/Condition
|
${HEADER_PATH}/Condition
|
||||||
@ -68,5 +69,12 @@ ELSE(WIN32)
|
|||||||
ENDIF(UNIX)
|
ENDIF(UNIX)
|
||||||
ENDIF(WIN32)
|
ENDIF(WIN32)
|
||||||
|
|
||||||
|
INCLUDE(CheckAtomicOps)
|
||||||
|
|
||||||
|
SET(OPENTHREADS_CONFIG_HEADER "${PROJECT_BINARY_DIR}/include/OpenThreads/Config")
|
||||||
|
CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/common/Config.in"
|
||||||
|
"${OPENTHREADS_CONFIG_HEADER}")
|
||||||
|
INSTALL_FILES(/include/OpenThreads/ FILES "${OPENTHREADS_CONFIG_HEADER}")
|
||||||
|
|
||||||
|
# Make sure everyone can find Config
|
||||||
|
INCLUDE_DIRECTORIES(${PROJECT_BINARY_DIR}/include)
|
||||||
|
10
src/OpenThreads/common/Config.in
Normal file
10
src/OpenThreads/common/Config.in
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _OPENTHREADS_CONFIG
|
||||||
|
#define _OPENTHREADS_CONFIG
|
||||||
|
|
||||||
|
#cmakedefine _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS
|
||||||
|
#cmakedefine _OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS
|
||||||
|
#cmakedefine _OPENTHREADS_ATOMIC_USE_SUN
|
||||||
|
#cmakedefine _OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED
|
||||||
|
#cmakedefine _OPENTHREADS_ATOMIC_USE_MUTEX
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user