summaryrefslogtreecommitdiff
path: root/src/mongo/bson/util/atomic_int.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/bson/util/atomic_int.h')
-rw-r--r--src/mongo/bson/util/atomic_int.h131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/mongo/bson/util/atomic_int.h b/src/mongo/bson/util/atomic_int.h
new file mode 100644
index 00000000000..0b853635795
--- /dev/null
+++ b/src/mongo/bson/util/atomic_int.h
@@ -0,0 +1,131 @@
+// atomic_int.h
+// atomic wrapper for unsigned
+
+/* Copyright 2009 10gen Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#if defined(_WIN32)
+#include "mongo/platform/windows_basic.h"
+#endif
+
+#include "mongo/platform/compiler.h"
+
+namespace mongo {
+
+ /**
+ * An unsigned integer supporting atomic read-modify-write operations.
+ *
+ * Many operations on these types depend on natural alignment (4 byte alignment for 4-byte
+ * words, i.e.).
+ */
+ struct MONGO_COMPILER_ALIGN_TYPE( 4 ) AtomicUInt {
+ AtomicUInt() : x(0) {}
+ AtomicUInt(unsigned z) : x(z) { }
+
+ operator unsigned() const { return x; }
+ unsigned get() const { return x; }
+ inline void set(unsigned newX);
+
+ inline AtomicUInt operator++(); // ++prefix
+ inline AtomicUInt operator++(int);// postfix++
+ inline AtomicUInt operator--(); // --prefix
+ inline AtomicUInt operator--(int); // postfix--
+ inline void signedAdd(int by);
+ inline void zero() { set(0); }
+ volatile unsigned x;
+ };
+
+#if defined(_WIN32)
+ void AtomicUInt::set(unsigned newX) {
+ InterlockedExchange((volatile long *)&x, newX);
+ }
+
+ AtomicUInt AtomicUInt::operator++() {
+ return InterlockedIncrement((volatile long*)&x);
+ }
+ AtomicUInt AtomicUInt::operator++(int) {
+ return InterlockedIncrement((volatile long*)&x)-1;
+ }
+ AtomicUInt AtomicUInt::operator--() {
+ return InterlockedDecrement((volatile long*)&x);
+ }
+ AtomicUInt AtomicUInt::operator--(int) {
+ return InterlockedDecrement((volatile long*)&x)+1;
+ }
+# if defined(_WIN64)
+ // don't see an InterlockedAdd for _WIN32...hmmm
+ void AtomicUInt::signedAdd(int by) {
+ InterlockedAdd((volatile long *)&x,by);
+ }
+# endif
+#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)
+ // this is in GCC >= 4.1
+ inline void AtomicUInt::set(unsigned newX) { __sync_synchronize(); x = newX; }
+ AtomicUInt AtomicUInt::operator++() {
+ return __sync_add_and_fetch(&x, 1);
+ }
+ AtomicUInt AtomicUInt::operator++(int) {
+ return __sync_fetch_and_add(&x, 1);
+ }
+ AtomicUInt AtomicUInt::operator--() {
+ return __sync_add_and_fetch(&x, -1);
+ }
+ AtomicUInt AtomicUInt::operator--(int) {
+ return __sync_fetch_and_add(&x, -1);
+ }
+ void AtomicUInt::signedAdd(int by) {
+ __sync_fetch_and_add(&x, by);
+ }
+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
+ inline void AtomicUInt::set(unsigned newX) {
+ asm volatile("mfence" ::: "memory");
+ x = newX;
+ }
+
+ // from boost 1.39 interprocess/detail/atomic.hpp
+ inline unsigned atomic_int_helper(volatile unsigned *x, int val) {
+ int r;
+ asm volatile
+ (
+ "lock\n\t"
+ "xadd %1, %0":
+ "+m"( *x ), "=r"( r ): // outputs (%0, %1)
+ "1"( val ): // inputs (%2 == %1)
+ "memory", "cc" // clobbers
+ );
+ return r;
+ }
+ AtomicUInt AtomicUInt::operator++() {
+ return atomic_int_helper(&x, 1)+1;
+ }
+ AtomicUInt AtomicUInt::operator++(int) {
+ return atomic_int_helper(&x, 1);
+ }
+ AtomicUInt AtomicUInt::operator--() {
+ return atomic_int_helper(&x, -1)-1;
+ }
+ AtomicUInt AtomicUInt::operator--(int) {
+ return atomic_int_helper(&x, -1);
+ }
+ void AtomicUInt::signedAdd(int by) {
+ atomic_int_helper(&x, by);
+ }
+#else
+# error "unsupported compiler or platform"
+#endif
+
+} // namespace mongo