-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Re-add Shared Pointer Class into platform features #7815
Merged
Merged
Changes from 5 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
9ebfbc0
Re-introduce a shared pointer class in mbed OS
f45642c
Make shared pointer thread safe and clean-up class and doc
2608478
Cleanup shared pointer implementation and add reset() methods
ac79b00
Cleanup description
6f3c07f
Optimize SharedPtr code
d9c1748
Update formatting for SharedPtr.h
3c599fe
Add Greentea tests for shared pointer
7086d69
Copy edit SharedPtr.h
298f847
Fix use_count() in SharedPtr
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,267 @@ | ||
/* 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, etc.) | ||
* | ||
* 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, "weak" references should be used 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(); | ||
return *_counter; | ||
core_util_critical_section_exit(); | ||
} 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__ |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you return prior exiting from critical section (is there an intention?)