Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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_atomic.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 empty SharedPtr not pointing to anything.
00080      */
00081     constexpr SharedPtr(std::nullptr_t) : SharedPtr()
00082     {
00083     }
00084 
00085     /**
00086      * @brief Create new SharedPtr
00087      * @param ptr Pointer to take control over
00088      */
00089     SharedPtr(T *ptr): _ptr(ptr), _counter(NULL)
00090     {
00091         // Allocate counter on the heap, so it can be shared
00092         if (_ptr != NULL) {
00093             _counter = new uint32_t;
00094             *_counter = 1;
00095         }
00096     }
00097 
00098     /**
00099      * @brief Destructor.
00100      * @details Decrement reference counter, and delete object if no longer pointed to.
00101      */
00102     ~SharedPtr()
00103     {
00104         decrement_counter();
00105     }
00106 
00107     /**
00108      * @brief Copy constructor.
00109      * @details Create new SharedPtr from other SharedPtr by
00110      *          copying pointer to original object and pointer to counter.
00111      * @param source Object being copied from.
00112      */
00113     SharedPtr(const SharedPtr &source): _ptr(source._ptr), _counter(source._counter)
00114     {
00115         // Increment reference counter
00116         if (_ptr != NULL) {
00117             core_util_atomic_incr_u32 (_counter, 1);
00118         }
00119     }
00120 
00121     /**
00122      * @brief Assignment operator.
00123      * @details Cleanup previous reference and assign new pointer and counter.
00124      * @param source Object being assigned from.
00125      * @return Object being assigned.
00126      */
00127     SharedPtr operator=(const SharedPtr &source)
00128     {
00129         if (this != &source) {
00130             // Clean up by decrementing counter
00131             decrement_counter();
00132 
00133             // Assign new values
00134             _ptr = source.get();
00135             _counter = source.get_counter();
00136 
00137             // Increment new counter
00138             if (_ptr != NULL) {
00139                 core_util_atomic_incr_u32 (_counter, 1);
00140             }
00141         }
00142 
00143         return *this;
00144     }
00145 
00146     /**
00147      * @brief Replaces the managed pointer with a new unmanaged pointer.
00148      * @param[in] ptr the new raw pointer to manage.
00149      */
00150     void reset(T *ptr)
00151     {
00152         // Clean up by decrementing counter
00153         decrement_counter();
00154 
00155         _ptr = ptr;
00156         if (ptr != NULL) {
00157             // Allocate counter on the heap, so it can be shared
00158             _counter = new uint32_t;
00159             *_counter = 1;
00160         } else {
00161             _counter = NULL;
00162         }
00163     }
00164 
00165     /**
00166      * @brief Replace the managed pointer with a NULL pointer.
00167      */
00168     void reset()
00169     {
00170         reset(NULL);
00171     }
00172 
00173     /**
00174      * @brief Raw pointer accessor.
00175      * @details Get raw pointer to object pointed to.
00176      * @return Pointer.
00177      */
00178     T *get() const
00179     {
00180         return _ptr;
00181     }
00182 
00183     /**
00184      * @brief Reference count accessor.
00185      * @return Reference count.
00186      */
00187     uint32_t use_count() const
00188     {
00189         if (_ptr != NULL) {
00190             return core_util_atomic_load_u32 (_counter);
00191         } else {
00192             return 0;
00193         }
00194     }
00195 
00196     /**
00197      * @brief Dereference object operator.
00198      * @details Override to return the object pointed to.
00199      */
00200     T &operator*() const
00201     {
00202         return *_ptr;
00203     }
00204 
00205     /**
00206      * @brief Dereference object member operator.
00207      * @details Override to return return member in object pointed to.
00208      */
00209     T *operator->() const
00210     {
00211         return _ptr;
00212     }
00213 
00214     /**
00215      * @brief Boolean conversion operator.
00216      * @return Whether or not the pointer is NULL.
00217      */
00218     operator bool() const
00219     {
00220         return (_ptr != NULL);
00221     }
00222 
00223 private:
00224     /**
00225      * @brief Get pointer to reference counter.
00226      * @return Pointer to reference counter.
00227      */
00228     uint32_t *get_counter() const
00229     {
00230         return _counter;
00231     }
00232 
00233     /**
00234      * @brief Decrement reference counter.
00235      * @details If count reaches zero, free counter and delete object pointed to.
00236      * Does not modify our own pointers - assumption is they will be overwritten
00237      * or destroyed immediately afterwards.
00238      */
00239     void decrement_counter()
00240     {
00241         if (_ptr != NULL) {
00242             if (core_util_atomic_decr_u32 (_counter, 1) == 0) {
00243                 delete _counter;
00244                 delete _ptr;
00245             }
00246         }
00247     }
00248 
00249 private:
00250     // Pointer to shared object
00251     T *_ptr;
00252 
00253     // Pointer to shared reference counter
00254     uint32_t *_counter;
00255 };
00256 
00257 /** Non-member relational operators.
00258   */
00259 template <class T, class U>
00260 bool operator== (const SharedPtr<T> &lhs, const SharedPtr<U> &rhs)
00261 {
00262     return (lhs.get() == rhs.get());
00263 }
00264 
00265 template <class T, typename U>
00266 bool operator== (const SharedPtr<T> &lhs, U rhs)
00267 {
00268     return (lhs.get() == (T *) rhs);
00269 }
00270 
00271 template <class T, typename U>
00272 bool operator== (U lhs, const SharedPtr<T> &rhs)
00273 {
00274     return ((T *) lhs == rhs.get());
00275 }
00276 
00277 /** Non-member relational operators.
00278   */
00279 template <class T, class U>
00280 bool operator!= (const SharedPtr<T> &lhs, const SharedPtr<U> &rhs)
00281 {
00282     return (lhs.get() != rhs.get());
00283 }
00284 
00285 template <class T, typename U>
00286 bool operator!= (const SharedPtr<T> &lhs, U rhs)
00287 {
00288     return (lhs.get() != (T *) rhs);
00289 }
00290 
00291 template <class T, typename U>
00292 bool operator!= (U lhs, const SharedPtr<T> &rhs)
00293 {
00294     return ((T *) lhs != rhs.get());
00295 }
00296 
00297 } /* namespace mbed */
00298 
00299 #ifndef MBED_NO_GLOBAL_USING_DIRECTIVE
00300 using mbed::SharedPtr;
00301 #endif
00302 
00303 #endif // __SHAREDPTR_H__