mbed library sources. Supersedes mbed-src.

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

Revision:
188:bcfe06ba3d64
Child:
189:f392fc9709a3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/platform/SharedPtr.h	Thu Nov 08 11:46:34 2018 +0000
@@ -0,0 +1,288 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2006-2018 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __SHAREDPTR_H__
+#define __SHAREDPTR_H__
+
+#include <stdlib.h>
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include "platform/mbed_critical.h"
+
+/** Shared pointer class.
+  *
+  * A shared pointer is a "smart" pointer that retains ownership of an object using
+  * reference counting accross all smart pointers referencing that object.
+  *
+  * @code
+  * #include "platform/SharedPtr.h"
+  *
+  * void test() {
+  *     struct MyStruct { int a; };
+  *
+  *     // Create shared pointer
+  *     SharedPtr<MyStruct> ptr( new MyStruct );
+  *
+  *     // Increase reference count
+  *     SharedPtr<MyStruct> ptr2( ptr );
+  *
+  *     ptr = NULL; // Reference to the struct instance is still held by ptr2
+  *
+  *     ptr2 = NULL; // The raw pointer is freed
+  * }
+  * @endcode
+  *
+  *
+  * It is similar to the std::shared_ptr class introduced in C++11;
+  * however, this is not a compatible implementation (no weak pointer, no make_shared, no custom deleters and so on.)
+  *
+  * Usage: SharedPtr<Class> ptr(new Class())
+  *
+  * When ptr is passed around by value, the copy constructor and
+  * destructor manages the reference count of the raw pointer.
+  * If the counter reaches zero, delete is called on the raw pointer.
+  *
+  * To avoid loops, use "weak" references by calling the original
+  * pointer directly through ptr.get().
+  */
+
+template <class T>
+class SharedPtr {
+public:
+    /**
+     * @brief Create empty SharedPtr not pointing to anything.
+     * @details Used for variable declaration.
+     */
+    SharedPtr(): _ptr(NULL), _counter(NULL)
+    {
+    }
+
+    /**
+     * @brief Create new SharedPtr
+     * @param ptr Pointer to take control over
+     */
+    SharedPtr(T *ptr): _ptr(ptr), _counter(NULL)
+    {
+        // Allocate counter on the heap, so it can be shared
+        if (_ptr != NULL) {
+            _counter = new uint32_t;
+            *_counter = 1;
+        }
+    }
+
+    /**
+     * @brief Destructor.
+     * @details Decrement reference counter, and delete object if no longer pointed to.
+     */
+    ~SharedPtr()
+    {
+        decrement_counter();
+    }
+
+    /**
+     * @brief Copy constructor.
+     * @details Create new SharedPtr from other SharedPtr by
+     *          copying pointer to original object and pointer to counter.
+     * @param source Object being copied from.
+     */
+    SharedPtr(const SharedPtr &source): _ptr(source._ptr), _counter(source._counter)
+    {
+        // Increment reference counter
+        if (_ptr != NULL) {
+            core_util_atomic_incr_u32(_counter, 1);
+        }
+    }
+
+    /**
+     * @brief Assignment operator.
+     * @details Cleanup previous reference and assign new pointer and counter.
+     * @param source Object being assigned from.
+     * @return Object being assigned.
+     */
+    SharedPtr operator=(const SharedPtr &source)
+    {
+        if (this != &source) {
+            // Clean up by decrementing counter
+            decrement_counter();
+
+            // Assign new values
+            _ptr = source.get();
+            _counter = source.get_counter();
+
+            // Increment new counter
+            if (_ptr != NULL) {
+                core_util_atomic_incr_u32(_counter, 1);
+            }
+        }
+
+        return *this;
+    }
+
+    /**
+     * @brief Replaces the managed pointer with a new unmanaged pointer.
+     * @param[in] ptr the new raw pointer to manage.
+     */
+    void reset(T *ptr)
+    {
+        // Clean up by decrementing counter
+        decrement_counter();
+
+        if (ptr != NULL) {
+            // Allocate counter on the heap, so it can be shared
+            _counter = new uint32_t;
+            *_counter = 1;
+        }
+    }
+
+    /**
+     * @brief Replace the managed pointer with a NULL pointer.
+     */
+    void reset()
+    {
+        reset(NULL);
+    }
+
+    /**
+     * @brief Raw pointer accessor.
+     * @details Get raw pointer to object pointed to.
+     * @return Pointer.
+     */
+    T *get() const
+    {
+        return _ptr;
+    }
+
+    /**
+     * @brief Reference count accessor.
+     * @return Reference count.
+     */
+    uint32_t use_count() const
+    {
+        if (_ptr != NULL) {
+            core_util_critical_section_enter();
+            uint32_t current_counter = *_counter;
+            core_util_critical_section_exit();
+            return current_counter;
+        } else {
+            return 0;
+        }
+    }
+
+    /**
+     * @brief Dereference object operator.
+     * @details Override to return the object pointed to.
+     */
+    T &operator*() const
+    {
+        return *_ptr;
+    }
+
+    /**
+     * @brief Dereference object member operator.
+     * @details Override to return return member in object pointed to.
+     */
+    T *operator->() const
+    {
+        return _ptr;
+    }
+
+    /**
+     * @brief Boolean conversion operator.
+     * @return Whether or not the pointer is NULL.
+     */
+    operator bool() const
+    {
+        return (_ptr != NULL);
+    }
+
+private:
+    /**
+     * @brief Get pointer to reference counter.
+     * @return Pointer to reference counter.
+     */
+    uint32_t *get_counter() const
+    {
+        return _counter;
+    }
+
+    /**
+     * @brief Decrement reference counter.
+     * @details If count reaches zero, free counter and delete object pointed to.
+     */
+    void decrement_counter()
+    {
+        if (_ptr != NULL) {
+            uint32_t new_value = core_util_atomic_decr_u32(_counter, 1);
+            if (new_value == 0) {
+                delete _counter;
+                _counter = NULL;
+                delete _ptr;
+                _ptr = NULL;
+            }
+        }
+    }
+
+private:
+    // Pointer to shared object
+    T *_ptr;
+
+    // Pointer to shared reference counter
+    uint32_t *_counter;
+};
+
+/** Non-member relational operators.
+  */
+template <class T, class U>
+bool operator== (const SharedPtr<T> &lhs, const SharedPtr<U> &rhs)
+{
+    return (lhs.get() == rhs.get());
+}
+
+template <class T, typename U>
+bool operator== (const SharedPtr<T> &lhs, U rhs)
+{
+    return (lhs.get() == (T *) rhs);
+}
+
+template <class T, typename U>
+bool operator== (U lhs, const SharedPtr<T> &rhs)
+{
+    return ((T *) lhs == rhs.get());
+}
+
+/** Non-member relational operators.
+  */
+template <class T, class U>
+bool operator!= (const SharedPtr<T> &lhs, const SharedPtr<U> &rhs)
+{
+    return (lhs.get() != rhs.get());
+}
+
+template <class T, typename U>
+bool operator!= (const SharedPtr<T> &lhs, U rhs)
+{
+    return (lhs.get() != (T *) rhs);
+}
+
+template <class T, typename U>
+bool operator!= (U lhs, const SharedPtr<T> &rhs)
+{
+    return ((T *) lhs != rhs.get());
+}
+
+#endif // __SHAREDPTR_H__