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.
Diff: mbed-os/platform/SharedPtr.h
- Revision:
- 0:8fdf9a60065b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os/platform/SharedPtr.h Wed Oct 10 00:33:53 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__