-
Notifications
You must be signed in to change notification settings - Fork 285
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add first draft of sub_ptr and ob_ptr
- Loading branch information
Showing
2 changed files
with
422 additions
and
0 deletions.
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,286 @@ | ||
/* | ||
* Copyright (c) 2015, Georgia Tech Research Corporation | ||
* All rights reserved. | ||
* | ||
* Author(s): Jeongseok Lee <jslee02@gmail.com> | ||
* | ||
* Georgia Tech Graphics Lab and Humanoid Robotics Lab | ||
* | ||
* Directed by Prof. C. Karen Liu and Prof. Mike Stilman | ||
* <karenliu@cc.gatech.edu> <mstilman@cc.gatech.edu> | ||
* | ||
* This file is provided under the following "BSD-style" License: | ||
* Redistribution and use in source and binary forms, with or | ||
* without modification, are permitted provided that the following | ||
* conditions are met: | ||
* * Redistributions of source code must retain the above copyright | ||
* notice, this list of conditions and the following disclaimer. | ||
* * Redistributions in binary form must reproduce the above | ||
* copyright notice, this list of conditions and the following | ||
* disclaimer in the documentation and/or other materials provided | ||
* with the distribution. | ||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND | ||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, | ||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | ||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR | ||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | ||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | ||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
* POSSIBILITY OF SUCH DAMAGE. | ||
*/ | ||
|
||
#ifndef DART_COMMON_SMARTPOINTER_H_ | ||
#define DART_COMMON_SMARTPOINTER_H_ | ||
|
||
#include <iostream> | ||
#include <memory> | ||
|
||
namespace dart { | ||
namespace common { | ||
|
||
namespace smart_ptr { | ||
namespace detail { | ||
|
||
template <class T> | ||
struct data_body | ||
{ | ||
data_body(T* _ptr) : observer_count(0), data(_ptr) {} | ||
~data_body() {} | ||
bool valid() const { return nullptr != data; } | ||
size_t observer_count; | ||
T* data; | ||
}; | ||
|
||
} // namespace detail | ||
} // namespace smart_ptr | ||
|
||
template <class T> | ||
class observer_pointer; | ||
|
||
/// subject_ptr is very similar to std::unique_ptr. | ||
/// subject_ptr is resposible to delete data | ||
template <class T> | ||
class subject_pointer | ||
{ | ||
public: | ||
|
||
friend class observer_pointer<T>; | ||
|
||
/// Default constructor | ||
constexpr subject_pointer() : mDataBody(nullptr) {} | ||
|
||
/// Constructor with null pointer | ||
constexpr subject_pointer(std::nullptr_t) : mDataBody(nullptr) {} | ||
|
||
/// Constructor with given data pointer | ||
subject_pointer(T* _ptr) | ||
: mDataBody(new smart_ptr::detail::data_body<T>(_ptr)) {} | ||
|
||
/// Non-copyable | ||
subject_pointer(const subject_pointer<T>&) = delete; | ||
|
||
/// Move constructor | ||
subject_pointer(subject_pointer<T>&& _other) | ||
: mDataBody(std::move(_other.mDataBody)) | ||
{ | ||
_other.mDataBody = nullptr; | ||
} | ||
|
||
/// | ||
~subject_pointer() | ||
{ | ||
if (mDataBody) | ||
{ | ||
delete mDataBody->data; | ||
mDataBody->data = nullptr; | ||
|
||
if (0 == mDataBody->observer_count) | ||
delete mDataBody; | ||
} | ||
} | ||
|
||
/// Non-assignable | ||
subject_pointer& operator=(const subject_pointer<T>&) = delete; | ||
|
||
/// Move assignment | ||
subject_pointer& operator=(subject_pointer<T>&& _other) | ||
{ | ||
if (this == &_other) | ||
return *this; | ||
|
||
mDataBody = std::move(_other.mDataBody); | ||
_other.mDataBody = nullptr; | ||
return *this; | ||
} | ||
|
||
/// Implicit conversion to pointer type | ||
operator T*() const { return mDataBody->data; } | ||
|
||
/// Dereferencing operator | ||
T& operator*() const { return *mDataBody->data; } | ||
|
||
/// Dereferencing operation | ||
T* operator->() { return mDataBody->data; } | ||
|
||
/// Get the subscription of this subject_pointer | ||
T* get() const { return mDataBody->data; } | ||
|
||
/// Replaces the managed object | ||
void reset(subject_pointer<T> _ptr = subject_pointer<T>()) | ||
{ | ||
|
||
} | ||
|
||
/// Get true if the data is still not deleted | ||
bool valid() | ||
{ | ||
if (mDataBody) | ||
return mDataBody->valid(); | ||
else | ||
return false; | ||
} | ||
|
||
/// Get number of observerse | ||
size_t getNumObservers() const { return mDataBody->observer_count; } | ||
|
||
protected: | ||
/// The actual data will be stored here. | ||
smart_ptr::detail::data_body<T>* mDataBody; | ||
}; | ||
|
||
template <class T> | ||
class observer_pointer | ||
{ | ||
public: | ||
/// Default constructor | ||
constexpr observer_pointer() : mDataBody(nullptr) {} | ||
|
||
/// Constructor with null pointer | ||
constexpr observer_pointer(std::nullptr_t) : mDataBody(nullptr) {} | ||
|
||
/// Constructor given observer_pointer | ||
observer_pointer(const observer_pointer<T>& _obPtr) | ||
: mDataBody(_obPtr.mDataBody) | ||
{ | ||
if (mDataBody) | ||
mDataBody->observer_count++; | ||
} | ||
|
||
/// Move constructor given observer_pointer | ||
observer_pointer(observer_pointer<T>&& _obPtr) | ||
: mDataBody(std::move(_obPtr.mDataBody)) | ||
{ | ||
_obPtr.mDataBody = nullptr; | ||
} | ||
|
||
/// Constructor given subject_pointer | ||
observer_pointer(const subject_pointer<T>& _subPtr) | ||
: mDataBody(_subPtr.mDataBody) | ||
{ | ||
if (mDataBody) | ||
mDataBody->observer_count++; | ||
} | ||
|
||
/// Destructor | ||
~observer_pointer() | ||
{ | ||
releaseDataBody(); | ||
} | ||
|
||
/// Assign onther observer_pointer | ||
observer_pointer& operator=(const observer_pointer<T>& _other) | ||
{ | ||
if (this == &_other) | ||
return *this; | ||
|
||
// If observing the same data, then do nothing | ||
if (mDataBody == _other.mDataBody) | ||
return *this; | ||
|
||
releaseDataBody(); | ||
|
||
mDataBody = _other.mDataBody; | ||
|
||
if (mDataBody) | ||
mDataBody->observer_count++; | ||
|
||
return *this; | ||
} | ||
|
||
/// Move onther observer_pointer | ||
observer_pointer& operator=(observer_pointer<T>&& _other) | ||
{ | ||
if (this == &_other) | ||
return *this; | ||
|
||
mDataBody = std::move(_other.mDataBody); | ||
_other.mDataBody = nullptr; | ||
return *this; | ||
} | ||
|
||
/// Assign subject_pointer | ||
observer_pointer& operator=(const subject_pointer<T>& _other) | ||
{ | ||
releaseDataBody(); | ||
|
||
mDataBody = _other.mDataBody; | ||
|
||
if (mDataBody) | ||
mDataBody->observer_count++; | ||
|
||
return *this; | ||
} | ||
|
||
/// Implicit conversion to pointer type | ||
operator T*() const { return mDataBody->data; } | ||
|
||
/// Dereferencing operator | ||
T& operator*() const { return *mDataBody->data; } | ||
|
||
/// Dereferencing operation | ||
T* operator->() { return mDataBody->data; } | ||
|
||
/// Get the subscription of this observer_pointer | ||
T* get() const { return mDataBody->data; } | ||
|
||
/// True if and only if this observer_pointer still points to a valid data | ||
bool valid() | ||
{ | ||
if (mDataBody) | ||
return mDataBody->valid(); | ||
else | ||
return false; | ||
} | ||
|
||
private: | ||
/// | ||
void releaseDataBody() | ||
{ | ||
if (mDataBody) | ||
{ | ||
mDataBody->observer_count--; | ||
if (0 == mDataBody->observer_count && !mDataBody->valid()) | ||
delete mDataBody; | ||
} | ||
} | ||
|
||
/// Data body | ||
smart_ptr::detail::data_body<T>* mDataBody; | ||
}; | ||
|
||
template <typename T> | ||
using sub_ptr = subject_pointer<T>; | ||
|
||
template <typename T> | ||
using ob_ptr = observer_pointer<T>; | ||
|
||
} // namespace common | ||
} // namespace dart | ||
|
||
#endif // DART_COMMON_SMARTPOINTER_H_ | ||
|
Oops, something went wrong.