diff options
Diffstat (limited to 'source/core/StarAtomicSharedPtr.hpp')
-rw-r--r-- | source/core/StarAtomicSharedPtr.hpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/source/core/StarAtomicSharedPtr.hpp b/source/core/StarAtomicSharedPtr.hpp new file mode 100644 index 0000000..e85ffd5 --- /dev/null +++ b/source/core/StarAtomicSharedPtr.hpp @@ -0,0 +1,121 @@ +#ifndef STAR_ATOMIC_SHARED_PTR_HPP +#define STAR_ATOMIC_SHARED_PTR_HPP + +#include "StarThread.hpp" + +namespace Star { + +// Thread safe shared_ptr such that is is possible to safely access the +// contents of the shared_ptr while other threads might be updating it. Makes +// it possible to safely do Read Copy Update. +template <typename T> +class AtomicSharedPtr { +public: + typedef shared_ptr<T> SharedPtr; + typedef weak_ptr<T> WeakPtr; + + AtomicSharedPtr(); + AtomicSharedPtr(AtomicSharedPtr const& p); + AtomicSharedPtr(AtomicSharedPtr&& p); + AtomicSharedPtr(SharedPtr p); + + SharedPtr load() const; + WeakPtr weak() const; + void store(SharedPtr p); + void reset(); + + explicit operator bool() const; + bool unique() const; + + SharedPtr operator->() const; + + AtomicSharedPtr& operator=(AtomicSharedPtr const& p); + AtomicSharedPtr& operator=(AtomicSharedPtr&& p); + AtomicSharedPtr& operator=(SharedPtr p); + +private: + SharedPtr m_ptr; + mutable SpinLock m_lock; +}; + +template <typename T> +AtomicSharedPtr<T>::AtomicSharedPtr() {} + +template <typename T> +AtomicSharedPtr<T>::AtomicSharedPtr(AtomicSharedPtr const& p) + : m_ptr(p.load()) {} + +template <typename T> +AtomicSharedPtr<T>::AtomicSharedPtr(AtomicSharedPtr&& p) + : m_ptr(move(p.m_ptr)) {} + +template <typename T> +AtomicSharedPtr<T>::AtomicSharedPtr(SharedPtr p) + : m_ptr(move(p)) {} + +template <typename T> +auto AtomicSharedPtr<T>::load() const -> SharedPtr { + SpinLocker locker(m_lock); + return m_ptr; +} + +template <typename T> +auto AtomicSharedPtr<T>::weak() const -> WeakPtr { + SpinLocker locker(m_lock); + return WeakPtr(m_ptr); +} + +template <typename T> +void AtomicSharedPtr<T>::store(SharedPtr p) { + SpinLocker locker(m_lock); + m_ptr = move(p); +} + +template <typename T> +void AtomicSharedPtr<T>::reset() { + SpinLocker locker(m_lock); + m_ptr.reset(); +} + +template <typename T> +AtomicSharedPtr<T>::operator bool() const { + SpinLocker locker(m_lock); + return (bool)m_ptr; +} + +template <typename T> +bool AtomicSharedPtr<T>::unique() const { + SpinLocker locker(m_lock); + return m_ptr.unique(); +} + +template <typename T> +auto AtomicSharedPtr<T>::operator-> () const -> SharedPtr { + SpinLocker locker(m_lock); + return m_ptr; +} + +template <typename T> +AtomicSharedPtr<T>& AtomicSharedPtr<T>::operator=(AtomicSharedPtr const& p) { + SpinLocker locker(m_lock); + m_ptr = p.load(); + return *this; +} + +template <typename T> +AtomicSharedPtr<T>& AtomicSharedPtr<T>::operator=(AtomicSharedPtr&& p) { + SpinLocker locker(m_lock); + m_ptr = move(p.m_ptr); + return *this; +} + +template <typename T> +AtomicSharedPtr<T>& AtomicSharedPtr<T>::operator=(SharedPtr p) { + SpinLocker locker(m_lock); + m_ptr = move(p); + return *this; +} + +} + +#endif |