Changeset 8493

Show
Ignore:
Timestamp:
06/26/08 12:27:16
Author:
robert
Message:

From Mathias Froechlich, "Attached is a change to that atomic stuff to move the win32, msvc
implementation of the atomic increment and decrement into a implementation
file.
This way inlining and compiler optimization can no longer happen for these
implementations, but it fixes compilation on win32 msvc targets. I expect
that this is still faster than with with mutexes.

Also the i386 gcc target gets atomic operations with this patch. By using an
implementation file we can guarantee that we have the right compiler flags
available."

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • OpenSceneGraph/trunk/CMakeModules/CheckAtomicOps.cmake

    r8490 r8493  
    1111int main() 
    1212{ 
    13 #ifdef __i386__ 
    14    // Bad, gcc behaves dependent on the compilers -march=... flags. 
    15    // Since the osg::Referenced stuff is code distributed in headers, it is 
    16    // unclear if we will have this feature available at compile time of the 
    17    // headers. So just do not use this feature for 32 bit code. 
    18    // May be we can implement around that limitation at some time.. 
    19    return EXIT_FAILURE; 
    20 #else 
    2113   unsigned value = 0; 
    2214   void* ptr = &value; 
     
    3123 
    3224   return EXIT_SUCCESS; 
    33 #endif 
    3425} 
    3526" _OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
    3627 
    3728CHECK_CXX_SOURCE_RUNS(" 
    38 #include <cstdlib
     29#include <stdlib.h
    3930 
    4031int main(int, const char**) 
     
    4536   __synchronize(value); 
    4637   __sub_and_fetch(&value, 1); 
    47    if (!__sync_compare_and_swap(&value, 0, 1)) 
     38   if (!__compare_and_swap(&value, 0, 1)) 
    4839      return EXIT_FAILURE; 
    4940    
    50    if (!__sync_compare_and_swap(&ptr, ptr, ptr)) 
     41   if (!__compare_and_swap((unsigned long*)&ptr, (unsigned long)ptr, (unsigned long)ptr)) 
    5142      return EXIT_FAILURE; 
    5243 
  • OpenSceneGraph/trunk/include/OpenThreads/Atomic

    r8490 r8493  
    1616 
    1717#include <OpenThreads/Config> 
     18#include <OpenThreads/Exports> 
    1819 
    19 #if defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    20 # include <windows.h> 
     20#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) && defined(__i386__) 
     21#define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES 
     22#elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
     23#define _OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES 
    2124#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
    2225# include <atomic.h> 
     
    2427# include "Mutex" 
    2528# include "ScopedLock" 
     29#endif 
     30 
     31#if defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES) 
     32#define _OPENTHREADS_ATOMIC_INLINE 
     33#else 
     34#define _OPENTHREADS_ATOMIC_INLINE inline 
    2635#endif 
    2736 
     
    3241 *  @brief  This class provides an atomic increment and decrement operation. 
    3342 */ 
    34 class Atomic { 
     43class OPENTHREAD_EXPORT_DIRECTIVE Atomic { 
    3544 public: 
    3645    Atomic(unsigned value = 0) : _value(value) 
    3746    { } 
    38     unsigned operator++() 
    39     { 
    40 #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
    41         return __sync_add_and_fetch(&_value, 1); 
    42 #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
    43         return __add_and_fetch(&_value, 1); 
    44 #elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
    45         return atomic_inc_uint_nv(&_value); 
    46 #elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    47         return InterlockedIncrement(&_value); 
    48 #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
    49         ScopedLock<Mutex> lock(_mutex); 
    50         return ++_value; 
    51 #else 
    52         return ++_value; 
    53 #endif 
    54     } 
    55     unsigned operator--() 
    56     { 
    57 #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
    58         return __sync_sub_and_fetch(&_value, 1); 
    59 #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
    60         return __sub_and_fetch(&_value, 1); 
    61 #elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
    62         return atomic_dec_uint_nv(&_value); 
    63 #elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    64         return InterlockedDecrement(&_value); 
    65 #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
    66         ScopedLock<Mutex> lock(_mutex); 
    67         return --_value; 
    68 #else 
    69         return --_value; 
    70 #endif 
    71     } 
    72     operator unsigned() const 
    73     { 
    74 #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
    75         __sync_synchronize(); 
    76         return _value; 
    77 #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
    78         __synchronize(_value); 
    79         return _value; 
    80 #elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
    81         membar_consumer(); // Hmm, do we need??? 
    82         return _value; 
    83 #elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    84         return static_cast<unsigned const volatile &>(_value); 
    85 #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
    86         ScopedLock<Mutex> lock(_mutex); 
    87         return _value; 
    88 #else 
    89         return _value; 
    90 #endif 
    91     } 
    92      
     47    _OPENTHREADS_ATOMIC_INLINE unsigned operator++(); 
     48    _OPENTHREADS_ATOMIC_INLINE unsigned operator--(); 
     49    _OPENTHREADS_ATOMIC_INLINE operator unsigned() const; 
    9350 private: 
    9451 
     
    11269 *  @brief  This class provides an atomic pointer assignment using cas operations. 
    11370 */ 
    114 template<typename T> 
    115 class AtomicPtr { 
     71class OPENTHREAD_EXPORT_DIRECTIVE AtomicPtr { 
    11672public: 
    117     AtomicPtr(T* ptr = 0) : _ptr(ptr) 
     73    AtomicPtr(void* ptr = 0) : _ptr(ptr) 
    11874    { } 
    11975    ~AtomicPtr() 
     
    12177 
    12278    // assigns a new pointer 
    123     bool assign(T* ptrNew, const T* const ptrOld) 
    124     { 
    125 #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
    126         return __sync_bool_compare_and_swap(&_ptr, ptrOld, ptrNew); 
    127 #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
    128         return __compare_and_swap(&_ptr, ptrOld, ptrNew); 
    129 #elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
    130         return ptrOld == atomic_cas_ptr(&_ptr, ptrOld, ptrNew); 
    131 #elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    132         return ptrOld == InterlockedCompareExchangePointer((PVOID volatile*)&_ptr, (PVOID)ptrNew, (PVOID)ptrOld); 
    133 #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
    134         ScopedLock<Mutex> lock(_mutex); 
    135         if (_ptr != ptrOld) 
    136             return false; 
    137         _ptr = ptrNew; 
    138         return true; 
    139 #else 
    140         if (_ptr != ptrOld) 
    141             return false; 
    142         _ptr = ptrNew; 
    143         return true; 
    144 #endif 
    145     } 
    146  
    147     T* get() const 
    148     { 
    149 #if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
    150         __sync_synchronize(); 
    151         return _ptr; 
    152 #elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
    153         __synchronize(_ptr); 
    154         return _ptr; 
    155 #elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
    156         membar_consumer(); // Hmm, do we need??? 
    157         return _ptr; 
    158 #elif defined(_OPENTHREADS_ATOMIC_USE_WIN32_INTERLOCKED) 
    159         return _ptr; 
    160 #elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
    161         ScopedLock<Mutex> lock(_mutex); 
    162         return _ptr; 
    163 #else 
    164         return _ptr; 
    165 #endif 
    166     } 
     79    _OPENTHREADS_ATOMIC_INLINE bool assign(void* ptrNew, const void* const ptrOld); 
     80    _OPENTHREADS_ATOMIC_INLINE void* get() const; 
    16781 
    16882private: 
     
    17387    mutable Mutex _mutex; 
    17488#endif 
    175     T* volatile _ptr; 
     89    void* volatile _ptr; 
    17690}; 
     91 
     92#if !defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES) 
     93 
     94_OPENTHREADS_ATOMIC_INLINE unsigned 
     95Atomic::operator++() 
     96{ 
     97#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     98    return __sync_add_and_fetch(&_value, 1); 
     99#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
     100    return __add_and_fetch(&_value, 1); 
     101#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
     102    return atomic_inc_uint_nv(&_value); 
     103#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
     104    ScopedLock<Mutex> lock(_mutex); 
     105    return ++_value; 
     106#else 
     107    return ++_value; 
     108#endif 
     109} 
     110 
     111_OPENTHREADS_ATOMIC_INLINE unsigned 
     112Atomic::operator--() 
     113{ 
     114#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     115    return __sync_sub_and_fetch(&_value, 1); 
     116#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
     117    return __sub_and_fetch(&_value, 1); 
     118#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
     119    return atomic_dec_uint_nv(&_value); 
     120#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
     121    ScopedLock<Mutex> lock(_mutex); 
     122    return --_value; 
     123#else 
     124    return --_value; 
     125#endif 
     126} 
     127 
     128_OPENTHREADS_ATOMIC_INLINE 
     129Atomic::operator unsigned() const 
     130{ 
     131#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     132    __sync_synchronize(); 
     133    return _value; 
     134#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
     135    __synchronize(); 
     136    return _value; 
     137#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
     138    membar_consumer(); // Hmm, do we need??? 
     139    return _value; 
     140#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
     141    ScopedLock<Mutex> lock(_mutex); 
     142    return _value; 
     143#else 
     144    return _value; 
     145#endif 
     146} 
     147 
     148_OPENTHREADS_ATOMIC_INLINE bool 
     149AtomicPtr::assign(void* ptrNew, const void* const ptrOld) 
     150{ 
     151#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     152    return __sync_bool_compare_and_swap(&_ptr, ptrOld, ptrNew); 
     153#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
     154    return __compare_and_swap((unsigned long*)&_ptr, (unsigned long)ptrOld, (unsigned long)ptrNew); 
     155#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
     156    return ptrOld == atomic_cas_ptr(&_ptr, ptrOld, ptrNew); 
     157#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
     158    ScopedLock<Mutex> lock(_mutex); 
     159    if (_ptr != ptrOld) 
     160        return false; 
     161    _ptr = ptrNew; 
     162    return true; 
     163#else 
     164    if (_ptr != ptrOld) 
     165        return false; 
     166    _ptr = ptrNew; 
     167    return true; 
     168#endif 
     169} 
     170 
     171_OPENTHREADS_ATOMIC_INLINE void* 
     172AtomicPtr::get() const 
     173{ 
     174#if defined(_OPENTHREADS_ATOMIC_USE_GCC_BUILTINS) 
     175    __sync_synchronize(); 
     176    return _ptr; 
     177#elif defined(_OPENTHREADS_ATOMIC_USE_MIPOSPRO_BUILTINS) 
     178    __synchronize(); 
     179    return _ptr; 
     180#elif defined(_OPENTHREADS_ATOMIC_USE_SUN) 
     181    membar_consumer(); // Hmm, do we need??? 
     182    return _ptr; 
     183#elif defined(_OPENTHREADS_ATOMIC_USE_MUTEX) 
     184    ScopedLock<Mutex> lock(_mutex); 
     185    return _ptr; 
     186#else 
     187    return _ptr; 
     188#endif 
     189} 
     190 
     191#endif // !defined(_OPENTHREADS_ATOMIC_USE_LIBRARY_ROUTINES) 
    177192 
    178193} 
  • OpenSceneGraph/trunk/include/osg/Referenced

    r8465 r8493  
    130130        struct ObserverSetData; 
    131131 
    132         OpenThreads::AtomicPtr<ObserverSetData> _observerSetDataPtr; 
     132        OpenThreads::AtomicPtr _observerSetDataPtr; 
    133133 
    134134        mutable OpenThreads::Atomic     _refCount; 
  • OpenSceneGraph/trunk/src/OpenThreads/pthreads/CMakeLists.txt

    r8358 r8493  
    2121    PThreadPrivateData.h 
    2222    ../common/Version.cpp 
     23    ../common/Atomic.cpp 
    2324) 
    2425 
  • OpenSceneGraph/trunk/src/osg/Referenced.cpp

    r8465 r8493  
    248248    } 
    249249#else 
    250     ObserverSetData* observerSetData = _observerSetDataPtr.get(); 
     250    ObserverSetData* observerSetData = static_cast<ObserverSetData*>(_observerSetDataPtr.get()); 
    251251    if (observerSetData) 
    252252    { 
     
    308308{ 
    309309#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS) 
    310     ObserverSetData* observerSetData = _observerSetDataPtr.get(); 
     310    ObserverSetData* observerSetData = static_cast<ObserverSetData*>(_observerSetDataPtr.get()); 
    311311    while (0 == observerSetData) { 
    312312        ObserverSetData* newObserverSetData = new ObserverSetData; 
    313313        if (!_observerSetDataPtr.assign(newObserverSetData, 0)) 
    314314            delete newObserverSetData; 
    315         observerSetData = _observerSetDataPtr.get(); 
     315        observerSetData = static_cast<ObserverSetData*>(_observerSetDataPtr.get()); 
    316316    } 
    317317    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(observerSetData->_mutex); 
     
    336336{ 
    337337#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS) 
    338     ObserverSetData* observerSetData = _observerSetDataPtr.get(); 
     338    ObserverSetData* observerSetData = static_cast<ObserverSetData*>(_observerSetDataPtr.get()); 
    339339    if (observerSetData) 
    340340    {