MongoDB C++ Driver  legacy-1.1.2
atomic_word_cxx11.h
1 /* Copyright 2014 10gen Inc.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #pragma once
17 
18 #if !defined(MONGO_HAVE_CXX11_ATOMICS)
19 #error "Cannot use atomic_word_cxx11.h without C++11 <atomic> support"
20 #endif
21 
22 // This file is a bit unusual. Most other source files in this codebase assume that C++11
23 // things are only usable if __cplusplus >= 201103L. However, we have made an explicit decision
24 // to use <atomic> when available, even if full C++11 conformance is not advertised. As a
25 // result, we unconditionally include <atomic>, but guard all other C++11 features under
26 // __cplusplus >= 201103L so that we can work on platforms that don't yet offer those features, but
27 // do offer <atomic>
28 
29 #include <atomic>
30 
31 #if __cplusplus >= 201103L
32 #include <type_traits>
33 #endif
34 
35 #include <boost/static_assert.hpp>
36 
37 #include "mongo/base/disallow_copying.h"
38 
39 namespace mongo {
40 
44 template <typename _WordType>
45 class AtomicWord {
46 #if __cplusplus < 201103L
47  // AtomicWords are not copyable in C++03.
48  MONGO_DISALLOW_COPYING(AtomicWord);
49 #endif
50 
51 public:
55  typedef _WordType WordType;
56 
60  explicit AtomicWord(WordType value = WordType(0)) : _value(value) {}
61 
62 #if __cplusplus >= 201103L
63  // In C++11, AtomicWords are not copyable or movable.
64  AtomicWord(const AtomicWord&) = delete;
65  AtomicWord& operator=(const AtomicWord&) = delete;
66  AtomicWord(AtomicWord&&) = delete;
67  AtomicWord& operator=(AtomicWord&&) = delete;
68 #endif
69 
75  WordType load() const {
76  return _value.load();
77  }
78 
84  WordType loadRelaxed() const {
85  return _value.load(std::memory_order_relaxed);
86  }
87 
93  void store(WordType newValue) {
94  return _value.store(newValue);
95  }
96 
104  WordType swap(WordType newValue) {
105  return _value.exchange(newValue);
106  }
107 
116  WordType compareAndSwap(WordType expected, WordType newValue) {
117  // NOTE: Subtle: compare_exchange mutates its first argument.
118  _value.compare_exchange_strong(expected, newValue);
119  return expected;
120  }
121 
129  WordType fetchAndAdd(WordType increment) {
130  return _value.fetch_add(increment);
131  }
132 
140  WordType fetchAndSubtract(WordType decrement) {
141  return _value.fetch_sub(decrement);
142  }
143 
151  WordType addAndFetch(WordType increment) {
152  return fetchAndAdd(increment) + increment;
153  }
154 
162  WordType subtractAndFetch(WordType decrement) {
163  return fetchAndSubtract(decrement) - decrement;
164  }
165 
166 private:
167  std::atomic<WordType> _value;
168 };
169 
170 #if __cplusplus >= 201103L
171 #define _ATOMIC_WORD_DECLARE(NAME, WTYPE) \
172  typedef class AtomicWord<WTYPE> NAME; \
173  namespace { \
174  BOOST_STATIC_ASSERT(sizeof(NAME) == sizeof(WTYPE)); \
175  BOOST_STATIC_ASSERT(std::is_standard_layout<WTYPE>::value); \
176  } // namespace
177 #else
178 #define _ATOMIC_WORD_DECLARE(NAME, WTYPE) \
179  typedef class AtomicWord<WTYPE> NAME; \
180  namespace { \
181  BOOST_STATIC_ASSERT(sizeof(NAME) == sizeof(WTYPE)); \
182  } // namespace
183 #endif
184 
185 _ATOMIC_WORD_DECLARE(AtomicUInt32, unsigned)
186 _ATOMIC_WORD_DECLARE(AtomicUInt64, unsigned long long)
187 _ATOMIC_WORD_DECLARE(AtomicInt32, int)
188 _ATOMIC_WORD_DECLARE(AtomicInt64, long long)
189 #undef _ATOMIC_WORD_DECLARE
190 
191 } // namespace mongo
WordType load() const
Gets the current value of this AtomicWord.
Definition: atomic_word_cxx11.h:75
Utility functions for parsing numbers from strings.
Definition: compare_numbers.h:20
WordType loadRelaxed() const
Gets the current value of this AtomicWord.
Definition: atomic_word_cxx11.h:84
_WordType WordType
Underlying value type.
Definition: atomic_word_cxx11.h:55
WordType compareAndSwap(WordType expected, WordType newValue)
Atomic compare and swap.
Definition: atomic_word_cxx11.h:116
WordType addAndFetch(WordType increment)
Get the current value of this, add "increment" and store it, atomically.
Definition: atomic_word_cxx11.h:151
AtomicWord(WordType value=WordType(0))
Construct a new word with the given initial value.
Definition: atomic_word_cxx11.h:60
WordType fetchAndSubtract(WordType decrement)
Get the current value of this, subtract "decrement" and store it, atomically.
Definition: atomic_word_cxx11.h:140
WordType swap(WordType newValue)
Atomically swaps the current value of this with "newValue".
Definition: atomic_word_cxx11.h:104
WordType subtractAndFetch(WordType decrement)
Get the current value of this, subtract "decrement" and store it, atomically.
Definition: atomic_word_cxx11.h:162
WordType fetchAndAdd(WordType increment)
Get the current value of this, add "increment" and store it, atomically.
Definition: atomic_word_cxx11.h:129
Implementation of the AtomicWord interface in terms of the C++11 Atomics.
Definition: atomic_word_cxx11.h:45
void store(WordType newValue)
Sets the value of this AtomicWord to "newValue".
Definition: atomic_word_cxx11.h:93