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 = NULL; // Reference to the struct instance is still held by ptr2
48  *
49  * ptr2 = NULL; // 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  SharedPtr(): _ptr(NULL), _counter(NULL)
75  {
76  }
77 
78  /**
79  * @brief Create new SharedPtr
80  * @param ptr Pointer to take control over
81  */
82  SharedPtr(T *ptr): _ptr(ptr), _counter(NULL)
83  {
84  // Allocate counter on the heap, so it can be shared
85  if (_ptr != NULL) {
86  _counter = new uint32_t;
87  *_counter = 1;
88  }
89  }
90 
91  /**
92  * @brief Destructor.
93  * @details Decrement reference counter, and delete object if no longer pointed to.
94  */
96  {
97  decrement_counter();
98  }
99 
100  /**
101  * @brief Copy constructor.
102  * @details Create new SharedPtr from other SharedPtr by
103  * copying pointer to original object and pointer to counter.
104  * @param source Object being copied from.
105  */
106  SharedPtr(const SharedPtr &source): _ptr(source._ptr), _counter(source._counter)
107  {
108  // Increment reference counter
109  if (_ptr != NULL) {
110  core_util_atomic_incr_u32(_counter, 1);
111  }
112  }
113 
114  /**
115  * @brief Assignment operator.
116  * @details Cleanup previous reference and assign new pointer and counter.
117  * @param source Object being assigned from.
118  * @return Object being assigned.
119  */
121  {
122  if (this != &source) {
123  // Clean up by decrementing counter
124  decrement_counter();
125 
126  // Assign new values
127  _ptr = source.get();
128  _counter = source.get_counter();
129 
130  // Increment new counter
131  if (_ptr != NULL) {
132  core_util_atomic_incr_u32(_counter, 1);
133  }
134  }
135 
136  return *this;
137  }
138 
139  /**
140  * @brief Replaces the managed pointer with a new unmanaged pointer.
141  * @param[in] ptr the new raw pointer to manage.
142  */
143  void reset(T *ptr)
144  {
145  // Clean up by decrementing counter
146  decrement_counter();
147 
148  _ptr = ptr;
149  if (ptr != NULL) {
150  // Allocate counter on the heap, so it can be shared
151  _counter = new uint32_t;
152  *_counter = 1;
153  } else {
154  _counter = NULL;
155  }
156  }
157 
158  /**
159  * @brief Replace the managed pointer with a NULL pointer.
160  */
161  void reset()
162  {
163  reset(NULL);
164  }
165 
166  /**
167  * @brief Raw pointer accessor.
168  * @details Get raw pointer to object pointed to.
169  * @return Pointer.
170  */
171  T *get() const
172  {
173  return _ptr;
174  }
175 
176  /**
177  * @brief Reference count accessor.
178  * @return Reference count.
179  */
180  uint32_t use_count() const
181  {
182  if (_ptr != NULL) {
183  return core_util_atomic_load_u32(_counter);
184  } else {
185  return 0;
186  }
187  }
188 
189  /**
190  * @brief Dereference object operator.
191  * @details Override to return the object pointed to.
192  */
193  T &operator*() const
194  {
195  return *_ptr;
196  }
197 
198  /**
199  * @brief Dereference object member operator.
200  * @details Override to return return member in object pointed to.
201  */
202  T *operator->() const
203  {
204  return _ptr;
205  }
206 
207  /**
208  * @brief Boolean conversion operator.
209  * @return Whether or not the pointer is NULL.
210  */
211  operator bool() const
212  {
213  return (_ptr != NULL);
214  }
215 
216 private:
217  /**
218  * @brief Get pointer to reference counter.
219  * @return Pointer to reference counter.
220  */
221  uint32_t *get_counter() const
222  {
223  return _counter;
224  }
225 
226  /**
227  * @brief Decrement reference counter.
228  * @details If count reaches zero, free counter and delete object pointed to.
229  * Does not modify our own pointers - assumption is they will be overwritten
230  * or destroyed immediately afterwards.
231  */
232  void decrement_counter()
233  {
234  if (_ptr != NULL) {
235  if (core_util_atomic_decr_u32(_counter, 1) == 0) {
236  delete _counter;
237  delete _ptr;
238  }
239  }
240  }
241 
242 private:
243  // Pointer to shared object
244  T *_ptr;
245 
246  // Pointer to shared reference counter
247  uint32_t *_counter;
248 };
249 
250 /** Non-member relational operators.
251  */
252 template <class T, class U>
253 bool operator== (const SharedPtr<T> &lhs, const SharedPtr<U> &rhs)
254 {
255  return (lhs.get() == rhs.get());
256 }
257 
258 template <class T, typename U>
259 bool operator== (const SharedPtr<T> &lhs, U rhs)
260 {
261  return (lhs.get() == (T *) rhs);
262 }
263 
264 template <class T, typename U>
265 bool operator== (U lhs, const SharedPtr<T> &rhs)
266 {
267  return ((T *) lhs == rhs.get());
268 }
269 
270 /** Non-member relational operators.
271  */
272 template <class T, class U>
273 bool operator!= (const SharedPtr<T> &lhs, const SharedPtr<U> &rhs)
274 {
275  return (lhs.get() != rhs.get());
276 }
277 
278 template <class T, typename U>
279 bool operator!= (const SharedPtr<T> &lhs, U rhs)
280 {
281  return (lhs.get() != (T *) rhs);
282 }
283 
284 template <class T, typename U>
285 bool operator!= (U lhs, const SharedPtr<T> &rhs)
286 {
287  return ((T *) lhs != rhs.get());
288 }
289 
290 } /* namespace mbed */
291 
292 #ifndef MBED_NO_GLOBAL_USING_DIRECTIVE
293 using mbed::SharedPtr;
294 #endif
295 
296 #endif // __SHAREDPTR_H__
uint32_t use_count() const
Reference count accessor.
Definition: SharedPtr.h:180
T * operator->() const
Dereference object member operator.
Definition: SharedPtr.h:202
SharedPtr operator=(const SharedPtr &source)
Assignment operator.
Definition: SharedPtr.h:120
~SharedPtr()
Destructor.
Definition: SharedPtr.h:95
SharedPtr()
Create empty SharedPtr not pointing to anything.
Definition: SharedPtr.h:74
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:82
void operator!=(const SafeBool< T > &lhs, const SafeBool< U > &rhs)
Avoid conversion to bool between different classes.
Definition: SafeBool.h:142
void reset(T *ptr)
Replaces the managed pointer with a new unmanaged pointer.
Definition: SharedPtr.h:143
T * get() const
Raw pointer accessor.
Definition: SharedPtr.h:171
SharedPtr(const SharedPtr &source)
Copy constructor.
Definition: SharedPtr.h:106
void operator==(const SafeBool< T > &lhs, const SafeBool< U > &rhs)
Avoid conversion to bool between different classes.
Definition: SafeBool.h:130
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:193
void reset()
Replace the managed pointer with a NULL pointer.
Definition: SharedPtr.h:161
MBED_FORCEINLINE uint32_t core_util_atomic_load_u32(const volatile uint32_t *valuePtr)
Atomic load.
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.