#pragma once #include "gp/algorithm/modifiers.hpp" #include "gp/algorithm/move.hpp" #include "gp/buffer.hpp" #include "gp/function.hpp" namespace gp { template class unique_ptr { T* data; gp::allocator& owner; unique_ptr(T* _data, gp::allocator& _owner) : data(_data) , owner(_owner) {} void dirty_clear() { if(data) { data->~T(); owner.deallocate(data); } } public: template static unique_ptr make(gp::allocator& owner, U&&... args) { auto ptr = owner.allocate(sizeof(T)); return unique_ptr(new(ptr) T(gp::forward(args)...), owner); } T* operator->() { return data; } T& operator*() { return *data; } operator bool() { return data != nullptr; } unique_ptr(unique_ptr&) = delete; unique_ptr(unique_ptr&& oth) : data(oth.data) , owner(oth.owner) { oth.data = nullptr; } unique_ptr& operator=(unique_ptr&) = delete; unique_ptr& operator=(unique_ptr&& oth) { dirty_clear(); data = oth.data; owner = oth.owner; } ~unique_ptr() { dirty_clear(); } }; template class shared_ptr { T* data; std::atomic_int* refcounter; gp::allocator& owner; shared_ptr(T* _data, gp::allocator& _owner) : data(_data) , owner(_owner) {} void dirty_clear() { if(!refcounter) return; if(refcounter->fetch_sub(1, std::memory_order::acq_rel) == 0) { if(data) { data->~T(); owner.deallocate(refcounter); owner.deallocate(data); } } } public: template static shared_ptr make(gp::allocator& owner, U&&... args) { auto ptr = owner.allocate(sizeof(T)); auto shared_atomic = owner.allocate(sizeof(std::atomic_int)); refcounter = new(shared_atomic) std::atomic_int(); refcounter->store(1); return shared_ptr(new(ptr) T(gp::forward(args)...), owner); } T* operator->() { return data; } T& operator*() { return *data; } operator bool() { return data != nullptr; } shared_ptr(shared_ptr& oth) { oth.refcounter->fetch_add(1, std::memory_order::acquire); data = oth.data; refcounter = oth.refcounter; owner = oth.owner; } shared_ptr(shared_ptr&& oth) : data(oth.data) , owner(oth.owner) { oth.data = nullptr; oth.refcounter = nullptr; } shared_ptr& operator=(shared_ptr& oth) { dirty_clear(); (*oth.refcounter)++; data = oth.data; refcounter = oth.refcounter; owner = oth.owner; } shared_ptr& operator=(shared_ptr&& oth) { dirty_clear(); data = oth.data; owner = oth.owner; } ~shared_ptr() { dirty_clear(); } }; }