From 00af0ebb9d8e2f67b27719d7f7128d7eebb2ae65 Mon Sep 17 00:00:00 2001 From: oan Date: Fri, 15 Sep 2017 17:22:30 +0300 Subject: [PATCH] 0028931: Eliminate dependency from TBB in OSD_Parallel header Implementation of methods OSD_Parallel::For() and ForEach() is moved to CXX files to avoid direct dependency of client code that uses OSD_Parallel on TBB headers, and necessity to link with TBB explicitly. Runtime polymorphism (virtual methods) is used to hide implementation (TBB or threads-based). --- src/BOPCol/BOPCol_Parallel.hxx | 2 + src/OSD/FILES | 2 + src/OSD/OSD_Parallel.cxx | 1 + src/OSD/OSD_Parallel.hxx | 502 +++++++++--------- src/OSD/OSD_Parallel_TBB.cxx | 46 ++ src/OSD/OSD_Parallel_Threads.cxx | 151 ++++++ src/QABugs/QABugs_19.cxx | 21 +- .../Select3D_SensitivePrimitiveArray.cxx | 1 + src/StdPrs/StdPrs_WFShape.cxx | 1 + 9 files changed, 471 insertions(+), 256 deletions(-) create mode 100644 src/OSD/OSD_Parallel_TBB.cxx create mode 100644 src/OSD/OSD_Parallel_Threads.cxx diff --git a/src/BOPCol/BOPCol_Parallel.hxx b/src/BOPCol/BOPCol_Parallel.hxx index efea73fc69..b4b597f205 100644 --- a/src/BOPCol/BOPCol_Parallel.hxx +++ b/src/BOPCol/BOPCol_Parallel.hxx @@ -19,6 +19,8 @@ #include #include #include +#include +#include // // 1. Implementation of Functors/Starters diff --git a/src/OSD/FILES b/src/OSD/FILES index c9e53811a0..8f563cb0b7 100755 --- a/src/OSD/FILES +++ b/src/OSD/FILES @@ -57,6 +57,8 @@ OSD_OpenMode.hxx OSD_OSDError.hxx OSD_Parallel.cxx OSD_Parallel.hxx +OSD_Parallel_TBB.cxx +OSD_Parallel_Threads.cxx OSD_Path.cxx OSD_Path.hxx OSD_PerfMeter.cxx diff --git a/src/OSD/OSD_Parallel.cxx b/src/OSD/OSD_Parallel.cxx index 2a6cbf222b..b201e8c2b4 100644 --- a/src/OSD/OSD_Parallel.cxx +++ b/src/OSD/OSD_Parallel.cxx @@ -21,6 +21,7 @@ #include #else #include + #include #ifdef __sun #include diff --git a/src/OSD/OSD_Parallel.hxx b/src/OSD/OSD_Parallel.hxx index 3f34408b74..65e3087b0c 100644 --- a/src/OSD/OSD_Parallel.hxx +++ b/src/OSD/OSD_Parallel.hxx @@ -14,25 +14,25 @@ #ifndef OSD_Parallel_HeaderFile #define OSD_Parallel_HeaderFile -#include -#include -#include -#include -#include +#include +#include +#include -#ifdef HAVE_TBB -#include -#include -#include -#endif - -//! @class OSD_Parallel -//! @brief Simplifies code parallelization. +//! @brief Simple tool for code parallelization. //! -//! The Class provides an interface of parallel processing "for" and "foreach" loops. -//! These primitives encapsulates complete logic for creating and managing parallel context of loops. -//! Moreover the primitives may be a wrapper for some primitives from 3rd-party library - TBB. -//! To use it is necessary to implement TBB like interface which is based on functors. +//! OSD_Parallel class provides simple interface for parallel processing of +//! tasks that can be formulated in terms of "for" or "foreach" loops. +//! +//! To use this tool it is necessary to: +//! - organize the data to be processed in a collection accessible by +//! iteration (usually array or vector); +//! - implement a functor class providing operator () accepting iterator +//! (or index in array) that does the job; +//! - call either For() or ForEach() providing begin and end iterators and +//! a functor object. +//! +//! Iterators should satisfy requirements of STL forward iterator. +//! Functor //! //! @code //! class Functor @@ -45,268 +45,286 @@ //! }; //! @endcode //! -//! In the body of the operator () should be implemented thread-safe logic of computations that can be performed in parallel context. -//! If parallelized loop iterates on the collections with direct access by index (such as Vector, Array), -//! it is more efficient to use the primitive ParallelFor (because it has no critical section). +//! The operator () should be implemented in a thread-safe way so that +//! the same functor object can process different data items in parallel threads. +//! +//! Iteration by index (For) is expected to be more efficient than using iterators +//! (ForEach). +//! +//! Implementation uses TBB if OCCT is built with support of TBB; otherwise it +//! uses ad-hoc parallelization tool. In general, if TBB is available, it is +//! more efficient to use it directly instead of using OSD_Parallel. + class OSD_Parallel { - //! Auxiliary class which ensures exclusive - //! access to iterators of processed data pool. - template - class Range +private: + + //! Interface class defining API for polymorphic wrappers over iterators. + //! Intended to add polymorphic behaviour to For and ForEach functionality + //! for arbitrary objects and eliminate dependency on template parameters. + class IteratorInterface { - public: //! @name public methods + public: + virtual ~IteratorInterface() {} - typedef Value Iterator; + //! Returns true if iterators wrapped by this and theOther are equal + virtual bool IsEqual (const IteratorInterface& theOther) const = 0; - //! Constructor - Range(const Value& theBegin, const Value& theEnd) - : myBegin(theBegin), - myEnd (theEnd), - myIt (theBegin) - { - } + //! Increments wrapped iterator + virtual void Increment () = 0; - //! Returns const link on the first element. - inline const Value& Begin() const - { - return myBegin; - } - - //! Returns const link on the last element. - inline const Value& End() const - { - return myEnd; - } - - //! Returns first non processed element or end. - //! Thread-safe method. - inline Iterator It() const - { - Standard_Mutex::Sentry aMutex( myMutex ); - return ( myIt != myEnd ) ? myIt++ : myEnd; - } - - private: //! @name private methods - - //! Empty copy constructor - Range(const Range& theCopy); - - //! Empty copy operator. - Range& operator=(const Range& theCopy); - - private: //! @name private fields - - const Value& myBegin; //!< Fisrt element of range. - const Value& myEnd; //!< Last element of range. - mutable Value myIt; //!< First non processed element of range. - mutable Standard_Mutex myMutex; //!< Access controller for the first non processed element. + //! Returns new instance of the wrapper containing copy + //! of the wrapped iterator. + virtual IteratorInterface* Clone() const = 0; }; - //! Auxiliary wrapper class for thread function. - template - class Task + //! Implementation of polymorphic iterator wrapper suitable for basic + //! types as well as for std iterators. + //! Wraps instance of actual iterator type Type. + template + class IteratorWrapper : public IteratorInterface { - public: //! @name public methods + public: + IteratorWrapper() {} + IteratorWrapper(const Type& theValue) : myValue(theValue) {} - //! Constructor. - Task(const Functor& thePerformer, Range& theRange) - : myPerformer(thePerformer), - myRange (theRange) + virtual bool IsEqual (const IteratorInterface& theOther) const Standard_OVERRIDE { + return myValue == dynamic_cast&>(theOther).myValue; } - //! Method is executed in the context of thread, - //! so this method defines the main calculations. - static Standard_Address RunWithIterator(Standard_Address theTask) + virtual void Increment () Standard_OVERRIDE { - Task& aTask = - *( static_cast< Task* >(theTask) ); - - const Range& aData( aTask.myRange ); - typename Range::Iterator i = aData.It(); - - for ( ; i != aData.End(); i = aData.It() ) - { - aTask.myPerformer(*i); - } - - return NULL; + ++myValue; } - //! Method is executed in the context of thread, - //! so this method defines the main calculations. - static Standard_Address RunWithIndex(Standard_Address theTask) + virtual IteratorInterface* Clone() const Standard_OVERRIDE { - Task& aTask = - *( static_cast< Task* >(theTask) ); - - const Range& aData( aTask.myRange ); - Standard_Integer i = aData.It(); - - for ( ; i < aData.End(); i = aData.It()) - { - aTask.myPerformer(i); - } - - return NULL; + return new IteratorWrapper(myValue); } - private: //! @name private methods + const Type& Value() const { return myValue; } - //! Empty copy constructor. - Task(const Task& theCopy); - - //! Empty copy operator. - Task& operator=(const Task& theCopy); - - private: //! @name private fields - - const Functor& myPerformer; //!< Link on functor. - const Range& myRange; //!< Link on processed data block. + private: + Type myValue; }; -public: //! @name public methods +protected: + // Note: UniversalIterator and FunctorInterface are made protected to be + // accessible from specialization using threads (non-TBB). - //! Returns number of logical proccesrs. - Standard_EXPORT static Standard_Integer NbLogicalProcessors(); + //! Fixed-type iterator, implementing STL forward iterator interface, used for + //! iteration over objects subject to parallel processing. + //! It stores pointer to instance of polymorphic iterator inheriting from + //! IteratorInterface, which contains actual type-specific iterator. + class UniversalIterator : + // Note that TBB requires that value_type of iterator be copyable, + // thus we use its own type for that + public std::iterator + { + public: + UniversalIterator() {} + + UniversalIterator(IteratorInterface* theOther) + : myPtr(theOther) + { + } + + UniversalIterator(const UniversalIterator& theOther) + : myPtr (theOther.myPtr->Clone()) + { + } + + UniversalIterator& operator= (const UniversalIterator& theOther) + { + myPtr.reset (theOther.myPtr->Clone()); + return *this; + } + + bool operator!= (const UniversalIterator& theOther) const + { + return ! myPtr->IsEqual (*theOther.myPtr); + } + + bool operator== (const UniversalIterator& theOther) const + { + return myPtr->IsEqual (*theOther.myPtr); + } + + UniversalIterator& operator++() + { + myPtr->Increment(); + return *this; + } + + UniversalIterator operator++(int) + { + UniversalIterator aValue(*this); + myPtr->Increment(); + return aValue; + } + + const UniversalIterator& operator* () const { return *this; } + UniversalIterator& operator* () { return *this; } + + const UniversalIterator* operator->() const { return this; } + UniversalIterator* operator->() { return this; } + + // type cast to actual iterator + template + const Iterator& DownCast () const + { + return dynamic_cast*>(myPtr.get())->Value(); + } + + private: +#if (defined(_MSC_VER) && (_MSC_VER < 1600)) + std::auto_ptr myPtr; +#else + std::unique_ptr myPtr; +#endif + }; + + //! Interface class representing functor object. + //! Intended to add polymorphic behavour to For and ForEach functionality + //! enabling execution of arbitrary function in parallel mode. + class FunctorInterface + { + public: + virtual ~FunctorInterface() {} + + virtual void operator () (UniversalIterator& theIterator) const = 0; + }; + +private: + + //! Wrapper for functors manipulating on std iterators. + template + class FunctorWrapperIter : public FunctorInterface + { + public: + FunctorWrapperIter (const Functor& theFunctor) + : myFunctor(theFunctor) + { + } + + virtual void operator() (UniversalIterator& theIterator) const Standard_OVERRIDE + { + const Iterator& anIt = theIterator.DownCast(); + myFunctor(*anIt); + } + + private: + FunctorWrapperIter (const FunctorWrapperIter&); + void operator = (const FunctorWrapperIter&); + const Functor& myFunctor; + }; + + //! Wrapper for functors manipulating on integer index. + template + class FunctorWrapperInt : public FunctorInterface + { + public: + FunctorWrapperInt (const Functor& theFunctor) + : myFunctor(theFunctor) + { + } + + virtual void operator() (UniversalIterator& theIterator) const Standard_OVERRIDE + { + Standard_Integer anIndex = theIterator.DownCast(); + myFunctor(anIndex); + } + + private: + FunctorWrapperInt (const FunctorWrapperInt&); + void operator = (const FunctorWrapperInt&); + const Functor& myFunctor; + }; + +private: //! Simple primitive for parallelization of "foreach" loops, e.g.: //! @code //! for (std::iterator anIter = theBegin; anIter != theEnd; ++anIter) {} //! @endcode + //! Implementation of framework-dependent functionality should be provided by + //! forEach_impl function defined in opencascade::parallel namespace. //! @param theBegin the first index (incusive) //! @param theEnd the last index (exclusive) - //! @param theFunctor functor providing an interface "void operator(InputIterator theIter){}" performing task for specified iterator position - //! @param isForceSingleThreadExecution if true, then no threads will be created - template - static void ForEach( InputIterator theBegin, - InputIterator theEnd, - const Functor& theFunctor, - const Standard_Boolean isForceSingleThreadExecution - = Standard_False ); + //! @param theFunctor functor providing an interface "void operator(InputIterator theIter){}" + //! performing task for the specified iterator position + Standard_EXPORT static void forEach (UniversalIterator& theBegin, + UniversalIterator& theEnd, + const FunctorInterface& theFunctor); - //! Simple primitive for parallelization of "for" loops, e.g.: +public: //! @name public methods + + //! Returns number of logical proccesrs. + Standard_EXPORT static Standard_Integer NbLogicalProcessors(); + + //! Simple primitive for parallelization of "foreach" loops, equivalent to: //! @code - //! for (int anIter = theBegin; anIter < theEnd; ++anIter) {} + //! for (auto anIter = theBegin; anIter != theEnd; ++anIter) { + //! theFunctor(*anIter); + //! } //! @endcode //! @param theBegin the first index (incusive) //! @param theEnd the last index (exclusive) - //! @param theFunctor functor providing an interface "void operator(int theIndex){}" performing task for specified index + //! @param theFunctor functor providing an interface "void operator(InputIterator theIter){}" + //! performing task for specified iterator position + //! @param isForceSingleThreadExecution if true, then no threads will be created + template + static void ForEach(InputIterator theBegin, + InputIterator theEnd, + const Functor& theFunctor, + const Standard_Boolean isForceSingleThreadExecution = Standard_False) + { + if (isForceSingleThreadExecution) + { + for (InputIterator it(theBegin); it != theEnd; ++it) + theFunctor(*it); + } + else + { + UniversalIterator aBegin(new IteratorWrapper(theBegin)); + UniversalIterator aEnd (new IteratorWrapper(theEnd)); + FunctorWrapperIter aFunctor (theFunctor); + forEach(aBegin, aEnd, aFunctor); + } + } + + //! Simple primitive for parallelization of "for" loops, equivalent to: + //! @code + //! for (int anIter = theBegin; anIter != theEnd; ++anIter) { + //! theFunctor(anIter); + //! } + //! @endcode + //! @param theBegin the first index (incusive) + //! @param theEnd the last index (exclusive) + //! @param theFunctor functor providing an interface "void operator(int theIndex){}" + //! performing task for specified index //! @param isForceSingleThreadExecution if true, then no threads will be created template - static void For( const Standard_Integer theBegin, - const Standard_Integer theEnd, - const Functor& theFunctor, - const Standard_Boolean isForceSingleThreadExecution - = Standard_False ); + static void For(const Standard_Integer theBegin, + const Standard_Integer theEnd, + const Functor& theFunctor, + const Standard_Boolean isForceSingleThreadExecution = Standard_False) + { + if (isForceSingleThreadExecution) + { + for (Standard_Integer it (theBegin); it != theEnd; ++it) + theFunctor(it); + } + else + { + UniversalIterator aBegin(new IteratorWrapper(theBegin)); + UniversalIterator aEnd (new IteratorWrapper(theEnd)); + FunctorWrapperInt aFunctor (theFunctor); + forEach(aBegin, aEnd, aFunctor); + } + } + }; -//======================================================================= -//function : OSD_Parallel::Range::It -//purpose : Template concretization. -//======================================================================= -template<> inline Standard_Integer OSD_Parallel::Range::It() const -{ - return Standard_Atomic_Increment( reinterpret_cast(&myIt) ) - 1; -} - -//======================================================================= -//function : ParallelForEach -//purpose : -//======================================================================= -template -void OSD_Parallel::ForEach( InputIterator theBegin, - InputIterator theEnd, - const Functor& theFunctor, - const Standard_Boolean isForceSingleThreadExecution ) -{ - if ( isForceSingleThreadExecution ) - { - for ( InputIterator it(theBegin); it != theEnd; ++it ) - theFunctor(*it); - - return; - } - #ifdef HAVE_TBB - { - try - { - tbb::parallel_for_each(theBegin, theEnd, theFunctor); - } - catch ( tbb::captured_exception& anException ) - { - throw Standard_NotImplemented(anException.what()); - } - } - #else - { - Range aData(theBegin, theEnd); - Task aTask(theFunctor, aData); - - const Standard_Integer aNbThreads = OSD_Parallel::NbLogicalProcessors(); - NCollection_Array1 aThreads(0, aNbThreads - 1); - - for ( Standard_Integer i = 0; i < aNbThreads; ++i ) - { - OSD_Thread& aThread = aThreads(i); - aThread.SetFunction(&Task::RunWithIterator); - aThread.Run(&aTask); - } - - for ( Standard_Integer i = 0; i < aNbThreads; ++i ) - aThreads(i).Wait(); - } - #endif -} - -//======================================================================= -//function : ParallelFor -//purpose : -//======================================================================= -template -void OSD_Parallel::For( const Standard_Integer theBegin, - const Standard_Integer theEnd, - const Functor& theFunctor, - const Standard_Boolean isForceSingleThreadExecution ) -{ - if ( isForceSingleThreadExecution ) - { - for ( Standard_Integer i = theBegin; i < theEnd; ++i ) - theFunctor(i); - - return; - } - #ifdef HAVE_TBB - { - try - { - tbb::parallel_for( theBegin, theEnd, theFunctor ); - } - catch ( tbb::captured_exception& anException ) - { - throw Standard_NotImplemented(anException.what()); - } - } - #else - { - Range aData(theBegin, theEnd); - Task aTask(theFunctor, aData); - - const Standard_Integer aNbThreads = OSD_Parallel::NbLogicalProcessors(); - NCollection_Array1 aThreads(0, aNbThreads - 1); - - for ( Standard_Integer i = 0; i < aNbThreads; ++i ) - { - OSD_Thread& aThread = aThreads(i); - aThread.SetFunction(&Task::RunWithIndex); - aThread.Run(&aTask); - } - - for ( Standard_Integer i = 0; i < aNbThreads; ++i ) - aThreads(i).Wait(); - } - #endif -} - #endif diff --git a/src/OSD/OSD_Parallel_TBB.cxx b/src/OSD/OSD_Parallel_TBB.cxx new file mode 100644 index 0000000000..19992ba26a --- /dev/null +++ b/src/OSD/OSD_Parallel_TBB.cxx @@ -0,0 +1,46 @@ +// Created on: 2014-08-19 +// Created by: Alexander Zaikin +// Copyright (c) 1996-1999 Matra Datavision +// Copyright (c) 2013-2014 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. + +// Version of parallel executor used when TBB is available +#ifdef HAVE_TBB + +#include +#include + +#include +#include +#include + +//======================================================================= +//function : forEach +//purpose : +//======================================================================= + +void OSD_Parallel::forEach (UniversalIterator& theBegin, + UniversalIterator& theEnd, + const FunctorInterface& theFunctor) +{ + try + { + tbb::parallel_for_each(theBegin, theEnd, theFunctor); + } + catch (tbb::captured_exception& anException) + { + throw Standard_ProgramError(anException.what()); + } +} + +#endif /* HAVE_TBB */ \ No newline at end of file diff --git a/src/OSD/OSD_Parallel_Threads.cxx b/src/OSD/OSD_Parallel_Threads.cxx new file mode 100644 index 0000000000..7c5cb47059 --- /dev/null +++ b/src/OSD/OSD_Parallel_Threads.cxx @@ -0,0 +1,151 @@ +// Created on: 2014-08-19 +// Created by: Alexander Zaikin +// Copyright (c) 1996-1999 Matra Datavision +// Copyright (c) 2013-2014 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. + +// Version of parallel executor used when TBB is not available +#ifndef HAVE_TBB + +#include + +#include +#include +#include + +namespace +{ + //! Class implementing tools for parallel processing + //! using threads (when TBB is not available); + //! it is derived from OSD_Parallel to get access to + //! Iterator and FunctorInterface nested types. + class OSD_Parallel_Threads : public OSD_Parallel + { + public: + //! Auxiliary class which ensures exclusive + //! access to iterators of processed data pool. + class Range + { + public: //! @name public methods + + //! Constructor + Range(const OSD_Parallel::UniversalIterator& theBegin, + const OSD_Parallel::UniversalIterator& theEnd) + : myBegin(theBegin), + myEnd(theEnd), + myIt(theBegin) + { + } + + //! Returns const link on the first element. + inline const OSD_Parallel::UniversalIterator& Begin() const + { + return myBegin; + } + + //! Returns const link on the last element. + inline const OSD_Parallel::UniversalIterator& End() const + { + return myEnd; + } + + //! Returns first non processed element or end. + //! Thread-safe method. + inline OSD_Parallel::UniversalIterator It() const + { + Standard_Mutex::Sentry aMutex(myMutex); + return (myIt != myEnd) ? myIt++ : myEnd; + } + + private: //! @name private methods + + //! Empty copy constructor + Range(const Range& theCopy); + + //! Empty copy operator. + Range& operator=(const Range& theCopy); + + private: //! @name private fields + + const OSD_Parallel::UniversalIterator& myBegin; //!< Fisrt element of range. + const OSD_Parallel::UniversalIterator& myEnd; //!< Last element of range. + mutable OSD_Parallel::UniversalIterator myIt; //!< First non processed element of range. + mutable Standard_Mutex myMutex; //!< Access controller for the first non processed element. + }; + + //! Auxiliary wrapper class for thread function. + class Task + { + public: //! @name public methods + + //! Constructor. + Task(const OSD_Parallel::FunctorInterface& thePerformer, Range& theRange) + : myPerformer(thePerformer), + myRange(theRange) + { + } + + //! Method is executed in the context of thread, + //! so this method defines the main calculations. + static Standard_Address Run(Standard_Address theTask) + { + Task& aTask = *(static_cast(theTask)); + + const Range& aData(aTask.myRange); + for (OSD_Parallel::UniversalIterator i = aData.It(); i != aData.End(); i = aData.It()) + aTask.myPerformer(i); + + return NULL; + } + + private: //! @name private methods + + //! Empty copy constructor. + Task(const Task& theCopy); + + //! Empty copy operator. + Task& operator=(const Task& theCopy); + + private: //! @name private fields + + const OSD_Parallel::FunctorInterface& myPerformer; //!< Link on functor. + const Range& myRange; //!< Link on processed data block. + }; + }; +} + +//======================================================================= +//function : forEach +//purpose : +//======================================================================= +void OSD_Parallel::forEach (UniversalIterator& theBegin, + UniversalIterator& theEnd, + const FunctorInterface& theFunctor) +{ + OSD_Parallel_Threads::Range aData(theBegin, theEnd); + OSD_Parallel_Threads::Task aTask(theFunctor, aData); + + const Standard_Integer aNbThreads = OSD_Parallel::NbLogicalProcessors(); + NCollection_Array1 aThreads(0, aNbThreads - 1); + for (Standard_Integer i = 0; i < aNbThreads; ++i) + { + OSD_Thread& aThread = aThreads(i); + aThread.SetFunction(&OSD_Parallel_Threads::Task::Run); + aThread.Run(&aTask); + } + + for (Standard_Integer i = 0; i < aNbThreads; ++i) + aThreads(i).Wait(); +} + +#endif /* ! HAVE_TBB */ \ No newline at end of file diff --git a/src/QABugs/QABugs_19.cxx b/src/QABugs/QABugs_19.cxx index 30a532fdc1..ab17d6ac57 100644 --- a/src/QABugs/QABugs_19.cxx +++ b/src/QABugs/QABugs_19.cxx @@ -54,6 +54,7 @@ #include #include #include +#include #include #include @@ -2864,19 +2865,19 @@ struct OCC25545_Functor //function : OCC25545 //purpose : Tests data race when concurrently accessing TopLoc_Location::Transformation() //======================================================================= -#ifdef HAVE_TBB + static Standard_Integer OCC25545 (Draw_Interpretor& di, Standard_Integer, const char **) { // Place vertices in a vector, giving the i-th vertex the // transformation that translates it on the vector (i,0,0) from the origin. - size_t n = 1000; + Standard_Integer n = 1000; std::vector aShapeVec (n); std::vector aLocVec (n); TopoDS_Shape aShape = BRepBuilderAPI_MakeVertex (gp::Origin ()); aShapeVec[0] = aShape; - for (size_t i = 1; i < n; ++i) { + for (Standard_Integer i = 1; i < n; ++i) { gp_Trsf aT; aT.SetTranslation (gp_Vec (1, 0, 0)); aLocVec[i] = aLocVec[i - 1] * aT; @@ -2887,20 +2888,12 @@ static Standard_Integer OCC25545 (Draw_Interpretor& di, // concurrently OCC25545_Functor aFunc(aShapeVec); - //concurrently process - tbb::parallel_for (size_t (0), n, aFunc, tbb::simple_partitioner ()); + // concurrently process + OSD_Parallel::For (0, n, aFunc); + QVERIFY (!aFunc.myIsRaceDetected); return 0; } -#else -static Standard_Integer OCC25545 (Draw_Interpretor&, - Standard_Integer, - const char **argv) -{ - cout << "Test skipped: command " << argv[0] << " requires TBB library" << endl; - return 0; -} -#endif //======================================================================= //function : OCC25547 diff --git a/src/Select3D/Select3D_SensitivePrimitiveArray.cxx b/src/Select3D/Select3D_SensitivePrimitiveArray.cxx index bc32db0906..a06de722d3 100644 --- a/src/Select3D/Select3D_SensitivePrimitiveArray.cxx +++ b/src/Select3D/Select3D_SensitivePrimitiveArray.cxx @@ -17,6 +17,7 @@ #include #include +#include IMPLEMENT_STANDARD_RTTIEXT(Select3D_SensitivePrimitiveArray, Select3D_SensitiveSet) diff --git a/src/StdPrs/StdPrs_WFShape.cxx b/src/StdPrs/StdPrs_WFShape.cxx index f400871421..ae6f411644 100644 --- a/src/StdPrs/StdPrs_WFShape.cxx +++ b/src/StdPrs/StdPrs_WFShape.cxx @@ -41,6 +41,7 @@ #include #include #include +#include //! Functor for executing StdPrs_Isolines in parallel threads. class StdPrs_WFShape_IsoFunctor