Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
SharedPtr.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2018 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #ifndef __SHAREDPTR_H__ 00018 #define __SHAREDPTR_H__ 00019 00020 #include <stdlib.h> 00021 00022 #include <stdint.h> 00023 #include <stddef.h> 00024 00025 #include "platform/mbed_critical.h" 00026 00027 /** Shared pointer class. 00028 * 00029 * A shared pointer is a "smart" pointer that retains ownership of an object using 00030 * reference counting accross all smart pointers referencing that object. 00031 * 00032 * @code 00033 * #include "platform/SharedPtr.h" 00034 * 00035 * void test() { 00036 * struct MyStruct { int a; }; 00037 * 00038 * // Create shared pointer 00039 * SharedPtr<MyStruct> ptr( new MyStruct ); 00040 * 00041 * // Increase reference count 00042 * SharedPtr<MyStruct> ptr2( ptr ); 00043 * 00044 * ptr = NULL; // Reference to the struct instance is still held by ptr2 00045 * 00046 * ptr2 = NULL; // The raw pointer is freed 00047 * } 00048 * @endcode 00049 * 00050 * 00051 * It is similar to the std::shared_ptr class introduced in C++11; 00052 * however, this is not a compatible implementation (no weak pointer, no make_shared, no custom deleters and so on.) 00053 * 00054 * Usage: SharedPtr<Class> ptr(new Class()) 00055 * 00056 * When ptr is passed around by value, the copy constructor and 00057 * destructor manages the reference count of the raw pointer. 00058 * If the counter reaches zero, delete is called on the raw pointer. 00059 * 00060 * To avoid loops, use "weak" references by calling the original 00061 * pointer directly through ptr.get(). 00062 */ 00063 00064 template <class T> 00065 class SharedPtr { 00066 public: 00067 /** 00068 * @brief Create empty SharedPtr not pointing to anything. 00069 * @details Used for variable declaration. 00070 */ 00071 SharedPtr(): _ptr(NULL), _counter(NULL) 00072 { 00073 } 00074 00075 /** 00076 * @brief Create new SharedPtr 00077 * @param ptr Pointer to take control over 00078 */ 00079 SharedPtr(T *ptr): _ptr(ptr), _counter(NULL) 00080 { 00081 // Allocate counter on the heap, so it can be shared 00082 if (_ptr != NULL) { 00083 _counter = new uint32_t; 00084 *_counter = 1; 00085 } 00086 } 00087 00088 /** 00089 * @brief Destructor. 00090 * @details Decrement reference counter, and delete object if no longer pointed to. 00091 */ 00092 ~SharedPtr() 00093 { 00094 decrement_counter(); 00095 } 00096 00097 /** 00098 * @brief Copy constructor. 00099 * @details Create new SharedPtr from other SharedPtr by 00100 * copying pointer to original object and pointer to counter. 00101 * @param source Object being copied from. 00102 */ 00103 SharedPtr(const SharedPtr &source): _ptr(source._ptr), _counter(source._counter) 00104 { 00105 // Increment reference counter 00106 if (_ptr != NULL) { 00107 core_util_atomic_incr_u32(_counter, 1); 00108 } 00109 } 00110 00111 /** 00112 * @brief Assignment operator. 00113 * @details Cleanup previous reference and assign new pointer and counter. 00114 * @param source Object being assigned from. 00115 * @return Object being assigned. 00116 */ 00117 SharedPtr operator=(const SharedPtr &source) 00118 { 00119 if (this != &source) { 00120 // Clean up by decrementing counter 00121 decrement_counter(); 00122 00123 // Assign new values 00124 _ptr = source.get(); 00125 _counter = source.get_counter(); 00126 00127 // Increment new counter 00128 if (_ptr != NULL) { 00129 core_util_atomic_incr_u32(_counter, 1); 00130 } 00131 } 00132 00133 return *this; 00134 } 00135 00136 /** 00137 * @brief Replaces the managed pointer with a new unmanaged pointer. 00138 * @param[in] ptr the new raw pointer to manage. 00139 */ 00140 void reset(T *ptr) 00141 { 00142 // Clean up by decrementing counter 00143 decrement_counter(); 00144 00145 if (ptr != NULL) { 00146 // Allocate counter on the heap, so it can be shared 00147 _counter = new uint32_t; 00148 *_counter = 1; 00149 } 00150 } 00151 00152 /** 00153 * @brief Replace the managed pointer with a NULL pointer. 00154 */ 00155 void reset() 00156 { 00157 reset(NULL); 00158 } 00159 00160 /** 00161 * @brief Raw pointer accessor. 00162 * @details Get raw pointer to object pointed to. 00163 * @return Pointer. 00164 */ 00165 T *get() const 00166 { 00167 return _ptr; 00168 } 00169 00170 /** 00171 * @brief Reference count accessor. 00172 * @return Reference count. 00173 */ 00174 uint32_t use_count() const 00175 { 00176 if (_ptr != NULL) { 00177 core_util_critical_section_enter(); 00178 uint32_t current_counter = *_counter; 00179 core_util_critical_section_exit(); 00180 return current_counter; 00181 } else { 00182 return 0; 00183 } 00184 } 00185 00186 /** 00187 * @brief Dereference object operator. 00188 * @details Override to return the object pointed to. 00189 */ 00190 T &operator*() const 00191 { 00192 return *_ptr; 00193 } 00194 00195 /** 00196 * @brief Dereference object member operator. 00197 * @details Override to return return member in object pointed to. 00198 */ 00199 T *operator->() const 00200 { 00201 return _ptr; 00202 } 00203 00204 /** 00205 * @brief Boolean conversion operator. 00206 * @return Whether or not the pointer is NULL. 00207 */ 00208 operator bool() const 00209 { 00210 return (_ptr != NULL); 00211 } 00212 00213 private: 00214 /** 00215 * @brief Get pointer to reference counter. 00216 * @return Pointer to reference counter. 00217 */ 00218 uint32_t *get_counter() const 00219 { 00220 return _counter; 00221 } 00222 00223 /** 00224 * @brief Decrement reference counter. 00225 * @details If count reaches zero, free counter and delete object pointed to. 00226 */ 00227 void decrement_counter() 00228 { 00229 if (_ptr != NULL) { 00230 uint32_t new_value = core_util_atomic_decr_u32(_counter, 1); 00231 if (new_value == 0) { 00232 delete _counter; 00233 _counter = NULL; 00234 delete _ptr; 00235 _ptr = NULL; 00236 } 00237 } 00238 } 00239 00240 private: 00241 // Pointer to shared object 00242 T *_ptr; 00243 00244 // Pointer to shared reference counter 00245 uint32_t *_counter; 00246 }; 00247 00248 /** Non-member relational operators. 00249 */ 00250 template <class T, class U> 00251 bool operator== (const SharedPtr<T> &lhs, const SharedPtr<U> &rhs) 00252 { 00253 return (lhs.get() == rhs.get()); 00254 } 00255 00256 template <class T, typename U> 00257 bool operator== (const SharedPtr<T> &lhs, U rhs) 00258 { 00259 return (lhs.get() == (T *) rhs); 00260 } 00261 00262 template <class T, typename U> 00263 bool operator== (U lhs, const SharedPtr<T> &rhs) 00264 { 00265 return ((T *) lhs == rhs.get()); 00266 } 00267 00268 /** Non-member relational operators. 00269 */ 00270 template <class T, class U> 00271 bool operator!= (const SharedPtr<T> &lhs, const SharedPtr<U> &rhs) 00272 { 00273 return (lhs.get() != rhs.get()); 00274 } 00275 00276 template <class T, typename U> 00277 bool operator!= (const SharedPtr<T> &lhs, U rhs) 00278 { 00279 return (lhs.get() != (T *) rhs); 00280 } 00281 00282 template <class T, typename U> 00283 bool operator!= (U lhs, const SharedPtr<T> &rhs) 00284 { 00285 return ((T *) lhs != rhs.get()); 00286 } 00287 00288 #endif // __SHAREDPTR_H__
Generated on Tue Aug 9 2022 00:37:19 by
1.7.2