libstdc++
|
00001 // -*- C++ -*- 00002 00003 // Copyright (C) 2007-2013 Free Software Foundation, Inc. 00004 // 00005 // This file is part of the GNU ISO C++ Library. This library is free 00006 // software; you can redistribute it and/or modify it under the terms 00007 // of the GNU General Public License as published by the Free Software 00008 // Foundation; either version 3, or (at your option) any later 00009 // version. 00010 00011 // This library is distributed in the hope that it will be useful, but 00012 // WITHOUT ANY WARRANTY; without even the implied warranty of 00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 // General Public License for more details. 00015 00016 // Under Section 7 of GPL version 3, you are granted additional 00017 // permissions described in the GCC Runtime Library Exception, version 00018 // 3.1, as published by the Free Software Foundation. 00019 00020 // You should have received a copy of the GNU General Public License and 00021 // a copy of the GCC Runtime Library Exception along with this program; 00022 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00023 // <http://www.gnu.org/licenses/>. 00024 00025 /** @file parallel/compatibility.h 00026 * @brief Compatibility layer, mostly concerned with atomic operations. 00027 * 00028 * This file is a GNU parallel extension to the Standard C++ Library 00029 * and contains implementation details for the library's internal use. 00030 */ 00031 00032 // Written by Felix Putze. 00033 00034 #ifndef _GLIBCXX_PARALLEL_COMPATIBILITY_H 00035 #define _GLIBCXX_PARALLEL_COMPATIBILITY_H 1 00036 00037 #include <parallel/types.h> 00038 #include <parallel/base.h> 00039 00040 #if !defined(_WIN32) || defined (__CYGWIN__) 00041 #include <sched.h> 00042 #endif 00043 00044 #ifdef __MINGW32__ 00045 // Including <windows.h> will drag in all the windows32 names. Since 00046 // that can cause user code portability problems, we just declare the 00047 // one needed function here. 00048 extern "C" 00049 __attribute((dllimport)) void __attribute__((stdcall)) Sleep (unsigned long); 00050 #endif 00051 00052 namespace __gnu_parallel 00053 { 00054 template<typename _Tp> 00055 inline _Tp 00056 __add_omp(volatile _Tp* __ptr, _Tp __addend) 00057 { 00058 int64_t __res; 00059 #pragma omp critical 00060 { 00061 __res = *__ptr; 00062 *(__ptr) += __addend; 00063 } 00064 return __res; 00065 } 00066 00067 /** @brief Add a value to a variable, atomically. 00068 * 00069 * @param __ptr Pointer to a signed integer. 00070 * @param __addend Value to add. 00071 */ 00072 template<typename _Tp> 00073 inline _Tp 00074 __fetch_and_add(volatile _Tp* __ptr, _Tp __addend) 00075 { 00076 if (__atomic_always_lock_free(sizeof(_Tp), __ptr)) 00077 return __atomic_fetch_add(__ptr, __addend, __ATOMIC_ACQ_REL); 00078 return __add_omp(__ptr, __addend); 00079 } 00080 00081 template<typename _Tp> 00082 inline bool 00083 __cas_omp(volatile _Tp* __ptr, _Tp __comparand, _Tp __replacement) 00084 { 00085 bool __res = false; 00086 #pragma omp critical 00087 { 00088 if (*__ptr == __comparand) 00089 { 00090 *__ptr = __replacement; 00091 __res = true; 00092 } 00093 } 00094 return __res; 00095 } 00096 00097 /** @brief Compare-and-swap 00098 * 00099 * Compare @c *__ptr and @c __comparand. If equal, let @c 00100 * *__ptr=__replacement and return @c true, return @c false otherwise. 00101 * 00102 * @param __ptr Pointer to signed integer. 00103 * @param __comparand Compare value. 00104 * @param __replacement Replacement value. 00105 */ 00106 template<typename _Tp> 00107 inline bool 00108 __compare_and_swap(volatile _Tp* __ptr, _Tp __comparand, _Tp __replacement) 00109 { 00110 if (__atomic_always_lock_free(sizeof(_Tp), __ptr)) 00111 return __atomic_compare_exchange_n(__ptr, &__comparand, __replacement, 00112 false, __ATOMIC_ACQ_REL, 00113 __ATOMIC_RELAXED); 00114 return __cas_omp(__ptr, __comparand, __replacement); 00115 } 00116 00117 /** @brief Yield control to another thread, without waiting for 00118 * the end of the time slice. 00119 */ 00120 inline void 00121 __yield() 00122 { 00123 #if defined (_WIN32) && !defined (__CYGWIN__) 00124 Sleep(0); 00125 #else 00126 sched_yield(); 00127 #endif 00128 } 00129 } // end namespace 00130 00131 #endif /* _GLIBCXX_PARALLEL_COMPATIBILITY_H */