1 // Created on: 2014-08-19
2 // Created by: Alexander Zaikin
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 2013-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Version of parallel executor used when TBB is not available
20 #include <OSD_Parallel.hxx>
22 #include <OSD_ThreadPool.hxx>
24 #include <NCollection_Array1.hxx>
25 #include <Standard_Mutex.hxx>
26 #include <OSD_Thread.hxx>
30 //! Class implementing tools for parallel processing
31 //! using threads (when TBB is not available);
32 //! it is derived from OSD_Parallel to get access to
33 //! Iterator and FunctorInterface nested types.
34 class OSD_Parallel_Threads : public OSD_ThreadPool, public OSD_Parallel
37 //! Auxiliary class which ensures exclusive
38 //! access to iterators of processed data pool.
41 public: //! @name public methods
44 Range(const OSD_Parallel::UniversalIterator& theBegin,
45 const OSD_Parallel::UniversalIterator& theEnd)
52 //! Returns const link on the first element.
53 inline const OSD_Parallel::UniversalIterator& Begin() const
58 //! Returns const link on the last element.
59 inline const OSD_Parallel::UniversalIterator& End() const
64 //! Returns first non processed element or end.
65 //! Thread-safe method.
66 inline OSD_Parallel::UniversalIterator It() const
68 Standard_Mutex::Sentry aMutex(myMutex);
69 return (myIt != myEnd) ? myIt++ : myEnd;
72 private: //! @name private methods
74 //! Empty copy constructor
75 Range(const Range& theCopy);
77 //! Empty copy operator.
78 Range& operator=(const Range& theCopy);
80 private: //! @name private fields
82 const OSD_Parallel::UniversalIterator& myBegin; //!< Fisrt element of range.
83 const OSD_Parallel::UniversalIterator& myEnd; //!< Last element of range.
84 mutable OSD_Parallel::UniversalIterator myIt; //!< First non processed element of range.
85 mutable Standard_Mutex myMutex; //!< Access controller for the first non processed element.
88 //! Auxiliary wrapper class for thread function.
89 class Task : public JobInterface
91 public: //! @name public methods
94 Task(const OSD_Parallel::FunctorInterface& thePerformer, Range& theRange)
95 : myPerformer(thePerformer),
100 //! Method is executed in the context of thread,
101 //! so this method defines the main calculations.
102 virtual void Perform (int ) Standard_OVERRIDE
104 for (OSD_Parallel::UniversalIterator anIter = myRange.It(); anIter != myRange.End(); anIter = myRange.It())
106 myPerformer (anIter);
110 private: //! @name private methods
112 //! Empty copy constructor.
113 Task(const Task& theCopy);
115 //! Empty copy operator.
116 Task& operator=(const Task& theCopy);
118 private: //! @name private fields
119 const FunctorInterface& myPerformer; //!< Link on functor
120 const Range& myRange; //!< Link on processed data block
123 //! Launcher specialization.
124 class UniversalLauncher : public Launcher
128 UniversalLauncher (OSD_ThreadPool& thePool, int theMaxThreads = -1)
129 : Launcher (thePool, theMaxThreads) {}
131 //! Primitive for parallelization of "for" loops.
132 void Perform (OSD_Parallel::UniversalIterator& theBegin,
133 OSD_Parallel::UniversalIterator& theEnd,
134 const OSD_Parallel::FunctorInterface& theFunctor)
136 Range aData (theBegin, theEnd);
137 Task aJob (theFunctor, aData);
144 //=======================================================================
147 //=======================================================================
148 void OSD_Parallel::forEach (UniversalIterator& theBegin,
149 UniversalIterator& theEnd,
150 const FunctorInterface& theFunctor,
151 Standard_Integer theNbItems)
153 const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool();
154 const Standard_Integer aNbThreads = theNbItems != -1 ? Min (theNbItems, aThreadPool->NbDefaultThreadsToLaunch()) : -1;
155 OSD_Parallel_Threads::UniversalLauncher aLauncher (*aThreadPool, aNbThreads);
156 aLauncher.Perform (theBegin, theEnd, theFunctor);
159 #endif /* ! HAVE_TBB */