From 95c882e9d45466a9e296f33fb6a10289cf40332f Mon Sep 17 00:00:00 2001 From: kgv Date: Mon, 4 Feb 2019 12:21:14 +0300 Subject: [PATCH] 0030329: Move BRepMesh_IncAllocator to NCollection package NCollection_IncAllocator has been extended with optional mutex allocation (disabled by default). --- src/BRepMesh/BRepMesh_FaceChecker.cxx | 1 - src/BRepMesh/BRepMesh_IncAllocator.hxx | 50 -------------------- src/BRepMesh/FILES | 1 - src/BRepMeshData/BRepMeshData_Model.cxx | 6 ++- src/NCollection/NCollection_IncAllocator.cxx | 26 +++++++++- src/NCollection/NCollection_IncAllocator.hxx | 20 ++++++-- 6 files changed, 45 insertions(+), 59 deletions(-) delete mode 100644 src/BRepMesh/BRepMesh_IncAllocator.hxx diff --git a/src/BRepMesh/BRepMesh_FaceChecker.cxx b/src/BRepMesh/BRepMesh_FaceChecker.cxx index 8897c90852..080e555c3b 100644 --- a/src/BRepMesh/BRepMesh_FaceChecker.cxx +++ b/src/BRepMesh/BRepMesh_FaceChecker.cxx @@ -18,7 +18,6 @@ #include #include #include -#include namespace { diff --git a/src/BRepMesh/BRepMesh_IncAllocator.hxx b/src/BRepMesh/BRepMesh_IncAllocator.hxx deleted file mode 100644 index 923acc0e98..0000000000 --- a/src/BRepMesh/BRepMesh_IncAllocator.hxx +++ /dev/null @@ -1,50 +0,0 @@ -// Created on: 2016-06-20 -// Created by: Oleg AGASHIN -// Copyright (c) 2016 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#ifndef _BRepMesh_IncAllocator_HeaderFile -#define _BRepMesh_IncAllocator_HeaderFile - -#include -#include - -//! Extension for NCollection_IncAllocator implementing simple thread safety -//! by introduction of Mutex. Intended for use in couple with BRepMeshData -//! entities in order to prevent data races while building data model in -//! parallel mode. Note that this allocator is supposed for use by collections -//! which allocate memory by huge blocks at arbitrary moment, thus it should -//! not introduce significant performance slow down. -class BRepMesh_IncAllocator : public NCollection_IncAllocator -{ -public: - //! Constructor - BRepMesh_IncAllocator(const size_t theBlockSize = DefaultBlockSize) - : NCollection_IncAllocator(theBlockSize) - { - } - - //! Allocate memory with given size. Returns NULL on failure - virtual void* Allocate(const size_t size) Standard_OVERRIDE - { - Standard_Mutex::Sentry aSentry(myMutex); - return NCollection_IncAllocator::Allocate(size); - } - - DEFINE_STANDARD_RTTI_INLINE(BRepMesh_IncAllocator, NCollection_IncAllocator) - -private: - Standard_Mutex myMutex; -}; - -#endif diff --git a/src/BRepMesh/FILES b/src/BRepMesh/FILES index 1279420cc3..a5a8d22c0e 100755 --- a/src/BRepMesh/FILES +++ b/src/BRepMesh/FILES @@ -46,7 +46,6 @@ BRepMesh_FactoryError.hxx BRepMesh_FastDiscret.hxx BRepMesh_GeomTool.cxx BRepMesh_GeomTool.hxx -BRepMesh_IncAllocator.hxx BRepMesh_IncrementalMesh.cxx BRepMesh_IncrementalMesh.hxx BRepMesh_MeshAlgoFactory.cxx diff --git a/src/BRepMeshData/BRepMeshData_Model.cxx b/src/BRepMeshData/BRepMeshData_Model.cxx index bd2e74c120..08c07f8c96 100644 --- a/src/BRepMeshData/BRepMeshData_Model.cxx +++ b/src/BRepMeshData/BRepMeshData_Model.cxx @@ -14,11 +14,12 @@ // commercial license or contractual agreement. #include + #include #include -#include #include #include +#include //======================================================================= // Function: Constructor @@ -27,10 +28,11 @@ BRepMeshData_Model::BRepMeshData_Model (const TopoDS_Shape& theShape) : IMeshData_Model (theShape), myMaxSize (0.), - myAllocator (new BRepMesh_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)), + myAllocator (new NCollection_IncAllocator (IMeshData::MEMORY_BLOCK_SIZE_HUGE)), myDFaces (256, myAllocator), myDEdges (256, myAllocator) { + myAllocator->SetThreadSafe(); } //======================================================================= diff --git a/src/NCollection/NCollection_IncAllocator.cxx b/src/NCollection/NCollection_IncAllocator.cxx index a867afa4e6..35ce1f6248 100644 --- a/src/NCollection/NCollection_IncAllocator.cxx +++ b/src/NCollection/NCollection_IncAllocator.cxx @@ -177,7 +177,8 @@ Standard_EXPORT void IncAllocator_PrintAlive() //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); @@ -207,6 +208,7 @@ NCollection_IncAllocator::NCollection_IncAllocator (const size_t theBlockSize) NCollection_IncAllocator::~NCollection_IncAllocator () { + delete myMutex; #ifdef OCCT_DEBUG if (IS_DEBUG) Debug_Destroy(this); @@ -215,6 +217,24 @@ NCollection_IncAllocator::~NCollection_IncAllocator () 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 @@ -226,6 +246,7 @@ void * NCollection_IncAllocator::Allocate (const size_t aSize) 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 */ @@ -286,10 +307,12 @@ void * NCollection_IncAllocator::Reallocate (void * theAddress, // 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; @@ -372,6 +395,7 @@ void NCollection_IncAllocator::Clean () void NCollection_IncAllocator::Reset (const Standard_Boolean doReleaseMem) { + Standard_Mutex::Sentry aLock (myMutex); if (doReleaseMem) Clean(); else { diff --git a/src/NCollection/NCollection_IncAllocator.hxx b/src/NCollection/NCollection_IncAllocator.hxx index fa6f53f871..84e32f8fc4 100644 --- a/src/NCollection/NCollection_IncAllocator.hxx +++ b/src/NCollection/NCollection_IncAllocator.hxx @@ -18,20 +18,26 @@ #include +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 { @@ -41,8 +47,13 @@ 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; @@ -105,6 +116,7 @@ class NCollection_IncAllocator : public NCollection_BaseAllocator }; protected: // --------- PROTECTED FIELDS --------- + Standard_Mutex* myMutex; IBlock * myFirstBlock; size_t mySize; size_t myMemSize; -- 2.20.1