1 /* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 // Atomic system independant 32-bit signed integer. 12 // Linux implementation. 13 // Note: Requires gcc 4.1.2 or later. 14 #ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_ 15 #define WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_ 16 17 #include <inttypes.h> 18 #include <malloc.h> 19 20 #include "common_types.h" 21 22 namespace webrtc { 23 class Atomic32Impl 24 { 25 public: 26 inline Atomic32Impl(WebRtc_Word32 initialValue); 27 inline ~Atomic32Impl(); 28 29 inline WebRtc_Word32 operator++(); 30 inline WebRtc_Word32 operator--(); 31 32 inline Atomic32Impl& operator=(const Atomic32Impl& rhs); 33 inline Atomic32Impl& operator=(WebRtc_Word32 rhs); 34 inline WebRtc_Word32 operator+=(WebRtc_Word32 rhs); 35 inline WebRtc_Word32 operator-=(WebRtc_Word32 rhs); 36 37 inline bool CompareExchange(WebRtc_Word32 newValue, 38 WebRtc_Word32 compareValue); 39 40 inline WebRtc_Word32 Value() const; 41 private: 42 void* _ptrMemory; 43 // Volatile ensures full memory barriers. 44 volatile WebRtc_Word32* _value; 45 }; 46 47 // TODO (hellner) use aligned_malloc instead of doing it manually. 48 inline Atomic32Impl::Atomic32Impl(WebRtc_Word32 initialValue) 49 : _ptrMemory(NULL), 50 _value(NULL) 51 { // Align the memory associated with _value on a 32-bit boundary. This is a 52 // requirement for the used Linux APIs to be atomic. 53 // Keep _ptrMemory to be able to reclaim memory. 54 _ptrMemory = malloc(sizeof(WebRtc_Word32)*2); 55 _value = (WebRtc_Word32*) (((uintptr_t)_ptrMemory+3)&(~0x3)); 56 *_value = initialValue; 57 } 58 59 inline Atomic32Impl::~Atomic32Impl() 60 { 61 if(_ptrMemory != NULL) 62 { 63 free(_ptrMemory); 64 } 65 } 66 67 inline WebRtc_Word32 Atomic32Impl::operator++() 68 { 69 WebRtc_Word32 returnValue = __sync_fetch_and_add(_value,1); 70 returnValue++; 71 return returnValue; 72 } 73 74 inline WebRtc_Word32 Atomic32Impl::operator--() 75 { 76 WebRtc_Word32 returnValue = __sync_fetch_and_sub(_value,1); 77 returnValue--; 78 return returnValue; 79 } 80 81 inline Atomic32Impl& Atomic32Impl::operator=(const Atomic32Impl& rhs) 82 { 83 *_value = *rhs._value; 84 return *this; 85 } 86 87 inline Atomic32Impl& Atomic32Impl::operator=(WebRtc_Word32 rhs) 88 { 89 *_value = rhs; 90 return *this; 91 } 92 93 inline WebRtc_Word32 Atomic32Impl::operator+=(WebRtc_Word32 rhs) 94 { 95 WebRtc_Word32 returnValue = __sync_fetch_and_add(_value,rhs); 96 returnValue += rhs; 97 return returnValue; 98 } 99 100 inline WebRtc_Word32 Atomic32Impl::operator-=(WebRtc_Word32 rhs) 101 { 102 WebRtc_Word32 returnValue = __sync_fetch_and_sub(_value,rhs); 103 returnValue -= rhs; 104 return returnValue; 105 } 106 107 inline bool Atomic32Impl::CompareExchange(WebRtc_Word32 newValue, 108 WebRtc_Word32 compareValue) 109 { 110 return __sync_bool_compare_and_swap(_value,compareValue,newValue); 111 } 112 113 inline WebRtc_Word32 Atomic32Impl::Value() const 114 { 115 return *_value; 116 } 117 } // namespace webrtc 118 119 #endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_ 120