Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions include/vsg/core/Auxiliary.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ namespace vsg

virtual std::size_t getSizeOf() const { return sizeof(Auxiliary); }

void ref() const;
void unref() const;
void unref_nodelete() const;
inline unsigned int referenceCount() const { return _referenceCount.load(); }
//void ref() const;
//void unref() const;
//void unref_nodelete() const;
inline unsigned int referenceCount() const { return _referenceCount->useCount(); }

virtual int compare(const Auxiliary& rhs) const;

Expand Down Expand Up @@ -97,10 +97,18 @@ namespace vsg

void resetConnectedObject();

void callDeleteOperator() { delete this; }

friend class Object;
friend class Allocator;

mutable std::atomic_uint _referenceCount;
template<class T>
friend class ref_ptr;

friend class RefCountBase;
friend class detail::RefCountPointer<Auxiliary>;

RefCountBase* _referenceCount;

mutable std::mutex _mutex;
Object* _connectedObject;
Expand Down
4 changes: 2 additions & 2 deletions include/vsg/core/Inherit.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ namespace vsg
template<typename... Args>
static ref_ptr<Subclass> create(Args&&... args)
{
return ref_ptr<Subclass>(new Subclass(std::forward<Args>(args)...));
return make_referenced<Subclass>(std::forward<Args>(args)...);
}

template<typename... Args>
static ref_ptr<Subclass> create_if(bool flag, Args&&... args)
{
if (flag) return ref_ptr<Subclass>(new Subclass(std::forward<Args>(args)...));
if (flag) return make_referenced<Subclass>(std::forward<Args>(args)...);
return {};
}

Expand Down
35 changes: 24 additions & 11 deletions include/vsg/core/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,14 @@ namespace vsg
Object(const Object& object, const CopyOp& copyop = {});
Object& operator=(const Object&);

static ref_ptr<Object> create() { return ref_ptr<Object>(new Object); }
static ref_ptr<Object> create() {
return make_referenced<Object>();
}

static ref_ptr<Object> create_if(bool flag)
{
if (flag)
return ref_ptr<Object>(new Object);
return make_referenced<Object>();
else
return {};
}
Expand Down Expand Up @@ -118,14 +120,14 @@ namespace vsg
virtual void read(Input& input);
virtual void write(Output& output) const;

// ref counting methods
inline void ref() const noexcept { _referenceCount.fetch_add(1, std::memory_order_relaxed); }
inline void unref() const noexcept
{
if (_referenceCount.fetch_sub(1, std::memory_order_seq_cst) <= 1) _attemptDelete();
}
inline void unref_nodelete() const noexcept { _referenceCount.fetch_sub(1, std::memory_order_seq_cst); }
inline unsigned int referenceCount() const noexcept { return _referenceCount.load(); }
// ref counting methods - maybe kill these?
//inline void ref() const noexcept { _referenceCount->increment(); }
//inline void unref() const noexcept
//{
// _referenceCount->decrement();
//}
//inline void unref_nodelete() const noexcept { _referenceCount.fetch_sub(1, std::memory_order_seq_cst); }
inline unsigned int referenceCount() const noexcept { return _referenceCount->useCount(); }

/// meta data access methods
/// wraps the value with a vsg::Value<T> object and then assigns via setObject(key, vsg::Value<T>)
Expand Down Expand Up @@ -182,12 +184,23 @@ namespace vsg
virtual ~Object();

virtual void _attemptDelete() const;
void callDestructor() { this->~Object(); }
void callDeleteOperator() const { delete this; }
void assignRefCount(RefCountBase* refCount);

void setAuxiliary(Auxiliary* auxiliary);

private:
friend class Auxiliary;

mutable std::atomic_uint _referenceCount;
template<class T>
friend class ref_ptr;
template<class T>
friend class observer_ptr;

friend class RefCountBase;

mutable RefCountBase* _referenceCount;

Auxiliary* _auxiliary;
};
Expand Down
96 changes: 67 additions & 29 deletions include/vsg/core/observer_ptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI

</editor-fold> */

#include <vsg/core/Auxiliary.h>
#include <vsg/core/ref_ptr.h>

namespace vsg
{
Expand All @@ -26,84 +26,120 @@ namespace vsg
using element_type = T;

observer_ptr() :
_ptr(nullptr) {}
_ptr(nullptr),
_refCount(nullptr)
{}

observer_ptr(const observer_ptr& rhs) :
_ptr(rhs._ptr),
_auxiliary(rhs._auxiliary)
_ptr(nullptr),
_refCount(rhs._refCount)
{
if (_refCount)
{
_ptr = rhs._ptr;
_refCount->incrementObservers();
}
}

template<class R>
explicit observer_ptr(R* ptr) :
_ptr(ptr),
_auxiliary(ptr ? ptr->getOrCreateAuxiliary() : nullptr)
_refCount(ptr ? ptr->_referenceCount : nullptr)
{
if (_ptr)
_refCount->incrementObservers();
}

template<class R>
explicit observer_ptr(const observer_ptr<R>& ptr) :
_ptr(ptr._ptr),
_auxiliary(ptr._auxiliary)
_ptr(nullptr),
_refCount(ptr._refCount)
{
if (_refCount)
{
_ptr = ptr._ptr;
_refCount->incrementObservers();
}
}

template<class R>
explicit observer_ptr(const vsg::ref_ptr<R>& ptr) :
_ptr(ptr.get()),
_auxiliary(ptr.valid() ? ptr->getOrCreateAuxiliary() : nullptr)
_refCount(ptr.valid() ? ptr->_referenceCount : nullptr)
{
if (_refCount)
_refCount->incrementObservers();
}

~observer_ptr()
{
if (_refCount)
_refCount->decrementObservers();
}

void reset()
{
_ptr = nullptr;
_auxiliary.reset();
if (_refCount)
_refCount->decrementObservers();
_refCount = nullptr;
}

template<class R>
observer_ptr& operator=(R* ptr)
{
if (_refCount)
_refCount->decrementObservers();
_ptr = ptr;
_auxiliary = ptr ? ptr->getOrCreateAuxiliary() : nullptr;
_refCount = ptr ? ptr->_referenceCount : nullptr;
if (_refCount)
_refCount->incrementObservers();
return *this;
}

observer_ptr& operator=(const observer_ptr& rhs)
{
if (_refCount)
_refCount->decrementObservers();
_ptr = rhs._ptr;
_auxiliary = rhs._auxiliary;
_refCount = rhs._refCount;
if (_refCount)
_refCount->incrementObservers();
return *this;
}

template<class R>
observer_ptr& operator=(const observer_ptr<R>& rhs)
{
if (_refCount)
_refCount->decrementObservers();
_ptr = rhs._ptr;
_auxiliary = rhs._auxiliary;
_refCount = rhs._refCount;
if (_refCount)
_refCount->incrementObservers();
return *this;
}

template<class R>
observer_ptr& operator=(const vsg::ref_ptr<R>& rhs)
{
if (_refCount)
_refCount->decrementObservers();
_ptr = rhs.get();
_auxiliary = rhs.valid() ? rhs->getOrCreateAuxiliary() : nullptr;
_refCount = rhs.valid() ? rhs->_referenceCount : nullptr;
if (_refCount)
_refCount->incrementObservers();
return *this;
}

template<class R>
bool operator<(const observer_ptr<R>& rhs) const { return (rhs._ptr < _ptr) || (rhs._ptr == _ptr && rhs._auxiliary < _auxiliary); }
bool operator<(const observer_ptr<R>& rhs) const { return (rhs._ptr < _ptr) || (rhs._ptr == _ptr && rhs._refCount < _refCount); }

template<class R>
bool operator==(const observer_ptr<R>& rhs) const { return (rhs._auxiliary == _auxiliary); }
bool operator==(const observer_ptr<R>& rhs) const { return (rhs._refCount == _refCount); }

template<class R>
bool operator!=(const observer_ptr<R>& rhs) const { return (rhs._auxiliary != _auxiliary); }
bool operator!=(const observer_ptr<R>& rhs) const { return (rhs._refCount != _refCount); }

template<class R>
bool operator<(const R* rhs) const
Expand All @@ -112,7 +148,7 @@ namespace vsg
return true;
if (_ptr == nullptr)
return false;
return rhs->getAuxiliary() < _auxiliary;
return rhs->_referenceCount < _refCount;
}

template<class R>
Expand All @@ -122,7 +158,7 @@ namespace vsg
return false;
if (rhs == nullptr)
return true;
return rhs->getAuxiliary() == _auxiliary;
return rhs->_referenceCount == _refCount;
}

template<class R>
Expand All @@ -132,7 +168,7 @@ namespace vsg
return true;
if (rhs == nullptr)
return false;
return rhs->getAuxiliary() != _auxiliary;
return rhs->_referenceCount != _refCount;
}

template<class R>
Expand All @@ -142,7 +178,7 @@ namespace vsg
return true;
if (_ptr == nullptr)
return false;
return rhs->getAuxiliary() < _auxiliary;
return rhs->_referenceCount < _refCount;
}

template<class R>
Expand All @@ -152,7 +188,7 @@ namespace vsg
return false;
if (rhs == nullptr)
return true;
return rhs->getAuxiliary() == _auxiliary;
return rhs->_referenceCount == _refCount;
}

template<class R>
Expand All @@ -162,10 +198,10 @@ namespace vsg
return true;
if (rhs == nullptr)
return false;
return rhs->getAuxiliary() != _auxiliary;
return rhs->_referenceCount != _refCount;
}

bool valid() const noexcept { return _auxiliary.valid() && _auxiliary->getConnectedObject() != nullptr; }
bool valid() const noexcept { return _refCount && _refCount->useCount() > 0; }

explicit operator bool() const noexcept { return valid(); }

Expand All @@ -176,13 +212,15 @@ namespace vsg
template<class R>
operator vsg::ref_ptr<R>() const
{
if (!_auxiliary) return vsg::ref_ptr<R>();

std::scoped_lock<std::mutex> guard(_auxiliary->getMutex());
if (_auxiliary->getConnectedObject() != nullptr)
return vsg::ref_ptr<R>(_ptr);
if (_refCount && _refCount->incrementIfNonZero())
{
detail::TemporaryOwner<R> temp{_ptr};
return vsg::ref_ptr<R>(temp);
}
else
{
return {};
}
}

/// We strongly recommend access via ref_ptr<> rather than get(). Only use get() to get access to the raw C pointer when it's know that the object pointed to will remain in memory through use of that raw C pointer.
Expand All @@ -193,7 +231,7 @@ namespace vsg
friend class observer_ptr;

T* _ptr;
vsg::ref_ptr<Auxiliary> _auxiliary;
RefCountBase* _refCount;
};

} // namespace vsg
Loading
Loading