Zth (libzth)
Loading...
Searching...
No Matches
allocator.h
Go to the documentation of this file.
1#ifndef ZTH_ALLOCATOR_H
2#define ZTH_ALLOCATOR_H
3/*
4 * SPDX-FileCopyrightText: 2019-2026 Jochem Rutgers
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 */
8
9#include <libzth/macros.h>
10
11#ifdef __cplusplus
12
13# include <libzth/config.h>
14# include <libzth/util.h>
15
16# include <exception>
17# include <list>
18# include <map>
19# include <string>
20# include <vector>
21
22namespace zth {
23
24# ifdef NDEBUG
25# define ZTH_MALLOC_INLINE inline
26# define ZTH_MALLOC_ATTR(attr)
27# else
28# define ZTH_MALLOC_INLINE __attribute__((noinline))
29# if !defined(__clang_analyzer__) && GCC_VERSION >= 110000L
30# define ZTH_MALLOC_ATTR(attr) __attribute__(attr)
31# else
32# define ZTH_MALLOC_ATTR(attr) __attribute__((malloc))
33# endif
34# endif
35
40template <typename T>
41static ZTH_MALLOC_INLINE void deallocate(T* p, size_t n = 1) noexcept
42{
43 if(!p)
44 return;
45
46 typename Config::Allocator<T>::type allocator;
47 allocator.deallocate(p, n);
48}
49
50template <typename T>
51static ZTH_MALLOC_INLINE void delete_alloc(T* p) noexcept
52{
53 if(unlikely(!p))
54 return;
55
56 p->~T();
57 deallocate(p);
58}
59
64template <typename T>
65__attribute__((warn_unused_result, returns_nonnull)) ZTH_MALLOC_ATTR(
66 (malloc((void (*)(T*, size_t) noexcept)deallocate, 1),
67 alloc_size(1))) static ZTH_MALLOC_INLINE T* allocate(size_t n = 1)
68{
69 typename Config::Allocator<T>::type allocator;
70 return allocator.allocate(n);
71}
72
81template <typename T>
82__attribute__((warn_unused_result)) ZTH_MALLOC_ATTR(
83 (malloc((void (*)(T*, size_t) noexcept)deallocate, 1),
84 alloc_size(1))) static ZTH_MALLOC_INLINE T* allocate_noexcept(size_t n = 1) noexcept
85{
86 try {
87 return allocate<T>(n);
88 } catch(std::bad_alloc const&) {
89 return nullptr;
90 } catch(...) {
91 std::terminate();
92 }
93
94 // Should not get here.
95 return nullptr;
96}
97
98template <typename T>
99__attribute__((warn_unused_result, returns_nonnull)) ZTH_MALLOC_ATTR(
100 (malloc((void (*)(T*) noexcept)delete_alloc))) static ZTH_MALLOC_INLINE T* new_alloc()
101{
102 T* o = allocate<T>();
103 try {
104 new(o) T;
105 return o;
106 } catch(...) {
107 deallocate(o);
108 zth_throw();
109 } // cppcheck-suppress missingReturn
110
111 // Should not get here.
112}
113
114template <typename T, typename Arg>
115__attribute__((warn_unused_result, returns_nonnull)) ZTH_MALLOC_ATTR((malloc(
116 (void (*)(T*) noexcept)delete_alloc))) static ZTH_MALLOC_INLINE T* new_alloc(Arg const& arg)
117{
118 T* o = allocate<T>();
119 try {
120 new(o) T(arg);
121 return o;
122 } catch(...) {
123 deallocate(o);
124 zth_throw();
125 } // cppcheck-suppress missingReturn
126
127 // Should not get here.
128}
129
130# if __cplusplus >= 201103L
131template <typename T, typename... Arg>
132__attribute__((warn_unused_result, returns_nonnull)) ZTH_MALLOC_ATTR((malloc(
133 (void (*)(T*) noexcept)delete_alloc))) static ZTH_MALLOC_INLINE T* new_alloc(Arg&&... arg)
134{
135 T* o = allocate<T>();
136 try {
137 new(o) T{std::forward<Arg>(arg)...};
138 return o;
139 } catch(...) {
140 deallocate(o);
141 zth_throw();
142 } // cppcheck-suppress missingReturn
143
144 // Should not get here.
145}
146# endif
147
158// cppcheck-suppress-macro duplInheritedMember
159# define ZTH_CLASS_NEW_DELETE(T) \
160 public: \
161 static ZTH_MALLOC_INLINE void operator delete(void* ptr) noexcept \
162 { \
163 ::zth::deallocate<T>(static_cast<T*>(ptr)); \
164 } \
165 ZTH_MALLOC_ATTR((malloc, alloc_size(1))) \
166 __attribute__((warn_unused_result, returns_nonnull)) static ZTH_MALLOC_INLINE void* \
167 operator new(std::size_t UNUSED_PAR(n)) \
168 { \
169 zth_assert(n == sizeof(T)); \
170 return ::zth::allocate<T>(); \
171 } \
172 static ZTH_MALLOC_INLINE void operator delete[](void* ptr, size_t sz) noexcept \
173 { \
174 zth_assert(sz % sizeof(T) == 0); \
175 ::zth::deallocate<T>(static_cast<T*>(ptr), sz / sizeof(T)); \
176 } \
177 ZTH_MALLOC_ATTR((malloc, alloc_size(1))) \
178 __attribute__((warn_unused_result, returns_nonnull)) static ZTH_MALLOC_INLINE void* \
179 operator new[](std::size_t sz) \
180 { \
181 zth_assert(sz % sizeof(T) == 0); \
182 return ::zth::allocate<T>(sz / sizeof(T)); \
183 } \
184 typedef typename zth::Config::Allocator<T>::type allocator_type; /* NOLINT */ \
185 \
186 private:
187
192template <typename T>
194 typedef std::vector<T, typename Config::Allocator<T>::type> type;
195};
196
201template <typename Key, typename T, typename Compare = std::less<Key> >
202struct map_type {
203 typedef std::map<
204 Key, T, Compare, typename Config::Allocator<std::pair<const Key, T> >::type>
206};
207
212template <typename T>
213struct list_type {
214 typedef std::list<T, typename Config::Allocator<T>::type> type;
215};
216
217template <typename Traits, typename Allocator>
218string to_zth_string(std::basic_string<char, Traits, Allocator> const& s)
219{
220 return string(s.data(), s.size());
221}
222
223inline std::string to_std_string(string const& s)
224{
225 return std::string(s.data(), s.size());
226}
227
228} // namespace zth
229#endif // __cplusplus
230#endif // ZTH_ALLOCATOR_H
#define ZTH_MALLOC_ATTR(attr)
Definition allocator.h:32
#define ZTH_MALLOC_INLINE
Definition allocator.h:28
std::basic_string< char, std::char_traits< char >, Config::Allocator< char >::type > string
std::string type using Config::Allocator::type.
Definition util.h:315
#define zth_throw(...)
Definition macros.h:365
std::string to_std_string(string const &s)
Definition allocator.h:223
string to_zth_string(std::basic_string< char, Traits, Allocator > const &s)
Definition allocator.h:218
std::list type using Config::Allocator::type.
Definition allocator.h:213
std::list< T, typename Config::Allocator< T >::type > type
Definition allocator.h:214
std::map type using Config::Allocator::type.
Definition allocator.h:202
std::map< Key, T, Compare, typename Config::Allocator< std::pair< const Key, T > >::type > type
Definition allocator.h:205
std::vector type using Config::Allocator::type.
Definition allocator.h:193
std::vector< T, typename Config::Allocator< T >::type > type
Definition allocator.h:194
#define unlikely(expr)
Marks the given expression to likely be evaluated to true.
Definition util.h:60