47 return (T *) ::operator
new(n *
sizeof(T));
52 ::operator
delete(p, n *
sizeof(T));
69 void operator()(T *ptr) const noexcept
73 template <
typename U>
void operator()(U *ptr)
const noexcept
79template <
class T>
class weak_ptr;
86template <
class T,
class Deleter = tenno::default_delete<T>,
87 class Alloc = tenno::allocator<T>>
108 if (this->num_weak_ptrs == 0)
109 this->allocator.deallocate(
117 template <
class Y,
class... Args>
118 friend typename std::enable_if<!std::is_array<Y>::value,
shared_ptr<Y>>::type
122 friend typename std::enable_if<std::is_array<Y>::value,
shared_ptr<Y>>::type
128 shared_ptr() noexcept : _element(
nullptr), _control_block(
nullptr)
144 cb->num_weak_ptrs = 0;
148 this->_element = cb->object;
149 this->_control_block = cb;
165 cb->num_weak_ptrs = 0;
167 cb->deleter = deleter;
169 this->_element = cb->object;
170 this->_control_block = cb;
191 this->_element = cb->
object;
192 this->_control_block = cb;
201 : _element(other._element), _control_block(other._control_block)
213 : _element(other._element), _control_block(other._control_block)
215 other._element =
nullptr;
216 other._control_block =
nullptr;
224 if (!this->_control_block)
231 if (this->_control_block->
num_ptrs == 0)
248 this->_element = other._element;
249 this->_control_block = other._control_block;
264 if (this->_control_block)
270 if (this->_control_block->
num_ptrs == 0)
276 this->_element = other._element;
277 this->_control_block = other._control_block;
287 if (!this->_control_block)
294 if (this->_control_block->
num_ptrs == 0)
299 this->_element =
nullptr;
300 this->_control_block =
nullptr;
311 if (!this->_control_block)
318 if (this->_control_block->
num_ptrs == 0)
328 cb->num_weak_ptrs = 0;
332 this->_element = cb->object;
333 this->_control_block = cb;
343 void reset(T *ptr, Deleter deleter)
noexcept
345 if (!this->_control_block)
352 if (this->_control_block->
num_ptrs == 0)
362 cb->num_weak_ptrs = 0;
364 cb->deleter = deleter;
366 this->_element = cb->object;
367 this->_control_block = cb;
378 void reset(T *ptr, Deleter deleter, Alloc alloc)
noexcept
380 if (!this->_control_block)
387 if (this->_control_block->
num_ptrs == 0)
401 this->_element = cb->
object;
402 this->_control_block = cb;
412 T *tmp_element = this->_element;
415 this->_element = other._element;
416 this->_control_block = other._control_block;
418 other._element = tmp_element;
419 other._control_block = tmp_control_block;
429 return this->_element;
439 return *this->_element;
449 return this->_element;
460 return (*this->_element)[index];
470 if (!this->_control_block)
472 return this->_control_block->
num_ptrs;
481 explicit operator bool() const noexcept
483 return this->_element !=
nullptr;
495 return *this->_element < *other._element;
508 if (!this->_element && !other._element)
510 if (!this->_element || !other._element)
512 return *this->_element == *other._element;
543 this->_control_block =
nullptr;
544 this->_ptr =
nullptr;
554 if (!r._control_block)
556 this->_control_block =
nullptr;
557 this->_ptr =
nullptr;
560 this->_control_block = r._control_block;
562 this->_control_block->num_weak_ptrs++;
572 if (!r._control_block)
574 this->_control_block =
nullptr;
575 this->_ptr =
nullptr;
578 this->_control_block = r._control_block;
580 r._control_block =
nullptr;
591 if (!r._control_block)
593 this->_control_block =
nullptr;
594 this->_ptr =
nullptr;
598 this->_ptr = r._element;
599 this->_control_block = r._control_block;
600 this->_control_block->num_weak_ptrs++;
608 if (this->_control_block)
612 this->_control_block->num_weak_ptrs--;
614 if (this->_control_block->num_ptrs == 0
615 && this->_control_block->num_weak_ptrs == 0)
616 this->_control_block->deallocate();
628 if (this->_control_block)
632 this->_control_block->num_weak_ptrs--;
634 if (this->_control_block->num_ptrs == 0
635 && this->_control_block->num_weak_ptrs == 0)
636 this->_control_block->deallocate();
638 if (!r._control_block)
640 this->_control_block =
nullptr;
641 this->_ptr =
nullptr;
645 this->_control_block = r._control_block;
647 this->_control_block->num_weak_ptrs++;
659 if (this->_control_block)
663 this->_control_block->num_weak_ptrs--;
665 if (this->_control_block->num_ptrs == 0
666 && this->_control_block->num_weak_ptrs == 0)
667 this->_control_block->deallocate();
669 if (!r._control_block)
671 this->_control_block =
nullptr;
672 this->_ptr =
nullptr;
676 this->_ptr = r._element;
677 this->_control_block = r._control_block;
678 this->_control_block->num_weak_ptrs++;
690 if (this->_control_block)
694 this->_control_block->num_weak_ptrs--;
696 if (this->_control_block->num_ptrs == 0
697 && this->_control_block->num_weak_ptrs == 0)
698 this->_control_block->deallocate();
700 if (!r._control_block)
702 this->_control_block =
nullptr;
703 this->_ptr =
nullptr;
706 this->_control_block = r._control_block;
708 r._control_block =
nullptr;
718 if (this->_control_block)
719 this->_control_block->num_weak_ptrs--;
720 this->_control_block =
nullptr;
721 this->_ptr =
nullptr;
731 auto cb_tmp = this->_control_block;
732 auto ptr_tmp = this->_ptr;
733 this->_control_block = r._control_block;
735 r._control_block = cb_tmp;
746 if (this->_control_block)
747 return this->_control_block->num_ptrs;
759 if (!this->_control_block)
761 return this->_control_block->num_ptrs == 0;
771 if (this->_control_block->num_ptrs == 0)
774 sp._element = this->_ptr;
775 sp._control_block = this->_control_block;
776 sp._control_block->num_ptrs++;
789 if (this->_ptr && !other._ptr)
791 if (!this->_ptr && other._ptr)
793 if (!this->_ptr || !other._ptr)
795 return *this->_ptr < *other._ptr;
808 return *this->_ptr < *other._element;
821 if (!this->_ptr && !other._element)
823 if (!this->_ptr || !other._element)
825 return *this->_ptr == *other._element;
846template <
class T,
class Deleter = tenno::default_delete<T>>
class unique_ptr
866 : _value(ptr), _deleter(deleter)
878 this->
reset(other.release());
879 this->_deleter = other.get_deleter();
885#if __cplusplus >= 202002L
890 if (this->_value !=
nullptr)
891 this->_deleter(this->_value);
903 this->
reset(other.release());
904 this->_deleter = other.get_deleter();
919 this->_value =
nullptr;
931 this->_deleter(this->_value);
942 T tmp_val = *other.get();
943 Deleter del_tmp = other.get_deleter();
944 *other.get() = *this->
get();
946 *this->_value = tmp_val;
947 this->_deleter = del_tmp;
967 return this->_deleter;
974 explicit operator bool() const noexcept
976 return this->_value !=
nullptr;
985 return *this->_value;
1015template <
class T,
class... Args>
1016typename std::enable_if<!std::is_array<T>::value, shared_ptr<T>>::type
1021 T *t =
new T(args...);
1023 sizeof(cb_t) /
sizeof(T) + (
sizeof(cb_t) %
sizeof(T) != 0 ? 1 : 0));
1026 cb->num_weak_ptrs = 0;
1031 sp._control_block = cb;
1036typename std::enable_if<std::is_array<T>::value,
shared_ptr<T>>::type
1043 sizeof(cb_t) /
sizeof(T) + (
sizeof(cb_t) %
sizeof(T) != 0 ? 1 : 0));
1046 cb->num_weak_ptrs = 0;
1051 sp._control_block = cb;
1067 sizeof(cb_t) /
sizeof(T) + (
sizeof(cb_t) %
sizeof(T) != 0 ? 1 : 0));
1070 cb->num_weak_ptrs = 0;
1075 sp._control_block = cb;
1089template <
class T,
class Alloc,
class... Args>
1092 Args &&...args)
noexcept
1094 T *t = alloc.allocate(1);
1107template <
class T,
class Alloc>
1110 T *t = alloc.allocate(1);
1148template <
class T,
class... Args>
1151 T *t =
new T(args...);
A simple lock guard implementation.
A simple mutex implementation.
shared_ptr(T *ptr)
Construct a new shared pointer object.
friend std::enable_if<!std::is_array< Y >::value, shared_ptr< Y > >::type make_shared(Args &&...args) noexcept
Create a shared pointer with the given arguments.
void reset(T *ptr, Deleter deleter, Alloc alloc) noexcept
Reset the shared pointer to point to the object managed by the control block cb.
shared_ptr(T *ptr, Deleter deleter)
Construct a new shared pointer object.
void reset(T *ptr, Deleter deleter) noexcept
Reset the shared pointer to point to the object managed by the control block cb.
bool owner_before(const shared_ptr &other) const noexcept
Stored value ordering.
shared_ptr & operator=(shared_ptr &&other) noexcept
Move assignment operator.
shared_ptr(shared_ptr &&other) noexcept
Move constructor.
void swap(shared_ptr &other) noexcept
Swap the shared pointer with another shared pointer.
shared_ptr(const shared_ptr &other) noexcept
Copy constructor.
T element_type
The type of the object to point to.
shared_ptr & operator=(const shared_ptr &other) noexcept
Copy assignment operator.
long use_count() const noexcept
Get the number of shared pointers pointing to the object.
shared_ptr(T *ptr, Deleter deleter, Alloc alloc)
Construct a new shared pointer object.
T & operator*() const noexcept
Dereference operator.
auto & operator[](tenno::size index) const noexcept
Array access operator.
void reset(T *ptr) noexcept
Reset the shared pointer to point to the object managed by the control block cb.
void reset() noexcept
Reset the shared pointer.
bool owner_equal(const shared_ptr &other) const noexcept
Stored value equality.
T * operator->() const noexcept
Member access operator.
T * get() const noexcept
Get the object pointed to by the shared pointer.
T & operator->() noexcept
Dereference operator.
constexpr unique_ptr & operator=(unique_ptr &&other) noexcept
Move the other unique_ptr object into this one.
constexpr unique_ptr(T *ptr, Deleter deleter=tenno::default_delete< T >())
Construct a new unique_ptr object with the given pointer.
deleter_type & get_deleter()
Get the deleter of the object.
constexpr unique_ptr(const unique_ptr &other)=delete
T & operator*() noexcept
Dereference operator.
constexpr pointer release() noexcept
Release the pointer from the unique_ptr object.
constexpr unique_ptr & operator=(const unique_ptr &other)=delete
~unique_ptr()
Destroy the unique_ptr object.
constexpr unique_ptr(unique_ptr &&other) noexcept
Construct a new unique_ptr object by moving the other object.
constexpr unique_ptr()
Construct a new empty unique_ptr object.
constexpr void reset(pointer ptr=pointer()) noexcept
Reset the pointer to the given value.
void swap(unique_ptr &other) noexcept
Swap the unique_ptr object with the other one.
constexpr pointer get() const noexcept
Get the pointer to the object.
void reset() noexcept
Reset the weak pointer.
bool owner_before(const weak_ptr< Y > &other) const noexcept
Stored value ordering.
long use_count() const noexcept
Get the number of shared pointers pointing to the object.
bool expired() const noexcept
Check if the weak pointer is empty.
tenno::shared_ptr< T > lock() const noexcept
Lock the weak pointer.
constexpr weak_ptr() noexcept
Default constructor.
weak_ptr & operator=(const weak_ptr &r) noexcept
Copy assignment operator.
bool owner_before(const tenno::shared_ptr< Y > &other) const noexcept
Stored value ordering.
void swap(weak_ptr &r) noexcept
Swap the weak pointer with another weak pointer.
weak_ptr(const weak_ptr &r) noexcept
Copy constructor.
weak_ptr(const tenno::shared_ptr< T > &r) noexcept
Construct a new weak pointer object.
weak_ptr & operator=(const shared_ptr< T > &r) noexcept
Move assignment operator.
T element_type
The type of the object to point to.
weak_ptr(weak_ptr &&r) noexcept
Move constructor.
weak_ptr & operator=(weak_ptr &&r) noexcept
Move assignment operator.
bool owner_equal(const tenno::shared_ptr< Y > &other) const noexcept
Stored value equality.
constexpr unique_ptr< T > make_unique(Args &&...args)
Create a unique pointer with the given arguments.
tenno::shared_ptr< T > allocate_shared(Alloc &alloc, Args &&...args) noexcept
Create a shared pointer with the given arguments and allocator.
shared_ptr< T > make_shared() noexcept
Default initialize a shared pointer.
constexpr std::remove_reference_t< T > && move(T &&t) noexcept
Move a value from one location to another.
T * allocate(tenno::size n)
void deallocate(T *p, tenno::size n)
constexpr bool operator==(const allocator &) const noexcept
allocator() noexcept=default
constexpr bool operator!=(const allocator &) const noexcept
const T & const_referemce
default_delete() noexcept=default
void operator()(U *ptr) const noexcept