13 #error ("BulkAllocator.h is currently broken; see issue #19494.") 17 #ifndef BULKALLOCATOR_H 18 #define BULKALLOCATOR_H 29 namespace bulk_allocator {
42 virtual const char*
what()
const throw()
override {
return msg; }
45 const char* msg =
nullptr;
97 typedef typename BaseAllocator_t::size_type
size_type;
102 typedef typename BaseAllocator_t::pointer
pointer;
118 { CreateGlobalAllocator(ChunkSize, bPreallocate); }
141 pointer allocate(size_type
n,
const void* = 0);
144 void deallocate(pointer p, size_type n);
147 static void Free() { GlobalAllocator.Free(); }
150 static size_type
GetChunkSize() {
return GlobalAllocator.GetChunkSize(); }
154 { GlobalAllocator.SetChunkSize(ChunkSize); }
161 void CreateGlobalAllocator(size_type ChunkSize,
bool bPreallocate =
false);
204 template <
typename T>
206 std::string name =
typeid(T).name();
209 std::unique_ptr<char, void(*)(void*)> res
210 { abi::__cxa_demangle(name.c_str(), NULL, NULL, &status), std::free };
211 return (status==0) ? res.get() : name ;
217 template <
typename T>
218 inline std::string
demangle(
const T&) {
return demangle<T>(); }
221 namespace bulk_allocator {
233 Counter_t
Count()
const {
return counter; }
240 {
if (!counter)
return false; --counter;
return true; }
243 Counter_t counter = 0;
259 template <
typename T>
268 size_type NewChunkSize = DefaultChunkSize,
bool bPreallocate =
false 278 pointer
Get(size_type
n);
287 void AddUser(size_type NewChunkSize,
bool bPreallocate =
false);
293 size_type AllocatedCount()
const;
296 size_type UsedCount()
const;
299 size_type FreeCount()
const;
302 size_type
NChunks()
const {
return MemoryPool.size(); }
305 std::array<size_type, 2> GetCounts()
const;
308 void SetChunkSize(size_type NewChunkSize,
bool force =
false);
330 pointer free =
nullptr;
335 begin = n? allocator->allocate(n):
nullptr;
358 bool full()
const {
return !available(); }
361 pointer
get() {
return (free != end)? free++:
nullptr; }
364 pointer
get(
size_t n)
367 if ((free += n) <=
end)
return ptr;
387 void Preallocate(size_type n);
392 template <
typename T>
394 std::swap(allocator, from.allocator);
395 std::swap(
begin, from.begin);
396 std::swap(
end, from.end);
397 std::swap(free, from.free);
400 template <
typename T>
404 std::swap(allocator, from.allocator);
405 std::swap(
begin, from.begin);
406 std::swap(
end, from.end);
407 std::swap(free, from.free);
412 template <
typename T>
416 template <
typename T>
419 ChunkSize(NewChunkSize), MemoryPool()
421 Preallocate(bPreallocate? ChunkSize: 0);
423 std::cout <<
"BulkAllocatorBase[" << ((
void*)
this)
424 <<
"] created for type " << demangle<value_type>()
425 <<
" with chunk size " << GetChunkSize()
427 << (GetChunkSize()*
sizeof(
value_type)) <<
" bytes/chunk" 433 template <
typename T>
436 std::cout <<
"BulkAllocatorBase[" << ((
void*)
this) <<
"] freeing " 437 << NChunks() <<
" memory chunks with " << AllocatedCount()
438 <<
" elements" << std::endl;
444 template <
typename T>
447 if (hasUsers())
return true;
453 template <
typename T>
458 SetChunkSize(NewChunkSize);
459 Preallocate(bPreallocate? ChunkSize: 0);
463 template <
typename T>
465 if (MemoryPool.empty() || (MemoryPool.front().available() <
n))
466 MemoryPool.emplace_back(allocator, n);
470 template <
typename T>
475 for (
const auto& chunk: MemoryPool) n += chunk.size();
480 template <
typename T>
485 for (
const auto& chunk: MemoryPool) n += chunk.used();
490 template <
typename T>
491 std::array<typename BulkAllocatorBase<T>::size_type, 2>
496 std::array<BulkAllocatorBase<T>::size_type, 2> stats = {{ 0U, 0U }};
497 for (
const auto& chunk: MemoryPool) {
498 stats[0] += chunk.used();
499 stats[1] += chunk.available();
505 template <
typename T>
509 if ((GetChunkSize() == NewChunkSize) && !force)
return;
511 std::cout <<
"BulkAllocatorBase[" << ((
void*)
this) <<
"]" 512 <<
" changing chunk size: " << GetChunkSize() <<
" => " 513 << NewChunkSize <<
": x" <<
sizeof(
value_type) <<
" byte => " 514 << (NewChunkSize*
sizeof(
value_type)) <<
" bytes/chunk" 517 ChunkSize = NewChunkSize;
521 template <
typename T>
525 if (n == 0)
return nullptr;
527 pointer ptr = MemoryPool.front().get(n);
534 std::array<size_type, 2> stats = GetCounts();
535 std::cout <<
"BulkAllocatorBase[" << ((
void*)
this)
536 <<
"] allocating " <<
std::max(ChunkSize, n)
537 <<
" more elements (on top of the current " << (stats[0] + stats[1])
538 <<
" elements, " << stats[1] <<
" unused)" << std::endl;
540 return MemoryPool.emplace
541 (MemoryPool.begin(), allocator,
std::max(ChunkSize, n))->
get(n);
549 template <
typename T>
553 template <
typename T>
557 GlobalAllocator.AddUser(ChunkSize, bPreallocate);
560 template <
typename T>
563 {
return GlobalAllocator.Get(n); }
565 template <
typename T>
567 return GlobalAllocator.Release(p);
572 #endif // BULKALLOCATOR_H A class managing a memory pool.
BaseAllocator_t::pointer pointer
MemoryChunk_t & operator=(const MemoryChunk_t &)=delete
Can't assign.
void Release(pointer)
Releases memory pointed by the specified pointer (but it does not).
Internal memory chunk; like a std::vector, but does not construct.
BaseAllocator_t::difference_type difference_type
BulkAllocatorBase(size_type NewChunkSize=DefaultChunkSize, bool bPreallocate=false)
Constructor; preallocates memory if explicitly requested.
bool RemoveUser()
Removed a user to the users count; returns false if no user yet.
void deallocate(pointer p, size_type n)
Frees n elements at p.
void CreateGlobalAllocator(size_type ChunkSize, bool bPreallocate=false)
Makes sure we have a valid "global allocator".
Counter_t Count() const
Returns the number of registered users.
pointer Get(size_type n)
Returns a pointer to memory for n new values of type T.
std::array< size_type, 2 > GetCounts() const
Returns an array equivalent to { UsedCount(), FreeCount() }.
void AddUser()
Adds a user to the users count.
Allocator_t::difference_type difference_type
void Free()
Releases the pool of memory; all pointer to it become invalid.
MemoryChunk_t(Allocator_t &alloc, size_type n)
memory_error(const char *message)
static void Free()
Releases all the allocated memory: dangerous!
static SharedAllocator_t GlobalAllocator
The allocator shared by all instances of this object.
BaseAllocator_t::reference reference
~BulkAllocator()
Destructor; memory is freed only if no allocators are left around.
bool full() const
Returns whether the chunk is full.
Exception thrown when BulkAllocator-specific allocation errors happen.
size_type ChunkSize
size of the chunks to add
BulkAllocator() noexcept
Default constructor: uses the default chunk size.
size_type AllocatedCount() const
Returns the total number of entries in the pool.
BaseAllocator_t::size_type size_type
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
BulkAllocator(const BulkAllocator< U > &a) noexcept
General copy constructor; currently, it does not preallocate.
Allocator_t * allocator
reference to the allocator to be used
A simple reference counter, keep track of a number of users.
BaseAllocator_t::const_reference const_reference
pointer allocate(size_type n, const void *=0)
Allocates memory for n elements.
BulkAllocator(size_type ChunkSize, bool bPreallocate=false) noexcept
Constructor: sets chunk size and optionally allocates the first chunk.
virtual const char * what() const override
std::vector< evd::details::RawDigitInfo_t >::const_iterator begin(RawDigitCacheDataClass const &cache)
~BulkAllocatorBase()
Destructor: releases all the memory pool (.
size_type size() const
Returns the number of elements in this pool.
details::bulk_allocator::BulkAllocatorBase< T > SharedAllocator_t
shared allocator type
Allocator_t allocator
the actual allocator we use
Aggressive allocator reserving a lot of memory in advance.
std::string demangle()
Demangles the name of a type.
std::allocator< T > Allocator_t
size_type NChunks() const
Returns the number of memory pool chunks allocated.
static size_type DefaultChunkSize
Default chunk size (default: 10000)
size_type available() const
Returns the number of free elements in this pool.
size_type UsedCount() const
Returns the total number of used entries in the pool.
MemoryChunk_t()
< Default constructor (does nothing)
size_type GetChunkSize() const
Returns the current chunk size.
bool hasUsers() const
Returns whether there are currently users.
unsigned int Counter_t
type of user counter
LArSoft-specific namespace.
static void SetChunkSize(size_type ChunkSize)
Sets chunk size of global allocator; only affects future allocations!
BaseAllocator_t::value_type value_type
BaseAllocator_t::const_pointer const_pointer
std::vector< evd::details::RawDigitInfo_t >::const_iterator end(RawDigitCacheDataClass const &cache)
void SetChunkSize(size_type NewChunkSize, bool force=false)
Sets the chunk size for the future allocations.
std::vector< MemoryChunk_t > MemoryPool_t
std::allocator< T > BaseAllocator_t
size_type used() const
Returns the number of used elements in this pool.
static size_type GetChunkSize()
Returns the chunk size of the underlying global allocator.
bool RemoveUser()
Removed a user to the users count; if no user is left, free the pool.
MemoryPool_t MemoryPool
list of all memory chunks; first is free
void AddUser()
Add a new pool user with the current parameters.