/
cow_ptr.hpp
140 lines (113 loc) · 5.08 KB
/
cow_ptr.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_COW_PTR_HPP
#define CPPA_COW_PTR_HPP
#include <cstddef>
#include <stdexcept>
#include <type_traits>
#include "cppa/intrusive_ptr.hpp"
#include "cppa/util/comparable.hpp"
namespace cppa {
/**
* @ingroup CopyOnWrite
* @brief A copy-on-write smart pointer implementation.
* @tparam T A class that provides a copy() member function and has
* the same interface as or is a subclass of
* {@link ref_counted}.
*/
template<typename T>
class cow_ptr : util::comparable<cow_ptr<T> >,
util::comparable<cow_ptr<T>, const T*>,
util::comparable<cow_ptr<T>, std::nullptr_t> {
public:
typedef T* pointer;
typedef const T* const_pointer;
typedef T element_type;
typedef T& reference;
typedef const T& const_reference;
constexpr cow_ptr() : m_ptr() { }
cow_ptr(pointer raw_ptr) : m_ptr(raw_ptr) { }
cow_ptr(cow_ptr&&) = default;
cow_ptr(const cow_ptr&) = default;
cow_ptr& operator=(cow_ptr&&) = default;
cow_ptr& operator=(const cow_ptr&) = default;
template<typename Y>
cow_ptr(cow_ptr<Y> other) : m_ptr(other.m_ptr.release()) {
static_assert(std::is_convertible<Y*, T*>::value,
"Y* is not assignable to T*");
}
inline void swap(cow_ptr& other) { m_ptr.swap(other.m_ptr); }
template<typename Y>
cow_ptr& operator=(cow_ptr<Y> other) {
m_ptr = std::move(other.m_ptr);
return *this;
}
void detach() { static_cast<void>(get_detached()); }
inline void reset(T* value = nullptr) { m_ptr.reset(value); }
// non-const access (detaches this pointer)
inline pointer get() { return (m_ptr) ? get_detached() : nullptr; }
inline pointer operator->() { return get_detached(); }
inline reference operator*() { return *get_detached(); }
// const access (does not detach this pointer)
inline const_pointer get() const { return m_ptr.get(); }
inline const_pointer operator->() const { return get(); }
inline const_reference operator*() const { return *get(); }
inline explicit operator bool() const { return static_cast<bool>(m_ptr); }
template<typename Arg>
inline ptrdiff_t compare(Arg&& what) const {
return m_ptr.compare(std::forward<Arg>(what));
}
private:
intrusive_ptr<T> m_ptr;
pointer get_detached() {
auto ptr = m_ptr.get();
if (!ptr->unique()) {
pointer new_ptr = ptr->copy();
reset(new_ptr);
return new_ptr;
}
return ptr;
}
};
/**
* @relates cow_ptr
*/
template<typename X, typename Y>
inline bool operator==(const cow_ptr<X>& lhs, const cow_ptr<Y>& rhs) {
return lhs.get() == rhs.get();
}
/**
* @relates cow_ptr
*/
template<typename X, typename Y>
inline bool operator!=(const cow_ptr<X>& lhs, const cow_ptr<Y>& rhs) {
return !(lhs == rhs);
}
} // namespace cppa
#endif // CPPA_COW_PTR_HPP