Thrill  0.1
atomic_movable.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * thrill/common/atomic_movable.hpp
3  *
4  * Part of Project Thrill - http://project-thrill.org
5  *
6  * Copyright (C) 2015 Timo Bingmann <[email protected]>
7  *
8  * All rights reserved. Published under the BSD-2 license in the LICENSE file.
9  ******************************************************************************/
10 
11 #pragma once
12 #ifndef THRILL_COMMON_ATOMIC_MOVABLE_HEADER
13 #define THRILL_COMMON_ATOMIC_MOVABLE_HEADER
14 
15 #include <atomic>
16 #include <utility>
17 
18 namespace thrill {
19 namespace common {
20 
21 /*!
22  * This is a derivative of std::atomic which enables easier and less error-prone
23  * writing of move-only classes by implementing a move constructor.
24  *
25  * std::atomic does not have a move constructor for a good reason: atomicity
26  * cannot be guaranteed. The problem is that then all move-only classes
27  * containing a std::atomic must implement custom move operations. However, in
28  * all our cases we only move objects during initialization. Custom move
29  * operations are trivial to write but error-prone to maintain, since they must
30  * contain all member variables. Missing variables create very subtle bugs,
31  * hence it is better to use this AtomicMovable class.
32  */
33 template <typename T>
34 class AtomicMovable : public std::atomic<T>
35 {
36 public:
37  //! default initialization (same as std::atomic)
38  AtomicMovable() = default;
39 
40  //! value initialization (same as std::atomic)
41  constexpr AtomicMovable(T desired)
42  : std::atomic<T>(desired) { }
43 
44  //! copy-construction (same as std::atomic)
45  AtomicMovable(const AtomicMovable& rhs) noexcept
46  : std::atomic<T>(T(rhs.load())) { }
47 
48  //! move-construction NOT same as std::atomic: load and move.
49  //! Requires T to have an ctor that takes an instance of T for
50  //! initialization.
51  AtomicMovable(const AtomicMovable&& rhs) noexcept
52  : std::atomic<T>(T(std::move(rhs.load()))) { }
53 
54  //! copy-assignment (same as std::atomic)
55  AtomicMovable& operator = (const AtomicMovable& rhs) noexcept {
56  std::atomic<T>::operator = (rhs.load());
57  return *this;
58  }
59 
60  //! move-assignment NOT same as std::atomic: load and move.
62  std::atomic<T>::operator = (std::move(rhs.load()));
63  return *this;
64  }
65 
66  //! assignment operator (same as std::atomic)
67  T operator = (T desired) noexcept { return std::atomic<T>::operator = (desired); }
68 };
69 
70 } // namespace common
71 } // namespace thrill
72 
73 #endif // !THRILL_COMMON_ATOMIC_MOVABLE_HEADER
74 
75 /******************************************************************************/
AtomicMovable & operator=(const AtomicMovable &rhs) noexcept
copy-assignment (same as std::atomic)
double T
AtomicMovable()=default
default initialization (same as std::atomic)
STL namespace.
constexpr AtomicMovable(T desired)
value initialization (same as std::atomic)
AtomicMovable(const AtomicMovable &&rhs) noexcept
AtomicMovable(const AtomicMovable &rhs) noexcept
copy-construction (same as std::atomic)
This is a derivative of std::atomic which enables easier and less error-prone writing of move-only cl...