|
@ -5,132 +5,134 @@ |
|
|
#include "gp/buffer.hpp"
|
|
|
#include "gp/buffer.hpp"
|
|
|
#include "gp/function.hpp"
|
|
|
#include "gp/function.hpp"
|
|
|
|
|
|
|
|
|
|
|
|
namespace gp { |
|
|
|
|
|
|
|
|
|
|
|
template<typename T> |
|
|
|
|
|
class unique_ptr { |
|
|
|
|
|
T* data; |
|
|
|
|
|
gp::allocator& owner; |
|
|
|
|
|
|
|
|
template<typename T> |
|
|
|
|
|
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<typename ...U> |
|
|
|
|
|
unique_ptr make(gp::allocator& owner, U&&... args) { |
|
|
|
|
|
auto ptr = owner.allocate(sizeof(T)); |
|
|
|
|
|
return unique_ptr(new(ptr) T(gp::forward<U>(args)...), owner); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
T& operator->() { |
|
|
|
|
|
return *data; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
T& operator*() { |
|
|
|
|
|
return *data; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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<typename T> |
|
|
|
|
|
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) { |
|
|
|
|
|
|
|
|
unique_ptr(T* _data, gp::allocator& _owner) |
|
|
|
|
|
: data(data) |
|
|
|
|
|
, owner(_owner) |
|
|
|
|
|
{} |
|
|
|
|
|
|
|
|
|
|
|
void dirty_clear() { |
|
|
if(data) { |
|
|
if(data) { |
|
|
data->~T(); |
|
|
data->~T(); |
|
|
owner.deallocate(refcounter); |
|
|
|
|
|
owner.deallocate(data); |
|
|
owner.deallocate(data); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
public: |
|
|
|
|
|
template<typename ...U> |
|
|
|
|
|
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<U>(args)...), owner); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
T& operator->() { |
|
|
|
|
|
return *data; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
T& operator*() { |
|
|
|
|
|
return *data; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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(); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
template<typename ...U> |
|
|
|
|
|
unique_ptr make(gp::allocator& owner, U&&... args) { |
|
|
|
|
|
auto ptr = owner.allocate(sizeof(T)); |
|
|
|
|
|
return unique_ptr(new(ptr) T(gp::forward<U>(args)...), owner); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
T& operator->() { |
|
|
|
|
|
return *data; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
T& operator*() { |
|
|
|
|
|
return *data; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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<typename T> |
|
|
|
|
|
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<typename ...U> |
|
|
|
|
|
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<U>(args)...), owner); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
T& operator->() { |
|
|
|
|
|
return *data; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
T& operator*() { |
|
|
|
|
|
return *data; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
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(); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
} |