0029935: Foundation Classes - introduce OSD_ThreadPool class defining a thread pool
[occt.git] / src / OSD / OSD_Parallel.hxx
1 // Copyright (c) 2013-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #ifndef OSD_Parallel_HeaderFile
15 #define OSD_Parallel_HeaderFile
16
17 #include <Standard_Type.hxx>
18 #include <memory>
19 #include <type_traits>
20
21 //! @brief Simple tool for code parallelization.
22 //!
23 //! OSD_Parallel class provides simple interface for parallel processing of 
24 //! tasks that can be formulated in terms of "for" or "foreach" loops.
25 //!
26 //! To use this tool it is necessary to:
27 //! - organize the data to be processed in a collection accessible by
28 //!   iteration (usually array or vector);
29 //! - implement a functor class providing operator () accepting iterator
30 //!   (or index in array) that does the job;
31 //! - call either For() or ForEach() providing begin and end iterators and
32 //!   a functor object.
33 //!
34 //! Iterators should satisfy requirements of STL forward iterator.
35 //! Functor 
36 //!
37 //! @code
38 //! class Functor
39 //! {
40 //! public:
41 //!   void operator() ([proccesing instance]) const
42 //!   {
43 //!     //...
44 //!   }
45 //! };
46 //! @endcode
47 //!
48 //! The operator () should be implemented in a thread-safe way so that
49 //! the same functor object can process different data items in parallel threads.
50 //!
51 //! Iteration by index (For) is expected to be more efficient than using iterators
52 //! (ForEach).
53 //!
54 //! Implementation uses TBB if OCCT is built with support of TBB; otherwise it
55 //! uses ad-hoc parallelization tool. In general, if TBB is available, it is
56 //! more efficient to use it directly instead of using OSD_Parallel.
57
58 class OSD_Parallel
59 {
60 private:
61
62   //! Interface class defining API for polymorphic wrappers over iterators.
63   //! Intended to add polymorphic behaviour to For and ForEach functionality
64   //! for arbitrary objects and eliminate dependency on template parameters.
65   class IteratorInterface
66   {
67   public:
68     virtual ~IteratorInterface() {}
69
70     //! Returns true if iterators wrapped by this and theOther are equal
71     virtual bool IsEqual (const IteratorInterface& theOther) const = 0;
72
73     //! Increments wrapped iterator
74     virtual void Increment () = 0;
75
76     //! Returns new instance of the wrapper containing copy
77     //! of the wrapped iterator.
78     virtual IteratorInterface* Clone() const = 0;
79   };
80
81   //! Implementation of polymorphic iterator wrapper suitable for basic 
82   //! types as well as for std iterators.
83   //! Wraps instance of actual iterator type Type.
84   template<class Type>
85   class IteratorWrapper : public IteratorInterface
86   {
87   public:
88     IteratorWrapper() {}
89     IteratorWrapper(const Type& theValue) : myValue(theValue) {}
90
91     virtual bool IsEqual (const IteratorInterface& theOther) const Standard_OVERRIDE
92     {
93       return myValue == dynamic_cast<const IteratorWrapper<Type>&>(theOther).myValue;
94     }
95
96     virtual void Increment () Standard_OVERRIDE
97     {
98       ++myValue;
99     }
100
101     virtual IteratorInterface* Clone() const Standard_OVERRIDE
102     {
103       return new IteratorWrapper<Type>(myValue);
104     }
105
106     const Type& Value() const { return myValue; }
107
108   private:
109     Type myValue;
110   };
111
112 protected:
113   // Note: UniversalIterator and FunctorInterface are made protected to be
114   // accessible from specialization using threads (non-TBB).
115
116   //! Fixed-type iterator, implementing STL forward iterator interface, used for 
117   //! iteration over objects subject to parallel processing.
118   //! It stores pointer to instance of polymorphic iterator inheriting from 
119   //! IteratorInterface, which contains actual type-specific iterator.
120   class UniversalIterator : 
121     // Note that TBB requires that value_type of iterator be copyable, 
122     // thus we use its own type for that
123     public std::iterator<std::forward_iterator_tag, UniversalIterator, ptrdiff_t, UniversalIterator*, UniversalIterator&>
124   {
125   public:
126     UniversalIterator() {}
127
128     UniversalIterator(IteratorInterface* theOther)
129     : myPtr(theOther)
130     {
131     }
132
133     UniversalIterator(const UniversalIterator& theOther)
134     : myPtr (theOther.myPtr->Clone())
135     {
136     }
137
138     UniversalIterator& operator= (const UniversalIterator& theOther)
139     {
140       myPtr.reset (theOther.myPtr->Clone());
141       return *this;
142     }
143
144     bool operator!= (const UniversalIterator& theOther) const
145     {
146       return ! myPtr->IsEqual (*theOther.myPtr);
147     }
148
149     bool operator== (const UniversalIterator& theOther) const
150     {
151       return myPtr->IsEqual (*theOther.myPtr);
152     }
153
154     UniversalIterator& operator++()
155     {
156       myPtr->Increment();
157       return *this;
158     }
159
160     UniversalIterator operator++(int)
161     {
162       UniversalIterator aValue(*this);
163       myPtr->Increment();
164       return aValue;
165     }
166
167     const UniversalIterator& operator* () const { return *this; }
168           UniversalIterator& operator* ()       { return *this; }
169
170     const UniversalIterator* operator->() const { return this; }
171           UniversalIterator* operator->()       { return this; }
172
173     // type cast to actual iterator
174     template <typename Iterator>
175     const Iterator& DownCast () const
176     {
177       return dynamic_cast<OSD_Parallel::IteratorWrapper<Iterator>*>(myPtr.get())->Value();
178     }
179
180   private:
181 #if (defined(_MSC_VER) && (_MSC_VER < 1600))
182     std::auto_ptr<IteratorInterface> myPtr;
183 #else
184     std::unique_ptr<IteratorInterface> myPtr;
185 #endif
186   };
187
188   //! Interface class representing functor object.
189   //! Intended to add polymorphic behavour to For and ForEach functionality 
190   //! enabling execution of arbitrary function in parallel mode.
191   class FunctorInterface
192   {
193   public:
194     virtual ~FunctorInterface() {}
195
196     virtual void operator () (UniversalIterator& theIterator) const = 0;
197   };
198
199 private:
200
201   //! Wrapper for functors manipulating on std iterators.
202   template<class Iterator, class Functor>
203   class FunctorWrapperIter : public FunctorInterface
204   {
205   public:
206     FunctorWrapperIter (const Functor& theFunctor)
207       : myFunctor(theFunctor)
208     {
209     }
210
211     virtual void operator() (UniversalIterator& theIterator) const Standard_OVERRIDE
212     {
213       const Iterator& anIt = theIterator.DownCast<Iterator>();
214       myFunctor(*anIt);
215     }
216
217   private:
218     FunctorWrapperIter (const FunctorWrapperIter&);
219     void operator = (const FunctorWrapperIter&);
220     const Functor& myFunctor;
221   };
222
223   //! Wrapper for functors manipulating on integer index.
224   template<class Functor>
225   class FunctorWrapperInt : public FunctorInterface
226   {
227   public:
228     FunctorWrapperInt (const Functor& theFunctor)
229       : myFunctor(theFunctor)
230     {
231     }
232
233     virtual void operator() (UniversalIterator& theIterator) const Standard_OVERRIDE
234     {
235       Standard_Integer anIndex = theIterator.DownCast<Standard_Integer>();
236       myFunctor(anIndex);
237     }
238
239   private:
240     FunctorWrapperInt (const FunctorWrapperInt&);
241     void operator = (const FunctorWrapperInt&);
242     const Functor& myFunctor;
243   };
244
245 private:
246
247   //! Simple primitive for parallelization of "foreach" loops, e.g.:
248   //! @code
249   //!   for (std::iterator anIter = theBegin; anIter != theEnd; ++anIter) {}
250   //! @endcode
251   //! Implementation of framework-dependent functionality should be provided by
252   //! forEach_impl function defined in opencascade::parallel namespace.
253   //! @param theBegin   the first index (incusive)
254   //! @param theEnd     the last  index (exclusive)
255   //! @param theFunctor functor providing an interface "void operator(InputIterator theIter){}" 
256   //!                   performing task for the specified iterator position
257   //! @param theNbItems number of items passed by iterator, -1 if unknown
258   Standard_EXPORT static void forEach (UniversalIterator& theBegin,
259                                        UniversalIterator& theEnd,
260                                        const FunctorInterface& theFunctor,
261                                        Standard_Integer theNbItems);
262
263 public: //! @name public methods
264
265         //! Returns number of logical proccesrs.
266   Standard_EXPORT static Standard_Integer NbLogicalProcessors();
267
268   //! Simple primitive for parallelization of "foreach" loops, equivalent to:
269   //! @code
270   //!   for (auto anIter = theBegin; anIter != theEnd; ++anIter) {
271   //!     theFunctor(*anIter);
272   //!   }
273   //! @endcode
274   //! @param theBegin   the first index (incusive)
275   //! @param theEnd     the last  index (exclusive)
276   //! @param theFunctor functor providing an interface "void operator(InputIterator theIter){}" 
277   //!                   performing task for specified iterator position
278   //! @param isForceSingleThreadExecution if true, then no threads will be created
279   //! @param theNbItems number of items passed by iterator, -1 if unknown
280   template <typename InputIterator, typename Functor>
281   static void ForEach(InputIterator          theBegin,
282                       InputIterator          theEnd,
283                       const Functor&         theFunctor,
284                       const Standard_Boolean isForceSingleThreadExecution = Standard_False,
285                       Standard_Integer theNbItems = -1)
286   {
287     if (isForceSingleThreadExecution || theNbItems == 1)
288     {
289       for (InputIterator it(theBegin); it != theEnd; ++it)
290         theFunctor(*it);
291     }
292     else
293     {
294       UniversalIterator aBegin(new IteratorWrapper<InputIterator>(theBegin));
295       UniversalIterator aEnd  (new IteratorWrapper<InputIterator>(theEnd));
296       FunctorWrapperIter<InputIterator,Functor> aFunctor (theFunctor);
297       forEach(aBegin, aEnd, aFunctor, theNbItems);
298     }
299   }
300
301   //! Simple primitive for parallelization of "for" loops, equivalent to:
302   //! @code
303   //!   for (int anIter = theBegin; anIter != theEnd; ++anIter) {
304   //!     theFunctor(anIter);
305   //!   }
306   //! @endcode
307   //! @param theBegin   the first index (incusive)
308   //! @param theEnd     the last  index (exclusive)
309   //! @param theFunctor functor providing an interface "void operator(int theIndex){}" 
310   //!                   performing task for specified index
311   //! @param isForceSingleThreadExecution if true, then no threads will be created
312   template <typename Functor>
313   static void For(const Standard_Integer theBegin,
314                   const Standard_Integer theEnd,
315                   const Functor&         theFunctor,
316                   const Standard_Boolean isForceSingleThreadExecution = Standard_False)
317   {
318     if (isForceSingleThreadExecution || (theEnd - theBegin) == 1)
319     {
320       for (Standard_Integer it (theBegin); it != theEnd; ++it)
321         theFunctor(it);
322     }
323     else
324     {
325       UniversalIterator aBegin(new IteratorWrapper<Standard_Integer>(theBegin));
326       UniversalIterator aEnd  (new IteratorWrapper<Standard_Integer>(theEnd));
327       FunctorWrapperInt<Functor> aFunctor (theFunctor);
328       forEach(aBegin, aEnd, aFunctor, theEnd - theBegin);
329     }
330   }
331
332 };
333
334 #endif