MongoDB  2.7.0
atomic_int.h
1 // atomic_int.h
2 // atomic wrapper for unsigned
3 
4 /* Copyright 2009 10gen Inc.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #pragma once
20 
21 #if defined(_WIN32)
22 #include "mongo/platform/windows_basic.h"
23 #endif
24 
25 #include "mongo/platform/compiler.h"
26 
27 namespace mongo {
28 
35  struct MONGO_COMPILER_ALIGN_TYPE( 4 ) AtomicUInt {
36  AtomicUInt() : x(0) {}
37  AtomicUInt(unsigned z) : x(z) { }
38 
39  operator unsigned() const { return x; }
40  unsigned get() const { return x; }
41  inline void set(unsigned newX);
42 
43  inline AtomicUInt operator++(); // ++prefix
44  inline AtomicUInt operator++(int);// postfix++
45  inline AtomicUInt operator--(); // --prefix
46  inline AtomicUInt operator--(int); // postfix--
47  inline void signedAdd(int by);
48  inline void zero() { set(0); }
49  volatile unsigned x;
50  };
51 
52 #if defined(_WIN32)
53  void AtomicUInt::set(unsigned newX) {
54  InterlockedExchange((volatile long *)&x, newX);
55  }
56 
57  AtomicUInt AtomicUInt::operator++() {
58  return InterlockedIncrement((volatile long*)&x);
59  }
60  AtomicUInt AtomicUInt::operator++(int) {
61  return InterlockedIncrement((volatile long*)&x)-1;
62  }
63  AtomicUInt AtomicUInt::operator--() {
64  return InterlockedDecrement((volatile long*)&x);
65  }
66  AtomicUInt AtomicUInt::operator--(int) {
67  return InterlockedDecrement((volatile long*)&x)+1;
68  }
69 # if defined(_WIN64)
70  // don't see an InterlockedAdd for _WIN32...hmmm
71  void AtomicUInt::signedAdd(int by) {
72  InterlockedAdd((volatile long *)&x,by);
73  }
74 # endif
75 #elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
76  // this is in GCC >= 4.1
77  inline void AtomicUInt::set(unsigned newX) { __sync_synchronize(); x = newX; }
78  AtomicUInt AtomicUInt::operator++() {
79  return __sync_add_and_fetch(&x, 1);
80  }
81  AtomicUInt AtomicUInt::operator++(int) {
82  return __sync_fetch_and_add(&x, 1);
83  }
84  AtomicUInt AtomicUInt::operator--() {
85  return __sync_add_and_fetch(&x, -1);
86  }
87  AtomicUInt AtomicUInt::operator--(int) {
88  return __sync_fetch_and_add(&x, -1);
89  }
90  void AtomicUInt::signedAdd(int by) {
91  __sync_fetch_and_add(&x, by);
92  }
93 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
94  inline void AtomicUInt::set(unsigned newX) {
95  asm volatile("mfence" ::: "memory");
96  x = newX;
97  }
98 
99  // from boost 1.39 interprocess/detail/atomic.hpp
100  inline unsigned atomic_int_helper(volatile unsigned *x, int val) {
101  int r;
102  asm volatile
103  (
104  "lock\n\t"
105  "xadd %1, %0":
106  "+m"( *x ), "=r"( r ): // outputs (%0, %1)
107  "1"( val ): // inputs (%2 == %1)
108  "memory", "cc" // clobbers
109  );
110  return r;
111  }
112  AtomicUInt AtomicUInt::operator++() {
113  return atomic_int_helper(&x, 1)+1;
114  }
115  AtomicUInt AtomicUInt::operator++(int) {
116  return atomic_int_helper(&x, 1);
117  }
118  AtomicUInt AtomicUInt::operator--() {
119  return atomic_int_helper(&x, -1)-1;
120  }
121  AtomicUInt AtomicUInt::operator--(int) {
122  return atomic_int_helper(&x, -1);
123  }
124  void AtomicUInt::signedAdd(int by) {
125  atomic_int_helper(&x, by);
126  }
127 #else
128 # error "unsupported compiler or platform"
129 #endif
130 
131 } // namespace mongo
struct MONGO_COMPILER_ALIGN_TYPE(4) AtomicUInt
An unsigned integer supporting atomic read-modify-write operations.
Definition: atomic_int.h:35