Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-25 09:19:06

0001 // Created by: Peter KURNEV
0002 // Copyright (c) 1999-2013 OPEN CASCADE SAS
0003 //
0004 // This file is part of Open CASCADE Technology software library.
0005 //
0006 // This library is free software; you can redistribute it and/or modify it under
0007 // the terms of the GNU Lesser General Public License version 2.1 as published
0008 // by the Free Software Foundation, with special exception defined in the file
0009 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0010 // distribution for complete text of the license and disclaimer of any warranty.
0011 //
0012 // Alternatively, this file may be used under the terms of Open CASCADE
0013 // commercial license or contractual agreement.
0014 
0015 #ifndef _BOPTools_Parallel_HeaderFile
0016 #define _BOPTools_Parallel_HeaderFile
0017 
0018 #include <OSD_Parallel.hxx>
0019 #include <OSD_ThreadPool.hxx>
0020 #include <NCollection_DataMap.hxx>
0021 #include <OSD_Thread.hxx>
0022 
0023 #include <mutex>
0024 
0025 //! Implementation of Functors/Starters
0026 class BOPTools_Parallel
0027 {
0028   template <class TypeSolverVector>
0029   class Functor
0030   {
0031   public:
0032     //! Constructor.
0033     explicit Functor(TypeSolverVector& theSolverVec)
0034         : mySolvers(theSolverVec)
0035     {
0036     }
0037 
0038     //! Defines functor interface.
0039     void operator()(const int theIndex) const
0040     {
0041       typename TypeSolverVector::value_type& aSolver = mySolvers[theIndex];
0042       aSolver.Perform();
0043     }
0044 
0045   private:
0046     Functor(const Functor&)            = delete;
0047     Functor& operator=(const Functor&) = delete;
0048 
0049   private:
0050     TypeSolverVector& mySolvers;
0051   };
0052 
0053   //! Functor storing map of thread id -> algorithm context
0054   template <class TypeSolverVector, class TypeContext>
0055   class ContextFunctor
0056   {
0057   public:
0058     //! Constructor
0059     explicit ContextFunctor(TypeSolverVector& theVector)
0060         : mySolverVector(theVector)
0061     {
0062     }
0063 
0064     //! Binds main thread context
0065     void SetContext(const opencascade::handle<TypeContext>& theContext)
0066     {
0067       myContextMap.Bind(OSD_Thread::Current(), theContext);
0068     }
0069 
0070     //! Returns current thread context
0071     const opencascade::handle<TypeContext>& GetThreadContext() const
0072     {
0073       const Standard_ThreadId aThreadID = OSD_Thread::Current();
0074       if (const opencascade::handle<TypeContext>* aContextPtr = myContextMap.Seek(aThreadID))
0075       {
0076         if (!aContextPtr->IsNull())
0077         {
0078           return *aContextPtr;
0079         }
0080       }
0081 
0082       // Create new context
0083       opencascade::handle<TypeContext> aContext =
0084         new TypeContext(NCollection_BaseAllocator::CommonBaseAllocator());
0085 
0086       std::lock_guard<std::mutex> aLock(myMutex);
0087       myContextMap.Bind(aThreadID, aContext);
0088       return myContextMap(aThreadID);
0089     }
0090 
0091     //! Defines functor interface
0092     void operator()(const int theIndex) const
0093     {
0094       const opencascade::handle<TypeContext>& aContext = GetThreadContext();
0095       typename TypeSolverVector::value_type&  aSolver  = mySolverVector[theIndex];
0096 
0097       aSolver.SetContext(aContext);
0098       aSolver.Perform();
0099     }
0100 
0101   private:
0102     ContextFunctor(const ContextFunctor&)            = delete;
0103     ContextFunctor& operator=(const ContextFunctor&) = delete;
0104 
0105   private:
0106     TypeSolverVector&                                                                mySolverVector;
0107     mutable NCollection_DataMap<Standard_ThreadId, opencascade::handle<TypeContext>> myContextMap;
0108     mutable std::mutex                                                               myMutex;
0109   };
0110 
0111   //! Functor storing array of algorithm contexts per thread in pool
0112   template <class TypeSolverVector, class TypeContext>
0113   class ContextFunctor2
0114   {
0115   public:
0116     //! Constructor
0117     explicit ContextFunctor2(TypeSolverVector&               theVector,
0118                              const OSD_ThreadPool::Launcher& thePoolLauncher)
0119         : mySolverVector(theVector),
0120           myContextArray(thePoolLauncher.LowerThreadIndex(), thePoolLauncher.UpperThreadIndex())
0121     {
0122     }
0123 
0124     //! Binds main thread context
0125     void SetContext(const opencascade::handle<TypeContext>& theContext)
0126     {
0127       // clang-format off
0128       myContextArray.ChangeLast() = theContext; // OSD_ThreadPool::Launcher::UpperThreadIndex() is reserved for a main thread
0129       // clang-format on
0130     }
0131 
0132     //! Defines functor interface with serialized thread index.
0133     void operator()(int theThreadIndex, int theIndex) const
0134     {
0135       opencascade::handle<TypeContext>& aContext = myContextArray.ChangeValue(theThreadIndex);
0136       if (aContext.IsNull())
0137       {
0138         aContext = new TypeContext(NCollection_BaseAllocator::CommonBaseAllocator());
0139       }
0140       typename TypeSolverVector::value_type& aSolver = mySolverVector[theIndex];
0141       aSolver.SetContext(aContext);
0142       aSolver.Perform();
0143     }
0144 
0145   private:
0146     ContextFunctor2(const ContextFunctor2&)            = delete;
0147     ContextFunctor2& operator=(const ContextFunctor2&) = delete;
0148 
0149   private:
0150     TypeSolverVector&                                            mySolverVector;
0151     mutable NCollection_Array1<opencascade::handle<TypeContext>> myContextArray;
0152   };
0153 
0154 public:
0155   //! Pure version
0156   template <class TypeSolverVector>
0157   static void Perform(bool theIsRunParallel, TypeSolverVector& theSolverVector)
0158   {
0159     Functor<TypeSolverVector> aFunctor(theSolverVector);
0160     OSD_Parallel::For(0, theSolverVector.Length(), aFunctor, !theIsRunParallel);
0161   }
0162 
0163   //! Context dependent version
0164   template <class TypeSolverVector, class TypeContext>
0165   static void Perform(bool                              theIsRunParallel,
0166                       TypeSolverVector&                 theSolverVector,
0167                       opencascade::handle<TypeContext>& theContext)
0168   {
0169     if (OSD_Parallel::ToUseOcctThreads())
0170     {
0171       const occ::handle<OSD_ThreadPool>&             aThreadPool = OSD_ThreadPool::DefaultPool();
0172       OSD_ThreadPool::Launcher                       aPoolLauncher(*aThreadPool,
0173                                              theIsRunParallel ? theSolverVector.Length() : 0);
0174       ContextFunctor2<TypeSolverVector, TypeContext> aFunctor(theSolverVector, aPoolLauncher);
0175       aFunctor.SetContext(theContext);
0176       aPoolLauncher.Perform(0, theSolverVector.Length(), aFunctor);
0177     }
0178     else
0179     {
0180       ContextFunctor<TypeSolverVector, TypeContext> aFunctor(theSolverVector);
0181       aFunctor.SetContext(theContext);
0182       OSD_Parallel::For(0, theSolverVector.Length(), aFunctor, !theIsRunParallel);
0183     }
0184   }
0185 };
0186 
0187 #endif