mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SharedPtr.h Source File

SharedPtr.h

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