![]() |
GemaCoreLib
The GeMA Core library
|
An implementation of the GmAppendBuffer interface based on synchoronized access to a shared buffer. More...
#include <gmAppendBuffer.h>
Classes | |
struct | ControllData |
Aux controll structure storing a buffer. More... | |
Public Member Functions | |
GmSingleAppendBuffer (size_t initSize, double resizeFactor=2.0, int numThreads=-1) | |
Buffer constructor. Can optionally pre allocate the buffer with initSize entries. If initSize is zero, a call to reserve() MUST be made before any append. The given resizeFactor controlls how the buffer grows in case of a resize. See the class comments for additional info. More... | |
~GmSingleAppendBuffer () | |
Destructor. Releases the allocated memory. | |
virtual void | clear () |
virtual void | reserve (size_t bsize) |
See comments on the base class. Should not be called if the size was given in the constructor. | |
virtual void | append (const T &val) |
virtual void | appendFromThread (int tid, const T &val) |
virtual size_t | size () const |
virtual T * | data () |
virtual size_t | usedMemory () const |
Protected Member Functions | |
void | clearList () |
Protected Attributes | |
ControllData * | _head |
Pointer to the first allocated buffer. | |
double | _resizeFactor |
The resize factor. | |
QAtomicInteger< size_t > | _nextIndex |
The next free index in the global vector. | |
QAtomicPointer< ControllData > | _controll |
The controll block pointing to the current buffer. | |
GmSpinLock | _controllLock |
The lock controlling changes to _controll. | |
T * | _dataBuffer |
The single buffer after a call to data() | |
int | _nt |
Number of threads considered for parallel memcopy. | |
An implementation of the GmAppendBuffer interface based on synchoronized access to a shared buffer.
This class uses atomic opertions to provide an efficient way for multiple threads to append data to a shared vector. When there is need for growing the vector, additional buffers are created (instead of growing the original one).
The initial buffer size needs to be informed either in the constructor or by a call to reserve(). The quality of this initial guess can impact in the overall efficiency of the buffer object. See below.
Calling data() will either return the internal vector if the size given in the buffer initialization was enough to hold all the added data or will allocate a new vector and fill it with the buffer data from the several internal buffers.
Buffer growing is controled by a factor parameter given in the constructor. Considering that the current buffer size at the moment of growing is S and the growing factor is f (f > 1), the new buffer size will be equal to (S * f). The default growing factor is 2.0, but it can be changed for sometihing smaller, like 1.1, if the confidence on the initial size is high.
This class can be more efficient than the GmPerThreadAppendBuffer option when the initial buffer size guess is good (no need to grow the pre-allocated vector) AND the memory usage is close to its limit. In this scenario, the synchronisation price is payed by the possibility of returning the original vector in data(), without the need of allocating more memory in an already low (physical) memory environment.
OBS: This class inherits from a template parameter Base, defaulted to GmAppendBuffer, in order to make it easy for changing the base class to another one that inherits GmAppendBuffer adding additional methods, as is done in the GmSparseMatrixTripletBuffer class.
|
inline |
Buffer constructor. Can optionally pre allocate the buffer with initSize entries. If initSize is zero, a call to reserve() MUST be made before any append. The given resizeFactor controlls how the buffer grows in case of a resize. See the class comments for additional info.
The number of threads defaults to the maximum number of threads as seen by the thread manager (when numThreads is -1). It only affects the number of threads used by parallel memcpy operations