0030618: Modeling Algorithms, BOPTools_Parallel - avoid using map for thread-local...
[occt.git] / src / OSD / OSD_Parallel_Threads.cxx
CommitLineData
00af0ebb 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
5//
6// This file is part of Open CASCADE Technology software library.
7//
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.
13//
14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
16
00af0ebb 17#include <OSD_Parallel.hxx>
18
6f498847 19#include <OSD_ThreadPool.hxx>
20
00af0ebb 21#include <NCollection_Array1.hxx>
22#include <Standard_Mutex.hxx>
23#include <OSD_Thread.hxx>
24
25namespace
26{
27 //! Class implementing tools for parallel processing
28 //! using threads (when TBB is not available);
29 //! it is derived from OSD_Parallel to get access to
30 //! Iterator and FunctorInterface nested types.
6f498847 31 class OSD_Parallel_Threads : public OSD_ThreadPool, public OSD_Parallel
00af0ebb 32 {
33 public:
34 //! Auxiliary class which ensures exclusive
35 //! access to iterators of processed data pool.
36 class Range
37 {
38 public: //! @name public methods
39
40 //! Constructor
41 Range(const OSD_Parallel::UniversalIterator& theBegin,
42 const OSD_Parallel::UniversalIterator& theEnd)
43 : myBegin(theBegin),
44 myEnd(theEnd),
45 myIt(theBegin)
46 {
47 }
48
49 //! Returns const link on the first element.
50 inline const OSD_Parallel::UniversalIterator& Begin() const
51 {
52 return myBegin;
53 }
54
55 //! Returns const link on the last element.
56 inline const OSD_Parallel::UniversalIterator& End() const
57 {
58 return myEnd;
59 }
60
61 //! Returns first non processed element or end.
62 //! Thread-safe method.
63 inline OSD_Parallel::UniversalIterator It() const
64 {
65 Standard_Mutex::Sentry aMutex(myMutex);
66 return (myIt != myEnd) ? myIt++ : myEnd;
67 }
68
69 private: //! @name private methods
70
71 //! Empty copy constructor
72 Range(const Range& theCopy);
73
74 //! Empty copy operator.
75 Range& operator=(const Range& theCopy);
76
77 private: //! @name private fields
78
79 const OSD_Parallel::UniversalIterator& myBegin; //!< Fisrt element of range.
80 const OSD_Parallel::UniversalIterator& myEnd; //!< Last element of range.
81 mutable OSD_Parallel::UniversalIterator myIt; //!< First non processed element of range.
82 mutable Standard_Mutex myMutex; //!< Access controller for the first non processed element.
83 };
84
85 //! Auxiliary wrapper class for thread function.
6f498847 86 class Task : public JobInterface
00af0ebb 87 {
88 public: //! @name public methods
89
90 //! Constructor.
91 Task(const OSD_Parallel::FunctorInterface& thePerformer, Range& theRange)
92 : myPerformer(thePerformer),
93 myRange(theRange)
94 {
95 }
96
97 //! Method is executed in the context of thread,
98 //! so this method defines the main calculations.
6f498847 99 virtual void Perform (int ) Standard_OVERRIDE
00af0ebb 100 {
6f498847 101 for (OSD_Parallel::UniversalIterator anIter = myRange.It(); anIter != myRange.End(); anIter = myRange.It())
102 {
103 myPerformer (anIter);
104 }
00af0ebb 105 }
106
107 private: //! @name private methods
108
109 //! Empty copy constructor.
110 Task(const Task& theCopy);
111
112 //! Empty copy operator.
113 Task& operator=(const Task& theCopy);
114
115 private: //! @name private fields
6f498847 116 const FunctorInterface& myPerformer; //!< Link on functor
117 const Range& myRange; //!< Link on processed data block
118 };
119
120 //! Launcher specialization.
121 class UniversalLauncher : public Launcher
122 {
123 public:
124 //! Constructor.
125 UniversalLauncher (OSD_ThreadPool& thePool, int theMaxThreads = -1)
126 : Launcher (thePool, theMaxThreads) {}
00af0ebb 127
6f498847 128 //! Primitive for parallelization of "for" loops.
129 void Perform (OSD_Parallel::UniversalIterator& theBegin,
130 OSD_Parallel::UniversalIterator& theEnd,
131 const OSD_Parallel::FunctorInterface& theFunctor)
132 {
133 Range aData (theBegin, theEnd);
134 Task aJob (theFunctor, aData);
135 perform (aJob);
136 }
00af0ebb 137 };
138 };
139}
140
141//=======================================================================
fc867b96 142//function : forEachOcct
143//purpose :
00af0ebb 144//=======================================================================
fc867b96 145void OSD_Parallel::forEachOcct (UniversalIterator& theBegin,
146 UniversalIterator& theEnd,
147 const FunctorInterface& theFunctor,
148 Standard_Integer theNbItems)
00af0ebb 149{
6f498847 150 const Handle(OSD_ThreadPool)& aThreadPool = OSD_ThreadPool::DefaultPool();
151 const Standard_Integer aNbThreads = theNbItems != -1 ? Min (theNbItems, aThreadPool->NbDefaultThreadsToLaunch()) : -1;
152 OSD_Parallel_Threads::UniversalLauncher aLauncher (*aThreadPool, aNbThreads);
153 aLauncher.Perform (theBegin, theEnd, theFunctor);
00af0ebb 154}
155
fc867b96 156// Version of parallel executor used when TBB is not available
157#ifndef HAVE_TBB
158//=======================================================================
159//function : forEachExternal
160//purpose :
161//=======================================================================
162void OSD_Parallel::forEachExternal (UniversalIterator& theBegin,
163 UniversalIterator& theEnd,
164 const FunctorInterface& theFunctor,
165 Standard_Integer theNbItems)
166{
167 forEachOcct (theBegin, theEnd, theFunctor, theNbItems);
168}
169
6f498847 170#endif /* ! HAVE_TBB */