Cuda battery library
Loading...
Searching...
No Matches
shared_ptr.hpp
Go to the documentation of this file.
1// Copyright 2021 Pierre Talbot
2
3#ifndef CUDA_BATTERY_SHARED_PTR_HPP
4#define CUDA_BATTERY_SHARED_PTR_HPP
5
6#include "utility.hpp"
7#include "allocator.hpp"
8
9namespace battery {
10
11/**
12 * Similar to std::shared_ptr but with some (technical) differences:
13 * - There is no specialization for arrays (e.g., shared_ptr<T[]>).
14 - It is parametrized by an allocator to allocate/deallocate the memory.
15 - No support for aliasing constructors.
16 - No special thread-safety support.
17 * Similarly to vector, the allocator is scoped, meaning it is propagated to the underlying type constructor if it takes one.
18*/
19template <class T, class Allocator = standard_allocator>
21public:
22 using element_type = T;
23 using pointer = T*;
24 using allocator_type = Allocator;
26private:
27 Allocator allocator;
28 int* count;
29 T* ptr;
30
31 template<class Y, class Alloc>
32 friend class shared_ptr;
33
34 CUDA NI int* allocate_counter() {
35 int* c = static_cast<int*>(allocator.allocate(sizeof(int)));
36 *c = 1;
37 return c;
38 }
39
40 CUDA void inc_counter() {
41 if(count != nullptr) {
42 ++(*count);
43 }
44 }
45
46public:
48 : allocator(allocator), count(nullptr), ptr(nullptr) {}
49
50 CUDA shared_ptr(std::nullptr_t, const allocator_type& allocator = allocator_type())
51 : allocator(allocator), count(nullptr), ptr(nullptr) {}
52
53 // `ptr` must have been allocated using `allocator_type`.
54 template<class Y>
55 CUDA NI explicit shared_ptr(Y* ptr, const allocator_type& allocator = allocator_type())
56 : allocator(allocator), count(allocate_counter()), ptr(static_cast<T*>(ptr))
57 {
58 }
59
61 : allocator(from.allocator), ptr(from.ptr), count(from.count)
62 {
63 from.ptr = nullptr;
64 from.count = nullptr;
65 }
66
67 template<class Y>
69 : allocator(from.allocator), ptr(static_cast<T*>(from.ptr)), count(from.count)
70 {
71 from.ptr = nullptr;
72 from.count = nullptr;
73 }
74
76 : allocator(from.allocator), ptr(from.ptr), count(from.count)
77 {
78 inc_counter();
79 }
80
81 template<class Y>
83 : allocator(from.allocator), ptr(static_cast<T*>(from.ptr)), count(from.count)
84 {
85 inc_counter();
86 }
87
89 if(ptr != nullptr) {
90 if(*count <= 1) {
91 ptr->~T();
92 allocator.deallocate(ptr);
93 ptr = nullptr;
94 allocator.deallocate(count);
95 count = nullptr;
96 }
97 else {
98 --(*count);
99 }
100 }
101 }
102
103 CUDA void swap(shared_ptr& other) {
104 ::battery::swap(ptr, other.ptr);
105 ::battery::swap(count, other.count);
106 ::battery::swap(allocator, other.allocator);
107 }
108
110 this_type(r).swap(*this);
111 return *this;
112 }
113
115 this_type(std::move(r)).swap(*this);
116 return *this;
117 }
118
119 template<class Y>
121 this_type(r).swap(*this);
122 return *this;
123 }
124
125 template<class Y>
127 this_type(std::move(r)).swap(*this);
128 return *this;
129 }
130
131
132 CUDA shared_ptr& operator=(std::nullptr_t) {
133 this_type(allocator).swap(*this);
134 return *this;
135 }
136
137 CUDA void reset() {
138 this_type(allocator).swap(*this);
139 }
140
141 template<class Y>
142 CUDA void reset(Y* ptr) {
143 this_type(ptr, allocator).swap(*this);
144 }
145
146 CUDA pointer get() const {
147 return ptr;
148 }
149
150 CUDA T& operator*() const {
151 assert(bool(ptr));
152 return *ptr;
153 }
154
156 assert(bool(ptr));
157 return ptr;
158 }
159
160 CUDA int use_count() const {
161 return count == nullptr ? 0 : *count;
162 }
163
165 return allocator;
166 }
167
168 CUDA explicit operator bool() const {
169 return ptr != nullptr;
170 }
171};
172
173template<class T, class Alloc, class... Args>
174CUDA NI shared_ptr<T, Alloc> allocate_shared(const Alloc& alloc, Args&&... args) {
175 Alloc allocator(alloc);
176 T* ptr = static_cast<T*>(allocator.allocate(sizeof(T)));
177 assert(ptr != nullptr);
178 if constexpr(std::is_constructible<T, Args&&..., const Alloc&>{}) {
179 new(ptr) T(std::forward<Args>(args)..., allocator);
180 }
181 else {
182 new(ptr) T(std::forward<Args>(args)...);
183 }
184 return shared_ptr<T, Alloc>(ptr, allocator);
185}
186
187/** Similar to `allocate_shared` but with an default-constructed allocator. */
188template<class T, class Alloc, class... Args>
190 return ::battery::allocate_shared<T>(Alloc(), std::forward<Args>(args)...);
191}
192
193} // namespace battery
194
195#endif
Definition shared_ptr.hpp:20
CUDA shared_ptr & operator=(shared_ptr &&r)
Definition shared_ptr.hpp:114
CUDA shared_ptr & operator=(std::nullptr_t)
Definition shared_ptr.hpp:132
shared_ptr< element_type, allocator_type > this_type
Definition shared_ptr.hpp:25
CUDA allocator_type get_allocator() const
Definition shared_ptr.hpp:164
CUDA NI ~shared_ptr()
Definition shared_ptr.hpp:88
T element_type
Definition shared_ptr.hpp:22
CUDA int use_count() const
Definition shared_ptr.hpp:160
CUDA pointer operator->() const
Definition shared_ptr.hpp:155
CUDA void reset()
Definition shared_ptr.hpp:137
CUDA NI shared_ptr(Y *ptr, const allocator_type &allocator=allocator_type())
Definition shared_ptr.hpp:55
CUDA T & operator*() const
Definition shared_ptr.hpp:150
CUDA void reset(Y *ptr)
Definition shared_ptr.hpp:142
CUDA pointer get() const
Definition shared_ptr.hpp:146
CUDA shared_ptr(this_type &&from)
Definition shared_ptr.hpp:60
CUDA shared_ptr(shared_ptr< Y, Allocator > &&from)
Definition shared_ptr.hpp:68
CUDA shared_ptr & operator=(const shared_ptr &r)
Definition shared_ptr.hpp:109
CUDA shared_ptr(const this_type &from)
Definition shared_ptr.hpp:75
T * pointer
Definition shared_ptr.hpp:23
CUDA shared_ptr(std::nullptr_t, const allocator_type &allocator=allocator_type())
Definition shared_ptr.hpp:50
CUDA shared_ptr & operator=(const shared_ptr< Y, Allocator > &r)
Definition shared_ptr.hpp:120
CUDA shared_ptr & operator=(shared_ptr< Y, Allocator > &&r)
Definition shared_ptr.hpp:126
CUDA shared_ptr(const allocator_type &allocator=allocator_type())
Definition shared_ptr.hpp:47
CUDA void swap(shared_ptr &other)
Definition shared_ptr.hpp:103
CUDA shared_ptr(const shared_ptr< Y, Allocator > &from)
Definition shared_ptr.hpp:82
Allocator allocator_type
Definition shared_ptr.hpp:24
Definition algorithm.hpp:10
CUDA constexpr void swap(T &a, T &b)
Definition utility.hpp:91
CUDA NI shared_ptr< T, Alloc > make_shared(Args &&... args)
Definition shared_ptr.hpp:189
CUDA NI shared_ptr< T, Alloc > allocate_shared(const Alloc &alloc, Args &&... args)
Definition shared_ptr.hpp:174
#define CUDA
Definition utility.hpp:59
#define NI
Definition utility.hpp:62