Mistake on this page?
Report an issue in GitHub or email us
SharedPtr.h
1 /* mbed Microcontroller Library
2  * Copyright (c) 2006-2018 ARM Limited
3  * SPDX-License-Identifier: Apache-2.0
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #ifndef __SHAREDPTR_H__
19 #define __SHAREDPTR_H__
20 
21 #include <stdlib.h>
22 
23 #include <stdint.h>
24 #include <stddef.h>
25 
26 #include "platform/mbed_atomic.h"
27 
28 namespace mbed {
29 
30 /** Shared pointer class.
31  *
32  * A shared pointer is a "smart" pointer that retains ownership of an object using
33  * reference counting across all smart pointers referencing that object.
34  *
35  * @code
36  * #include "platform/SharedPtr.h"
37  *
38  * void test() {
39  * struct MyStruct { int a; };
40  *
41  * // Create shared pointer
42  * SharedPtr<MyStruct> ptr( new MyStruct );
43  *
44  * // Increase reference count
45  * SharedPtr<MyStruct> ptr2( ptr );
46  *
47  * ptr = nullptr; // Reference to the struct instance is still held by ptr2
48  *
49  * ptr2 = nullptr; // The raw pointer is freed
50  * }
51  * @endcode
52  *
53  *
54  * It is similar to the std::shared_ptr class introduced in C++11;
55  * however, this is not a compatible implementation (no weak pointer, no make_shared, no custom deleters and so on.)
56  *
57  * Usage: SharedPtr<Class> ptr(new Class())
58  *
59  * When ptr is passed around by value, the copy constructor and
60  * destructor manages the reference count of the raw pointer.
61  * If the counter reaches zero, delete is called on the raw pointer.
62  *
63  * To avoid loops, use "weak" references by calling the original
64  * pointer directly through ptr.get().
65  */
66 
67 template <class T>
68 class SharedPtr {
69 public:
70  /**
71  * @brief Create empty SharedPtr not pointing to anything.
72  * @details Used for variable declaration.
73  */
74  constexpr SharedPtr(): _ptr(), _counter()
75  {
76  }
77 
78  /**
79  * @brief Create empty SharedPtr not pointing to anything.
80  */
81  constexpr SharedPtr(std::nullptr_t) : SharedPtr()
82  {
83  }
84 
85  /**
86  * @brief Create new SharedPtr
87  * @param ptr Pointer to take control over
88  */
89  SharedPtr(T *ptr): _ptr(ptr), _counter()
90  {
91  // Allocate counter on the heap, so it can be shared
92  if (_ptr != nullptr) {
93  _counter = new uint32_t(1);
94  }
95  }
96 
97  /**
98  * @brief Destructor.
99  * @details Decrement reference counter, and delete object if no longer pointed to.
100  */
102  {
103  decrement_counter();
104  }
105 
106  /**
107  * @brief Copy constructor.
108  * @details Create new SharedPtr from other SharedPtr by
109  * copying pointer to original object and pointer to counter.
110  * @param source Object being copied from.
111  */
112  SharedPtr(const SharedPtr &source): _ptr(source._ptr), _counter(source._counter)
113  {
114  // Increment reference counter
115  if (_ptr != nullptr) {
116  core_util_atomic_incr_u32(_counter, 1);
117  }
118  }
119 
120  /**
121  * @brief Move constructor.
122  * @details Create new SharedPtr from other SharedPtr by
123  * moving pointer to original object and pointer to counter.
124  * @param source Object being copied from.
125  */
126  SharedPtr(SharedPtr &&source): _ptr(source._ptr), _counter(source._counter)
127  {
128  source._ptr = nullptr;
129  source._counter = nullptr;
130  }
131 
132  /**
133  * @brief Copy assignment operator.
134  * @details Cleanup previous reference and assign new pointer and counter.
135  * @param source Object being assigned from.
136  * @return Object being assigned.
137  */
139  {
140  if (this != &source) {
141  // Clean up by decrementing counter
142  decrement_counter();
143 
144  // Assign new values
145  _ptr = source.get();
146  _counter = source.get_counter();
147 
148  // Increment new counter
149  if (_ptr != nullptr) {
150  core_util_atomic_incr_u32(_counter, 1);
151  }
152  }
153 
154  return *this;
155  }
156 
157  /**
158  * @brief Move assignment operator.
159  * @details Cleanup previous reference and assign new pointer and counter.
160  * @param source Object being assigned from.
161  * @return Object being assigned.
162  */
164  {
165  if (this != &source) {
166  // Clean up by decrementing counter
167  decrement_counter();
168 
169  // Assign new values
170  _ptr = source._ptr;
171  _counter = source._counter;
172 
173  source._ptr = nullptr;
174  source._counter = nullptr;
175  }
176 
177  return *this;
178  }
179 
180  /**
181  * @brief Replaces the managed pointer with a new unmanaged pointer.
182  * @param[in] ptr the new raw pointer to manage.
183  */
184  void reset(T *ptr)
185  {
186  // Clean up by decrementing counter
187  decrement_counter();
188 
189  _ptr = ptr;
190  if (ptr != nullptr) {
191  // Allocate counter on the heap, so it can be shared
192  _counter = new uint32_t(1);
193  } else {
194  _counter = nullptr;
195  }
196  }
197 
198  /**
199  * @brief Replace the managed pointer with a null pointer.
200  */
201  void reset()
202  {
203  // Clean up by decrementing counter
204  decrement_counter();
205 
206  _ptr = nullptr;
207  _counter = nullptr;
208  }
209 
210  /**
211  * @brief Raw pointer accessor.
212  * @details Get raw pointer to object pointed to.
213  * @return Pointer.
214  */
215  T *get() const
216  {
217  return _ptr;
218  }
219 
220  /**
221  * @brief Reference count accessor.
222  * @return Reference count.
223  */
224  uint32_t use_count() const
225  {
226  if (_ptr != nullptr) {
227  return core_util_atomic_load_u32(_counter);
228  } else {
229  return 0;
230  }
231  }
232 
233  /**
234  * @brief Dereference object operator.
235  * @details Override to return the object pointed to.
236  */
237  T &operator*() const
238  {
239  return *_ptr;
240  }
241 
242  /**
243  * @brief Dereference object member operator.
244  * @details Override to return return member in object pointed to.
245  */
246  T *operator->() const
247  {
248  return _ptr;
249  }
250 
251  /**
252  * @brief Boolean conversion operator.
253  * @return Whether or not the pointer is null.
254  */
255  operator bool() const
256  {
257  return _ptr != nullptr;
258  }
259 
260 private:
261  /**
262  * @brief Get pointer to reference counter.
263  * @return Pointer to reference counter.
264  */
265  uint32_t *get_counter() const
266  {
267  return _counter;
268  }
269 
270  /**
271  * @brief Decrement reference counter.
272  * @details If count reaches zero, free counter and delete object pointed to.
273  * Does not modify our own pointers - assumption is they will be overwritten
274  * or destroyed immediately afterwards.
275  */
276  void decrement_counter()
277  {
278  if (_ptr != nullptr) {
279  if (core_util_atomic_decr_u32(_counter, 1) == 0) {
280  delete _counter;
281  delete _ptr;
282  }
283  }
284  }
285 
286 private:
287  // Pointer to shared object
288  T *_ptr;
289 
290  // Pointer to shared reference counter
291  uint32_t *_counter;
292 };
293 
294 /** Non-member relational operators.
295  */
296 template <class T, class U>
297 bool operator== (const SharedPtr<T> &lhs, const SharedPtr<U> &rhs)
298 {
299  return (lhs.get() == rhs.get());
300 }
301 
302 template <class T, typename U>
303 bool operator== (const SharedPtr<T> &lhs, U rhs)
304 {
305  return (lhs.get() == (T *) rhs);
306 }
307 
308 template <class T, typename U>
309 bool operator== (U lhs, const SharedPtr<T> &rhs)
310 {
311  return ((T *) lhs == rhs.get());
312 }
313 
314 /** Non-member relational operators.
315  */
316 template <class T, class U>
317 bool operator!= (const SharedPtr<T> &lhs, const SharedPtr<U> &rhs)
318 {
319  return (lhs.get() != rhs.get());
320 }
321 
322 template <class T, typename U>
323 bool operator!= (const SharedPtr<T> &lhs, U rhs)
324 {
325  return (lhs.get() != (T *) rhs);
326 }
327 
328 template <class T, typename U>
329 bool operator!= (U lhs, const SharedPtr<T> &rhs)
330 {
331  return ((T *) lhs != rhs.get());
332 }
333 
334 } /* namespace mbed */
335 
336 #ifndef MBED_NO_GLOBAL_USING_DIRECTIVE
337 using mbed::SharedPtr;
338 #endif
339 
340 #endif // __SHAREDPTR_H__
uint32_t use_count() const
Reference count accessor.
Definition: SharedPtr.h:224
T * operator->() const
Dereference object member operator.
Definition: SharedPtr.h:246
SharedPtr operator=(const SharedPtr &source)
Copy assignment operator.
Definition: SharedPtr.h:138
~SharedPtr()
Destructor.
Definition: SharedPtr.h:101
uint32_t core_util_atomic_decr_u32(volatile uint32_t *valuePtr, uint32_t delta)
Atomic decrement.
Shared pointer class.
Definition: SharedPtr.h:68
SharedPtr(T *ptr)
Create new SharedPtr.
Definition: SharedPtr.h:89
constexpr SharedPtr(std::nullptr_t)
Create empty SharedPtr not pointing to anything.
Definition: SharedPtr.h:81
constexpr SharedPtr()
Create empty SharedPtr not pointing to anything.
Definition: SharedPtr.h:74
SharedPtr(SharedPtr &&source)
Move constructor.
Definition: SharedPtr.h:126
void operator!=(const SafeBool< T > &lhs, const SafeBool< U > &rhs)
Avoid conversion to bool between different classes.
void reset(T *ptr)
Replaces the managed pointer with a new unmanaged pointer.
Definition: SharedPtr.h:184
T * get() const
Raw pointer accessor.
Definition: SharedPtr.h:215
SharedPtr(const SharedPtr &source)
Copy constructor.
Definition: SharedPtr.h:112
void operator==(const SafeBool< T > &lhs, const SafeBool< U > &rhs)
Avoid conversion to bool between different classes.
uint32_t core_util_atomic_incr_u32(volatile uint32_t *valuePtr, uint32_t delta)
Atomic increment.
T & operator*() const
Dereference object operator.
Definition: SharedPtr.h:237
void reset()
Replace the managed pointer with a null pointer.
Definition: SharedPtr.h:201
MBED_FORCEINLINE uint32_t core_util_atomic_load_u32(const volatile uint32_t *valuePtr)
Atomic load.
Definition: ATHandler.h:46
SharedPtr operator=(SharedPtr &&source)
Move assignment operator.
Definition: SharedPtr.h:163
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.