#pragma once #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 class AtomicSharedPtr { public: typedef shared_ptr SharedPtr; typedef weak_ptr 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 AtomicSharedPtr::AtomicSharedPtr() {} template AtomicSharedPtr::AtomicSharedPtr(AtomicSharedPtr const& p) : m_ptr(p.load()) {} template AtomicSharedPtr::AtomicSharedPtr(AtomicSharedPtr&& p) : m_ptr(std::move(p.m_ptr)) {} template AtomicSharedPtr::AtomicSharedPtr(SharedPtr p) : m_ptr(std::move(p)) {} template auto AtomicSharedPtr::load() const -> SharedPtr { SpinLocker locker(m_lock); return m_ptr; } template auto AtomicSharedPtr::weak() const -> WeakPtr { SpinLocker locker(m_lock); return WeakPtr(m_ptr); } template void AtomicSharedPtr::store(SharedPtr p) { SpinLocker locker(m_lock); m_ptr = std::move(p); } template void AtomicSharedPtr::reset() { SpinLocker locker(m_lock); m_ptr.reset(); } template AtomicSharedPtr::operator bool() const { SpinLocker locker(m_lock); return (bool)m_ptr; } template bool AtomicSharedPtr::unique() const { SpinLocker locker(m_lock); return m_ptr.unique(); } template auto AtomicSharedPtr::operator-> () const -> SharedPtr { SpinLocker locker(m_lock); return m_ptr; } template AtomicSharedPtr& AtomicSharedPtr::operator=(AtomicSharedPtr const& p) { SpinLocker locker(m_lock); m_ptr = p.load(); return *this; } template AtomicSharedPtr& AtomicSharedPtr::operator=(AtomicSharedPtr&& p) { SpinLocker locker(m_lock); m_ptr = std::move(p.m_ptr); return *this; } template AtomicSharedPtr& AtomicSharedPtr::operator=(SharedPtr p) { SpinLocker locker(m_lock); m_ptr = std::move(p); return *this; } }