Skip to content

Commit

Permalink
Add first draft of sub_ptr and ob_ptr
Browse files Browse the repository at this point in the history
  • Loading branch information
jslee02 committed Mar 16, 2015
1 parent a236513 commit de62fea
Show file tree
Hide file tree
Showing 2 changed files with 422 additions and 0 deletions.
286 changes: 286 additions & 0 deletions dart/common/smart_ptr.h
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_

Loading

0 comments on commit de62fea

Please sign in to comment.