//purpose : Constructor
//=======================================================================
-NCollection_IncAllocator::NCollection_IncAllocator (const size_t theBlockSize)
+NCollection_IncAllocator::NCollection_IncAllocator (size_t theBlockSize)
+: myMutex (NULL)
{
#ifdef ALLOC_TRACK_USAGE
printf ("\n..NCollection_IncAllocator: Created (%x)\n",this);
NCollection_IncAllocator::~NCollection_IncAllocator ()
{
+ delete myMutex;
#ifdef OCCT_DEBUG
if (IS_DEBUG)
Debug_Destroy(this);
free (myFirstBlock);
}
+//=======================================================================
+//function : SetThreadSafe
+//purpose :
+//=======================================================================
+void NCollection_IncAllocator::SetThreadSafe (bool theIsThreadSafe)
+{
+ if (myMutex == NULL
+ && theIsThreadSafe)
+ {
+ myMutex = new Standard_Mutex();
+ }
+ else if (!theIsThreadSafe)
+ {
+ delete myMutex;
+ myMutex = NULL;
+ }
+}
+
//=======================================================================
//function : Allocate
//purpose : allocate a memory
aligned_t * aResult = NULL;
const size_t cSize = aSize ? IMEM_SIZE(aSize) : 0;
+ Standard_Mutex::Sentry aLock (myMutex);
if (cSize > mySize) {
/* If the requested size exceeds normal allocation size, allocate
a separate block and place it as the head of the list */
// Check that the dummy parameters are OK
if (theAddress == NULL || oldSize == 0)
return Allocate (newSize);
+
const size_t cOldSize = IMEM_SIZE(oldSize);
const size_t cNewSize = newSize ? IMEM_SIZE(newSize) : 0;
aligned_t * anAddress = (aligned_t *) theAddress;
+ Standard_Mutex::Sentry aLock (myMutex);
// We check only the LAST allocation to do the real extension/contraction
if (anAddress + cOldSize == myFirstBlock -> p_free_space) {
myFirstBlock -> p_free_space = anAddress;
void NCollection_IncAllocator::Reset (const Standard_Boolean doReleaseMem)
{
+ Standard_Mutex::Sentry aLock (myMutex);
if (doReleaseMem)
Clean();
else {
#include <NCollection_BaseAllocator.hxx>
+class Standard_Mutex;
+
/**
* Class NCollection_IncAllocator - incremental memory allocator. This class
* allocates memory on request returning the pointer to an allocated
* block. This memory is never returned to the system until the allocator is
* destroyed.
- *
+ *
* By comparison with the standard new() and malloc() calls, this method is
* faster and consumes very small additional memory to maintain the heap.
- *
+ *
* All pointers returned by Allocate() are aligned to the size of the data
* type "aligned_t". To modify the size of memory blocks requested from the
* OS, use the parameter of the constructor (measured in bytes); if this
* parameter is smaller than 25 bytes on 32bit or 49 bytes on 64bit, the
* block size will be the default 24 kbytes
+ *
+ * Note that this allocator is most suitable for single-threaded algorithms
+ * (consider creating dedicated allocators per working thread),
+ * and thread-safety of allocations is DISABLED by default (see SetThreadSafe()).
*/
class NCollection_IncAllocator : public NCollection_BaseAllocator
{
// ---------- PUBLIC METHODS ----------
- //! Constructor
- Standard_EXPORT NCollection_IncAllocator (const size_t theBlockSize = DefaultBlockSize);
+ //! Constructor.
+ //! Note that this constructor does NOT setup mutex for using allocator concurrently from different threads,
+ //! see SetThreadSafe() method.
+ Standard_EXPORT NCollection_IncAllocator (size_t theBlockSize = DefaultBlockSize);
+
+ //! Setup mutex for thread-safe allocations.
+ Standard_EXPORT void SetThreadSafe (bool theIsThreadSafe = true);
//! Allocate memory with given size. Returns NULL on failure
Standard_EXPORT virtual void* Allocate (const size_t size) Standard_OVERRIDE;
};
protected:
// --------- PROTECTED FIELDS ---------
+ Standard_Mutex* myMutex;
IBlock * myFirstBlock;
size_t mySize;
size_t myMemSize;