source: mainline/uspace/lib/cpp/include/internal/memory/weak_ptr.hpp@ baed175

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since baed175 was baed175, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added weak_ptr

  • Property mode set to 100644
File size: 6.2 KB
Line 
1/*
2 * Copyright (c) 2018 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_INTERNAL_MEMORY_WEAK_PTR
30#define LIBCPP_INTERNAL_MEMORY_WEAK_PTR
31
32#include <internal/memory/shared_payload.hpp>
33#include <type_traits>
34#include <utility>
35
36namespace std
37{
38 template<class T>
39 class shared_ptr;
40
41 /**
42 * 20.8.2.3, class template weak_ptr:
43 */
44
45 template<class T>
46 class weak_ptr
47 {
48 public:
49 using element_type = T;
50
51 /**
52 * 20.8.2.3.1, constructors:
53 */
54
55 constexpr weak_ptr() noexcept
56 : payload_{}
57 { /* DUMMY BODY */ }
58
59 template<class U>
60 weak_ptr(
61 const shared_ptr<U>& other,
62 enable_if_t<is_convertible_v<U*, element_type*>>* = nullptr
63 ) noexcept
64 : payload_{other.payload_}
65 {
66 if (payload_)
67 payload_->increment_weak();
68 }
69
70 weak_ptr(const weak_ptr& other) noexcept
71 : payload_{other.payload_}
72 {
73 if (payload_)
74 payload_->increment_weak();
75 }
76
77 template<class U>
78 weak_ptr(
79 const weak_ptr<U>& other,
80 enable_if_t<is_convertible_v<U*, element_type*>>* = nullptr
81 ) noexcept
82 : payload_{other.payload_}
83 {
84 if (payload_)
85 payload_->increment_weak();
86 }
87
88 weak_ptr(weak_ptr&& other) noexcept
89 : payload_{other.payload_}
90 {
91 other.payload_ = nullptr;
92 }
93
94 template<class U>
95 weak_ptr(
96 weak_ptr<U>&& other,
97 enable_if_t<is_convertible_v<U*, element_type*>>* = nullptr
98 ) noexcept
99 : payload_{other.payload_}
100 {
101 other.payload_ = nullptr;
102 }
103
104 /**
105 * 20.8.2.3.2, destructor:
106 */
107
108 ~weak_ptr()
109 {
110 remove_payload_();
111 }
112
113 /**
114 * 20.8.2.3.3, assignment:
115 */
116
117 weak_ptr& operator=(const weak_ptr& rhs) noexcept
118 {
119 remove_payload_();
120
121 payload_ = rhs.payload_;
122 if (payload_)
123 payload_->increment_weak();
124
125 return *this;
126 }
127
128 template<class U>
129 weak_ptr& operator=(const weak_ptr<U>& rhs) noexcept
130 {
131 weak_ptr{rhs}.swap(*this);
132
133 return *this;
134 }
135
136 template<class U>
137 weak_ptr& operator=(const shared_ptr<U>& rhs) noexcept
138 {
139 weak_ptr{rhs}.swap(*this);
140
141 return *this;
142 }
143
144 weak_ptr& operator=(weak_ptr&& rhs) noexcept
145 {
146 weak_ptr{move(rhs)}.swap(*this);
147
148 return *this;
149 }
150
151 template<class U>
152 weak_ptr& operator=(
153 weak_ptr<U>&& rhs
154 ) noexcept
155 {
156 weak_ptr{move(rhs)}.swap(*this);
157
158 return *this;
159 }
160
161 /**
162 * 20.8.2.3.4, modifiers:
163 */
164
165 void swap(weak_ptr& other) noexcept
166 {
167 std::swap(payload_, other.payload_);
168 }
169
170 void reset() noexcept
171 {
172 weak_ptr{}.swap(*this);
173 }
174
175 /**
176 * 20.8.2.3.5, observers:
177 */
178
179 long use_count() const noexcept
180 {
181 if (payload_)
182 return payload_->refs();
183 else
184 return 0L;
185 }
186
187 bool expired() const noexcept
188 {
189 return use_count() == 0L;
190 }
191
192 shared_ptr<T> lock() const noexcept
193 {
194 return shared_ptr{payload_->lock()};
195 }
196
197 template<class U>
198 bool owner_before(const shared_ptr<U>& other) const
199 {
200 return payload_ < other.payload_;
201 }
202
203 template<class U>
204 bool owner_before(const weak_ptr<U>& other) const
205 {
206 return payload_ < other.payload_;
207 }
208
209 private:
210 aux::shared_payload_base<T>* payload_;
211
212 void remove_payload_()
213 {
214 if (payload_ && payload_->decrement_weak())
215 payload_->destroy();
216 payload_ = nullptr;
217 }
218
219 template<class U>
220 friend class shared_ptr;
221 };
222
223 /**
224 * 20.8.2.3.6, specialized algorithms:
225 */
226
227 template<class T>
228 void swap(weak_ptr<T>& lhs, weak_ptr<T>& rhs) noexcept
229 {
230 lhs.swap(rhs);
231 }
232}
233
234#endif
Note: See TracBrowser for help on using the repository browser.