Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

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  *
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__