Mercurial > foo_out_sdl
comparison foosdk/sdk/pfc/alloc.h @ 1:20d02a178406 default tip
*: check in everything else
yay
| author | Paper <paper@tflc.us> |
|---|---|
| date | Mon, 05 Jan 2026 02:15:46 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:e9bb126753e7 | 1:20d02a178406 |
|---|---|
| 1 #pragma once | |
| 2 | |
| 3 #include "primitives.h" | |
| 4 | |
| 5 namespace pfc { | |
| 6 | |
| 7 static void * raw_malloc(t_size p_size) { | |
| 8 return p_size > 0 ? new_ptr_check_t(malloc(p_size)) : NULL; | |
| 9 } | |
| 10 | |
| 11 static void raw_free(void * p_block) throw() {free(p_block);} | |
| 12 | |
| 13 inline void* raw_realloc(void * p_ptr,t_size p_size) { | |
| 14 if (p_size == 0) {raw_free(p_ptr); return NULL;} | |
| 15 else if (p_ptr == NULL) return raw_malloc(p_size); | |
| 16 else return pfc::new_ptr_check_t(::realloc(p_ptr,p_size)); | |
| 17 } | |
| 18 | |
| 19 inline bool raw_realloc_inplace(void * p_block,t_size p_size) throw() { | |
| 20 if (p_block == NULL) return p_size == 0; | |
| 21 #ifdef _MSC_VER | |
| 22 if (p_size == 0) return false; | |
| 23 return _expand(p_block,p_size) != NULL; | |
| 24 #else | |
| 25 return false; | |
| 26 #endif | |
| 27 } | |
| 28 | |
| 29 template<typename T> | |
| 30 t_size calc_array_width(t_size p_width) { | |
| 31 return pfc::mul_safe_t<std::bad_alloc,t_size>(p_width,sizeof(T)); | |
| 32 } | |
| 33 | |
| 34 template<typename T> | |
| 35 T * __raw_malloc_t(t_size p_size) { | |
| 36 return reinterpret_cast<T*>(raw_malloc(calc_array_width<T>(p_size))); | |
| 37 } | |
| 38 | |
| 39 template<typename T> | |
| 40 void __raw_free_t(T * p_block) throw() { | |
| 41 raw_free(reinterpret_cast<void*>(p_block)); | |
| 42 } | |
| 43 | |
| 44 template<typename T> | |
| 45 T * __raw_realloc_t(T * p_block,t_size p_size) { | |
| 46 return reinterpret_cast<T*>(raw_realloc(p_block,calc_array_width<T>(p_size))); | |
| 47 } | |
| 48 | |
| 49 template<typename T> | |
| 50 bool __raw_realloc_inplace_t(T * p_block,t_size p_size) { | |
| 51 return raw_realloc_inplace(p_block,calc_array_width<T>(p_size)); | |
| 52 } | |
| 53 | |
| 54 | |
| 55 template<typename t_exception,typename t_int> | |
| 56 inline t_int safe_shift_left_t(t_int p_val,t_size p_shift = 1) { | |
| 57 t_int newval = p_val << p_shift; | |
| 58 if (newval >> p_shift != p_val) throw t_exception(); | |
| 59 return newval; | |
| 60 } | |
| 61 | |
| 62 template<typename t_item> class alloc_dummy { | |
| 63 private: typedef alloc_dummy<t_item> t_self; | |
| 64 public: | |
| 65 alloc_dummy() {} | |
| 66 void set_size(t_size p_size) {throw pfc::exception_not_implemented();} | |
| 67 t_size get_size() const {throw pfc::exception_not_implemented();} | |
| 68 const t_item & operator[](t_size p_index) const {throw pfc::exception_not_implemented();} | |
| 69 t_item & operator[](t_size p_index) {throw pfc::exception_not_implemented();} | |
| 70 | |
| 71 bool is_ptr_owned(const void * p_item) const {return false;} | |
| 72 | |
| 73 //set to true when we prioritize speed over memory usage | |
| 74 enum { alloc_prioritizes_speed = false }; | |
| 75 | |
| 76 //not mandatory | |
| 77 const t_item * get_ptr() const {throw pfc::exception_not_implemented();} | |
| 78 t_item * get_ptr() {throw pfc::exception_not_implemented();} | |
| 79 void prealloc(t_size) {throw pfc::exception_not_implemented();} | |
| 80 void force_reset() {throw pfc::exception_not_implemented();} | |
| 81 void move_from(t_self &) {throw pfc::exception_not_implemented();} | |
| 82 private: | |
| 83 const t_self & operator=(const t_self &) {throw pfc::exception_not_implemented();} | |
| 84 alloc_dummy(const t_self&) {throw pfc::exception_not_implemented();} | |
| 85 }; | |
| 86 | |
| 87 template<typename t_item> | |
| 88 bool is_pointer_in_range(const t_item * p_buffer,t_size p_buffer_size,const void * p_pointer) { | |
| 89 return p_pointer >= reinterpret_cast<const void*>(p_buffer) && p_pointer < reinterpret_cast<const void*>(p_buffer + p_buffer_size); | |
| 90 } | |
| 91 | |
| 92 | |
| 93 //! Simple inefficient fully portable allocator. | |
| 94 template<typename t_item> class alloc_simple { | |
| 95 private: typedef alloc_simple<t_item> t_self; | |
| 96 public: | |
| 97 alloc_simple() : m_data(NULL), m_size(0) {} | |
| 98 void set_size(t_size p_size) { | |
| 99 if (p_size != m_size) { | |
| 100 t_item * l_data = NULL; | |
| 101 if (p_size > 0) l_data = new t_item[p_size]; | |
| 102 try { | |
| 103 pfc::memcpy_t(l_data,m_data,pfc::min_t(m_size,p_size)); | |
| 104 } catch(...) { | |
| 105 delete[] l_data; | |
| 106 throw; | |
| 107 } | |
| 108 delete[] m_data; | |
| 109 m_data = l_data; | |
| 110 m_size = p_size; | |
| 111 } | |
| 112 } | |
| 113 t_size get_size() const {return m_size;} | |
| 114 const t_item & operator[](t_size p_index) const {PFC_ASSERT(p_index < m_size); return m_data[p_index];} | |
| 115 t_item & operator[](t_size p_index) {PFC_ASSERT(p_index < m_size); return m_data[p_index];} | |
| 116 bool is_ptr_owned(const void * p_item) const {return is_pointer_in_range(get_ptr(),get_size(),p_item);} | |
| 117 | |
| 118 enum { alloc_prioritizes_speed = false }; | |
| 119 | |
| 120 t_item * get_ptr() {return m_data;} | |
| 121 const t_item * get_ptr() const {return m_data;} | |
| 122 | |
| 123 void prealloc(t_size) {} | |
| 124 void force_reset() {set_size(0);} | |
| 125 | |
| 126 ~alloc_simple() {delete[] m_data;} | |
| 127 | |
| 128 void move_from(t_self & other) noexcept { | |
| 129 delete[] m_data; | |
| 130 m_data = replace_null_t(other.m_data); | |
| 131 m_size = replace_null_t(other.m_size); | |
| 132 } | |
| 133 private: | |
| 134 const t_self & operator=(const t_self &) = delete; | |
| 135 alloc_simple(const t_self&) = delete; | |
| 136 | |
| 137 t_item * m_data; | |
| 138 t_size m_size; | |
| 139 }; | |
| 140 | |
| 141 template<typename t_item> class __array_fast_helper_t { | |
| 142 private: | |
| 143 typedef __array_fast_helper_t<t_item> t_self; | |
| 144 public: | |
| 145 __array_fast_helper_t() : m_buffer(NULL), m_size(0), m_size_total(0) {} | |
| 146 | |
| 147 | |
| 148 void set_size(t_size p_size,t_size p_size_total) { | |
| 149 PFC_ASSERT(p_size <= p_size_total); | |
| 150 PFC_ASSERT(m_size <= m_size_total); | |
| 151 if (p_size_total > m_size_total) { | |
| 152 resize_storage(p_size_total); | |
| 153 resize_content(p_size); | |
| 154 } else { | |
| 155 resize_content(p_size); | |
| 156 resize_storage(p_size_total); | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 | |
| 161 | |
| 162 t_size get_size() const {return m_size;} | |
| 163 t_size get_size_total() const {return m_size_total;} | |
| 164 const t_item & operator[](t_size p_index) const {PFC_ASSERT(p_index < m_size); return m_buffer[p_index];} | |
| 165 t_item & operator[](t_size p_index) {PFC_ASSERT(p_index < m_size); return m_buffer[p_index];} | |
| 166 ~__array_fast_helper_t() { | |
| 167 set_size(0,0); | |
| 168 } | |
| 169 t_item * get_ptr() {return m_buffer;} | |
| 170 const t_item * get_ptr() const {return m_buffer;} | |
| 171 bool is_ptr_owned(const void * p_item) const {return is_pointer_in_range(m_buffer,m_size_total,p_item);} | |
| 172 | |
| 173 void move_from(t_self & other) { | |
| 174 set_size(0,0); | |
| 175 m_buffer = replace_null_t(other.m_buffer); | |
| 176 m_size = replace_null_t(other.m_size); | |
| 177 m_size_total = replace_null_t(other.m_size_total); | |
| 178 } | |
| 179 private: | |
| 180 const t_self & operator=(const t_self &) = delete; | |
| 181 __array_fast_helper_t(const t_self &) = delete; | |
| 182 | |
| 183 | |
| 184 void resize_content(t_size p_size) { | |
| 185 if constexpr (traits_t<t_item>::needs_constructor || traits_t<t_item>::needs_destructor) { | |
| 186 if (p_size > m_size) {//expand | |
| 187 do { | |
| 188 __unsafe__in_place_constructor_t(m_buffer[m_size]); | |
| 189 m_size++; | |
| 190 } while(m_size < p_size); | |
| 191 } else if (p_size < m_size) { | |
| 192 __unsafe__in_place_destructor_array_t(m_buffer + p_size, m_size - p_size); | |
| 193 m_size = p_size; | |
| 194 } | |
| 195 } else { | |
| 196 m_size = p_size; | |
| 197 } | |
| 198 } | |
| 199 | |
| 200 void resize_storage(t_size p_size) { | |
| 201 PFC_ASSERT( m_size <= m_size_total ); | |
| 202 PFC_ASSERT( m_size <= p_size ); | |
| 203 if (m_size_total != p_size) { | |
| 204 if constexpr (pfc::traits_t<t_item>::realloc_safe) { | |
| 205 m_buffer = pfc::__raw_realloc_t(m_buffer,p_size); | |
| 206 m_size_total = p_size; | |
| 207 } else if (__raw_realloc_inplace_t(m_buffer,p_size)) { | |
| 208 //success | |
| 209 m_size_total = p_size; | |
| 210 } else { | |
| 211 t_item * newbuffer = pfc::__raw_malloc_t<t_item>(p_size); | |
| 212 try { | |
| 213 pfc::__unsafe__in_place_constructor_array_copy_t(newbuffer,m_size,m_buffer); | |
| 214 } catch(...) { | |
| 215 pfc::__raw_free_t(newbuffer); | |
| 216 throw; | |
| 217 } | |
| 218 pfc::__unsafe__in_place_destructor_array_t(m_buffer,m_size); | |
| 219 pfc::__raw_free_t(m_buffer); | |
| 220 m_buffer = newbuffer; | |
| 221 m_size_total = p_size; | |
| 222 } | |
| 223 } | |
| 224 } | |
| 225 | |
| 226 t_item * m_buffer; | |
| 227 t_size m_size,m_size_total; | |
| 228 }; | |
| 229 | |
| 230 template<typename t_item> class __array_lite_helper_t { | |
| 231 private: | |
| 232 typedef __array_lite_helper_t<t_item> t_self; | |
| 233 public: | |
| 234 __array_lite_helper_t() : m_buffer(NULL), m_size(0) {} | |
| 235 | |
| 236 | |
| 237 void set_size(t_size p_size) { | |
| 238 if (p_size > m_size) { // expand | |
| 239 resize_storage(p_size); | |
| 240 resize_content(p_size); | |
| 241 } else if (p_size < m_size) { // shrink | |
| 242 resize_content(p_size); | |
| 243 resize_storage(p_size); | |
| 244 } | |
| 245 } | |
| 246 | |
| 247 | |
| 248 | |
| 249 t_size get_size() const {return m_size;} | |
| 250 const t_item & operator[](t_size p_index) const {PFC_ASSERT(p_index < m_size); return m_buffer[p_index];} | |
| 251 t_item & operator[](t_size p_index) {PFC_ASSERT(p_index < m_size); return m_buffer[p_index];} | |
| 252 ~__array_lite_helper_t() { | |
| 253 set_size(0); | |
| 254 } | |
| 255 t_item * get_ptr() {return m_buffer;} | |
| 256 const t_item * get_ptr() const {return m_buffer;} | |
| 257 bool is_ptr_owned(const void * p_item) const {return is_pointer_in_range(m_buffer,m_size,p_item);} | |
| 258 | |
| 259 void move_from(t_self & other) { | |
| 260 set_size(0); | |
| 261 m_buffer = replace_null_t(other.m_buffer); | |
| 262 m_size = replace_null_t(other.m_size); | |
| 263 } | |
| 264 private: | |
| 265 const t_self & operator=(const t_self &) = delete; | |
| 266 __array_lite_helper_t(const t_self &) = delete; | |
| 267 | |
| 268 | |
| 269 void resize_content(t_size p_size) { | |
| 270 if constexpr (traits_t<t_item>::needs_constructor || traits_t<t_item>::needs_destructor) { | |
| 271 if (p_size > m_size) {//expand | |
| 272 do { | |
| 273 __unsafe__in_place_constructor_t(m_buffer[m_size]); | |
| 274 m_size++; | |
| 275 } while(m_size < p_size); | |
| 276 } else if (p_size < m_size) { | |
| 277 __unsafe__in_place_destructor_array_t(m_buffer + p_size, m_size - p_size); | |
| 278 m_size = p_size; | |
| 279 } | |
| 280 } else { | |
| 281 m_size = p_size; | |
| 282 } | |
| 283 } | |
| 284 | |
| 285 void resize_storage(t_size p_size) { | |
| 286 PFC_ASSERT( m_size <= p_size ); | |
| 287 if constexpr (pfc::traits_t<t_item>::realloc_safe) { | |
| 288 m_buffer = pfc::__raw_realloc_t(m_buffer,p_size); | |
| 289 //m_size_total = p_size; | |
| 290 } else if (__raw_realloc_inplace_t(m_buffer,p_size)) { | |
| 291 //success | |
| 292 //m_size_total = p_size; | |
| 293 } else { | |
| 294 t_item * newbuffer = pfc::__raw_malloc_t<t_item>(p_size); | |
| 295 try { | |
| 296 pfc::__unsafe__in_place_constructor_array_copy_t(newbuffer,m_size,m_buffer); | |
| 297 } catch(...) { | |
| 298 pfc::__raw_free_t(newbuffer); | |
| 299 throw; | |
| 300 } | |
| 301 pfc::__unsafe__in_place_destructor_array_t(m_buffer,m_size); | |
| 302 pfc::__raw_free_t(m_buffer); | |
| 303 m_buffer = newbuffer; | |
| 304 //m_size_total = p_size; | |
| 305 } | |
| 306 } | |
| 307 | |
| 308 t_item * m_buffer; | |
| 309 t_size m_size; | |
| 310 }; | |
| 311 | |
| 312 template<typename t_item> class alloc_standard { | |
| 313 private: typedef alloc_standard<t_item> t_self; | |
| 314 public: | |
| 315 alloc_standard() {} | |
| 316 void set_size(t_size p_size) {m_content.set_size(p_size);} | |
| 317 | |
| 318 t_size get_size() const {return m_content.get_size();} | |
| 319 | |
| 320 const t_item & operator[](t_size p_index) const {return m_content[p_index];} | |
| 321 t_item & operator[](t_size p_index) {return m_content[p_index];} | |
| 322 | |
| 323 const t_item * get_ptr() const {return m_content.get_ptr();} | |
| 324 t_item * get_ptr() {return m_content.get_ptr();} | |
| 325 | |
| 326 bool is_ptr_owned(const void * p_item) const {return m_content.is_ptr_owned(p_item);} | |
| 327 void prealloc(t_size p_size) {} | |
| 328 void force_reset() {set_size(0);} | |
| 329 | |
| 330 enum { alloc_prioritizes_speed = false }; | |
| 331 | |
| 332 void move_from(t_self & other) { m_content.move_from(other.m_content); } | |
| 333 private: | |
| 334 alloc_standard(const t_self &) = delete; | |
| 335 const t_self & operator=(const t_self&) = delete; | |
| 336 | |
| 337 __array_lite_helper_t<t_item> m_content; | |
| 338 }; | |
| 339 | |
| 340 template<typename t_item> class alloc_fast { | |
| 341 private: typedef alloc_fast<t_item> t_self; | |
| 342 public: | |
| 343 alloc_fast() {} | |
| 344 | |
| 345 void set_size(t_size p_size) { | |
| 346 t_size size_base = m_data.get_size_total(); | |
| 347 if (size_base == 0) size_base = 1; | |
| 348 while(size_base < p_size) { | |
| 349 size_base = safe_shift_left_t<std::bad_alloc,t_size>(size_base,1); | |
| 350 } | |
| 351 while(size_base >> 2 > p_size) { | |
| 352 size_base >>= 1; | |
| 353 } | |
| 354 m_data.set_size(p_size,size_base); | |
| 355 } | |
| 356 | |
| 357 t_size get_size() const {return m_data.get_size();} | |
| 358 const t_item & operator[](t_size p_index) const {return m_data[p_index];} | |
| 359 t_item & operator[](t_size p_index) {return m_data[p_index];} | |
| 360 | |
| 361 const t_item * get_ptr() const {return m_data.get_ptr();} | |
| 362 t_item * get_ptr() {return m_data.get_ptr();} | |
| 363 bool is_ptr_owned(const void * p_item) const {return m_data.is_ptr_owned(p_item);} | |
| 364 void prealloc(t_size) {} | |
| 365 void force_reset() {m_data.set_size(0,0);} | |
| 366 | |
| 367 enum { alloc_prioritizes_speed = true }; | |
| 368 | |
| 369 void move_from(t_self & other) { m_data.move_from(other.m_data); } | |
| 370 private: | |
| 371 alloc_fast(const t_self &) = delete; | |
| 372 const t_self & operator=(const t_self&) = delete; | |
| 373 __array_fast_helper_t<t_item> m_data; | |
| 374 }; | |
| 375 | |
| 376 template<typename t_item> class alloc_fast_aggressive { | |
| 377 private: typedef alloc_fast_aggressive<t_item> t_self; | |
| 378 public: | |
| 379 alloc_fast_aggressive() {} | |
| 380 | |
| 381 void set_size(t_size p_size) { | |
| 382 t_size size_base = m_data.get_size_total(); | |
| 383 if (size_base == 0) size_base = 1; | |
| 384 while(size_base < p_size) { | |
| 385 size_base = safe_shift_left_t<std::bad_alloc,t_size>(size_base,1); | |
| 386 } | |
| 387 m_data.set_size(p_size,size_base); | |
| 388 } | |
| 389 | |
| 390 void prealloc(t_size p_size) { | |
| 391 if (p_size > 0) { | |
| 392 t_size size_base = m_data.get_size_total(); | |
| 393 if (size_base == 0) size_base = 1; | |
| 394 while(size_base < p_size) { | |
| 395 size_base = safe_shift_left_t<std::bad_alloc,t_size>(size_base,1); | |
| 396 } | |
| 397 m_data.set_size(m_data.get_size(),size_base); | |
| 398 } | |
| 399 } | |
| 400 | |
| 401 t_size get_size() const {return m_data.get_size();} | |
| 402 const t_item & operator[](t_size p_index) const {;return m_data[p_index];} | |
| 403 t_item & operator[](t_size p_index) {return m_data[p_index];} | |
| 404 | |
| 405 const t_item * get_ptr() const {return m_data.get_ptr();} | |
| 406 t_item * get_ptr() {return m_data.get_ptr();} | |
| 407 bool is_ptr_owned(const void * p_item) const {return m_data.is_ptr_owned(p_item);} | |
| 408 void force_reset() {m_data.set_size(0,0);} | |
| 409 | |
| 410 enum { alloc_prioritizes_speed = true }; | |
| 411 | |
| 412 void move_from(t_self & other) { m_data.move_from(other.m_data); } | |
| 413 private: | |
| 414 alloc_fast_aggressive(const t_self &) = delete; | |
| 415 const t_self & operator=(const t_self&) = delete; | |
| 416 __array_fast_helper_t<t_item> m_data; | |
| 417 }; | |
| 418 | |
| 419 template<t_size p_width> class alloc_fixed { | |
| 420 public: | |
| 421 template<typename t_item> class alloc { | |
| 422 private: typedef alloc<t_item> t_self; | |
| 423 public: | |
| 424 alloc() : m_size(0) {} | |
| 425 | |
| 426 void set_size(t_size p_size) { | |
| 427 static_assert_t<sizeof(m_array) == sizeof(t_item[p_width])>(); | |
| 428 | |
| 429 if (p_size > p_width) throw pfc::exception_overflow(); | |
| 430 else if (p_size > m_size) { | |
| 431 __unsafe__in_place_constructor_array_t(get_ptr()+m_size,p_size-m_size); | |
| 432 m_size = p_size; | |
| 433 } else if (p_size < m_size) { | |
| 434 __unsafe__in_place_destructor_array_t(get_ptr()+p_size,m_size-p_size); | |
| 435 m_size = p_size; | |
| 436 } | |
| 437 } | |
| 438 | |
| 439 ~alloc() { | |
| 440 if constexpr (pfc::traits_t<t_item>::needs_destructor) set_size(0); | |
| 441 } | |
| 442 | |
| 443 t_size get_size() const {return m_size;} | |
| 444 | |
| 445 t_item * get_ptr() {return reinterpret_cast<t_item*>(&m_array);} | |
| 446 const t_item * get_ptr() const {return reinterpret_cast<const t_item*>(&m_array);} | |
| 447 | |
| 448 const t_item & operator[](t_size n) const {return get_ptr()[n];} | |
| 449 t_item & operator[](t_size n) {return get_ptr()[n];} | |
| 450 bool is_ptr_owned(const void * p_item) const {return is_pointer_in_range(get_ptr(),p_width,p_item);} | |
| 451 void prealloc(t_size) {} | |
| 452 void force_reset() {set_size(0);} | |
| 453 | |
| 454 enum { alloc_prioritizes_speed = false }; | |
| 455 | |
| 456 void move_from(t_self & other) { | |
| 457 const size_t count = other.get_size(); | |
| 458 set_size( count ); | |
| 459 for(size_t w = 0; w < count; ++w) this->get_ptr()[w] = other.get_ptr()[w]; | |
| 460 } | |
| 461 private: | |
| 462 alloc(const t_self&) {throw pfc::exception_not_implemented();} | |
| 463 const t_self& operator=(const t_self&) {throw pfc::exception_not_implemented();} | |
| 464 | |
| 465 t_uint8 m_array[sizeof(t_item[p_width])]; | |
| 466 t_size m_size; | |
| 467 }; | |
| 468 }; | |
| 469 | |
| 470 template<t_size p_width, template<typename> class t_alloc = alloc_standard > class alloc_hybrid { | |
| 471 public: | |
| 472 template<typename t_item> class alloc { | |
| 473 private: typedef alloc<t_item> t_self; | |
| 474 public: | |
| 475 alloc() {} | |
| 476 | |
| 477 void set_size(t_size p_size) { | |
| 478 if (p_size > p_width) { | |
| 479 m_fixed.set_size(p_width); | |
| 480 m_variable.set_size(p_size - p_width); | |
| 481 } else { | |
| 482 m_fixed.set_size(p_size); | |
| 483 m_variable.set_size(0); | |
| 484 } | |
| 485 } | |
| 486 | |
| 487 t_item & operator[](t_size p_index) { | |
| 488 PFC_ASSERT(p_index < get_size()); | |
| 489 if (p_index < p_width) return m_fixed[p_index]; | |
| 490 else return m_variable[p_index - p_width]; | |
| 491 } | |
| 492 | |
| 493 const t_item & operator[](t_size p_index) const { | |
| 494 PFC_ASSERT(p_index < get_size()); | |
| 495 if (p_index < p_width) return m_fixed[p_index]; | |
| 496 else return m_variable[p_index - p_width]; | |
| 497 } | |
| 498 | |
| 499 t_size get_size() const {return m_fixed.get_size() + m_variable.get_size();} | |
| 500 bool is_ptr_owned(const void * p_item) const {return m_fixed.is_ptr_owned(p_item) || m_variable.is_ptr_owned(p_item);} | |
| 501 void prealloc(t_size p_size) { | |
| 502 if (p_size > p_width) m_variable.prealloc(p_size - p_width); | |
| 503 } | |
| 504 void force_reset() { | |
| 505 m_fixed.force_reset(); m_variable.force_reset(); | |
| 506 } | |
| 507 enum { alloc_prioritizes_speed = t_alloc<t_item>::alloc_prioritizes_speed }; | |
| 508 | |
| 509 void move_from(t_self & other) { | |
| 510 m_fixed.move_from(other.m_fixed); | |
| 511 m_variable.move_from(other.m_variable); | |
| 512 } | |
| 513 private: | |
| 514 alloc(const t_self&) {throw pfc::exception_not_implemented();} | |
| 515 const t_self& operator=(const t_self&) {throw pfc::exception_not_implemented();} | |
| 516 | |
| 517 typename alloc_fixed<p_width>::template alloc<t_item> m_fixed; | |
| 518 t_alloc<t_item> m_variable; | |
| 519 }; | |
| 520 }; | |
| 521 | |
| 522 template<typename t_item> class traits_t<alloc_simple<t_item> > : public traits_default_movable {}; | |
| 523 template<typename t_item> class traits_t<__array_fast_helper_t<t_item> > : public traits_default_movable {}; | |
| 524 template<typename t_item> class traits_t<alloc_standard<t_item> > : public pfc::traits_t<__array_fast_helper_t<t_item> > {}; | |
| 525 template<typename t_item> class traits_t<alloc_fast<t_item> > : public pfc::traits_t<__array_fast_helper_t<t_item> > {}; | |
| 526 template<typename t_item> class traits_t<alloc_fast_aggressive<t_item> > : public pfc::traits_t<__array_fast_helper_t<t_item> > {}; | |
| 527 | |
| 528 #if 0//not working (compiler bug?) | |
| 529 template<t_size p_width,typename t_item> class traits_t<typename alloc_fixed<p_width>::template alloc<t_item> > : public pfc::traits_t<t_item> { | |
| 530 public: | |
| 531 enum { | |
| 532 needs_constructor = true, | |
| 533 }; | |
| 534 }; | |
| 535 | |
| 536 template<t_size p_width,template<typename> class t_alloc,typename t_item> | |
| 537 class traits_t<typename alloc_hybrid<p_width,t_alloc>::template alloc<t_item> > : public traits_combined<t_alloc,typename alloc_fixed<p_width>::template alloc<t_item> > {}; | |
| 538 #endif | |
| 539 | |
| 540 | |
| 541 }; |
