![]() |
ATLAS Offline Software
|
Collection of memory allocators with a common lifetime, plus subsystem summary. More...
#include "AthAllocators/ArenaBase.h"#include "AthAllocators/ArenaHeader.h"#include "AthAllocators/ArenaAllocatorCreator.h"#include "AthAllocators/ArenaAllocatorBase.h"#include <cstdlib>#include <string>#include <ostream>Go to the source code of this file.
Classes | |
| class | SG::Arena |
| Collection of memory allocators with a common lifetime,. More... | |
| class | SG::Arena::Push |
Helper class for making Arena instances current in a stack-like manner. More... | |
Namespaces | |
| SG | |
| Forward declaration. | |
Collection of memory allocators with a common lifetime, plus subsystem summary.
First, a bit of terminology; this also summarizes the major components of the library. This will be followed by more detailed descriptions. See also the individual class headers.
A Handle is the interface the application uses to allocate memory. A Handle is templated on the type being allocated as well as on the underlying Allocator. When a Handle is constructed, it is associated with the Allocator associated with the Arena that is current at that time (a new Allocator is automatically created if required). Therefore, a Handle should not be passed between threads, and Handle objects should not exist across any point where the current store/Arena may be changed.
A Handle also holds a lock on its associated allocator. Therefore, if you try to create two handle instances referencing the same allocator (i.e, same type and same thread), you'll get a deadlock.
Multiple Handle implementations may be available, implementing different strategies for initializing the elements.
Here are some more details about these components. For full details, see the individual class headers.
An Allocator is the fundamental allocator for a single type. Allocator instances generally request memory from the system in big blocks and then divide it up into individual elements. The memory allocated from the system is generally not returned to the system unless explicitly requested; elements not currently in use are kept in a pool for fast allocation. An Allocator class does not depend on the type being allocated. Instead, the necessary information is passed to the Allocator on creation in a parameters structure. This includes the element size, as well as three function pointers:
Any of these may be null, in which case the corresponding call is skipped.
An Allocator has a name, which is used both to identify it in the Allocator registry when Allocators are created on demand and in memory statistics reports. An Allocator must support these operations:
allocate, to allocate a new element.reset, to free all allocated elements. The memory will generally be retained by the Allocator to be reused again quickly.erase, to free all allocated elements, and return all allocated memory to the system.reserve, to adjust the amount of current unused memory which the Allocator keeps in its pool. If the amount of memory requested is greater than what is currently available, the new memory will usually be allocated in a single block. If the amount of memory requested is less than what is currently available, free blocks will be returned to the system, if possible.name to return the Allocator's name, and stats to return the current statistics for the Allocator.There are some additional operations which an Allocator may optionally implement:
free, to free an individual element.resetTo, to free all elements that were allocated after a given element, as well as the element itself.Two Allocator implementations are currently available in the library:
ArenaPoolAllocator: Allocates elements in a stack-like manner. Implements the resetTo operation and an iterator, but does not implement free.ArenaHeapAllocator: An Allocator that allows elements to be individually freed. Implements free, but not resetTo nor an iterator. This Allocator requires maintaining a pointer with each free element. By default, this pointer is kept outside the element, increasing the effective size per element. However, if part of the element may be overwritten while it is free, then the allocator may be configured to have this pointer overlap part of the element.Allocator objects are grouped into Arenas. Each Arena contains a vector of Allocator objects. Each distinct Allocator type is assigned an index into this vector; these indices are globally unique. An Arena is associated with a ArenaHeader, which maintains a notion of the ‘current’ Arena; the ArenaHeader holds a reference to the Allocator vector of the current Arena. An Arena has a makeCurrent operation to nominate it as the current Arena for its ArenaHeader. A helper class Arena::Push is provided to change the current Arena in a stack-like manner. An Arena also has operations to reset or erase all of its Allocators, as well as for summing statistics over them all. An Arena also has a name, which is used in printing statistics reports.
The object that the application uses to allocate memory is provided by the Handle classes. These are templated on the type being allocated as well as on the underlying Allocator class. A Handle is created by passing in the Arena (or ArenaHeader) with which it is created, as well as any optional creation parameters for the Allocator. The first time a given type is seen, it is assigned an index the the Arena Allocator vector. When a Handle is created, it will look up the proper Allocator instance in the current Arena, creating it if needed. The Handle will then forward operations to the underlying Allocator. The library provides two Handle implementations:
ArenaHandle: When this Handle is used, the element constructor/destructor are expected to be called every time an element is allocated/freed by the application. The allocate method returns a void*; it is expected that this will then be used in a placement new. The destructor will be called by the library when elements are freed.Handle allows ‘caching’ already-constructed objects, such that the constructor is run only when the element's memory is first allocated from the system, and the destructor is run only when the element's memory is released back to the system. The allocate method thus returns an already-initialized T*. An optional clear function may be called when the element is freed by the application.An example of the basic usage might be something like this.
See also the unit tests for the Handle classes.
Definition in file Arena.h.
1.8.18