1 // Copyright (c) 2013-2014 OPEN CASCADE SAS
3 // This file is part of Open CASCADE Technology software library.
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.
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
14 #ifndef OSD_Parallel_HeaderFile
15 #define OSD_Parallel_HeaderFile
17 #include <Standard_Type.hxx>
19 #include <type_traits>
21 //! @brief Simple tool for code parallelization.
23 //! OSD_Parallel class provides simple interface for parallel processing of
24 //! tasks that can be formulated in terms of "for" or "foreach" loops.
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
34 //! Iterators should satisfy requirements of STL forward iterator.
41 //! void operator() ([proccesing instance]) const
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.
51 //! Iteration by index (For) is expected to be more efficient than using iterators
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.
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
68 virtual ~IteratorInterface() {}
70 //! Returns true if iterators wrapped by this and theOther are equal
71 virtual bool IsEqual (const IteratorInterface& theOther) const = 0;
73 //! Increments wrapped iterator
74 virtual void Increment () = 0;
76 //! Returns new instance of the wrapper containing copy
77 //! of the wrapped iterator.
78 virtual IteratorInterface* Clone() const = 0;
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.
85 class IteratorWrapper : public IteratorInterface
89 IteratorWrapper(const Type& theValue) : myValue(theValue) {}
91 virtual bool IsEqual (const IteratorInterface& theOther) const Standard_OVERRIDE
93 return myValue == dynamic_cast<const IteratorWrapper<Type>&>(theOther).myValue;
96 virtual void Increment () Standard_OVERRIDE
101 virtual IteratorInterface* Clone() const Standard_OVERRIDE
103 return new IteratorWrapper<Type>(myValue);
106 const Type& Value() const { return myValue; }
113 // Note: UniversalIterator and FunctorInterface are made protected to be
114 // accessible from specialization using threads (non-TBB).
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&>
126 UniversalIterator() {}
128 UniversalIterator(IteratorInterface* theOther)
133 UniversalIterator(const UniversalIterator& theOther)
134 : myPtr (theOther.myPtr->Clone())
138 UniversalIterator& operator= (const UniversalIterator& theOther)
140 myPtr.reset (theOther.myPtr->Clone());
144 bool operator!= (const UniversalIterator& theOther) const
146 return ! myPtr->IsEqual (*theOther.myPtr);
149 bool operator== (const UniversalIterator& theOther) const
151 return myPtr->IsEqual (*theOther.myPtr);
154 UniversalIterator& operator++()
160 UniversalIterator operator++(int)
162 UniversalIterator aValue(*this);
167 const UniversalIterator& operator* () const { return *this; }
168 UniversalIterator& operator* () { return *this; }
170 const UniversalIterator* operator->() const { return this; }
171 UniversalIterator* operator->() { return this; }
173 // type cast to actual iterator
174 template <typename Iterator>
175 const Iterator& DownCast () const
177 return dynamic_cast<OSD_Parallel::IteratorWrapper<Iterator>*>(myPtr.get())->Value();
181 #if (defined(_MSC_VER) && (_MSC_VER < 1600))
182 std::auto_ptr<IteratorInterface> myPtr;
184 std::unique_ptr<IteratorInterface> myPtr;
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
194 virtual ~FunctorInterface() {}
196 virtual void operator () (UniversalIterator& theIterator) const = 0;
201 //! Wrapper for functors manipulating on std iterators.
202 template<class Iterator, class Functor>
203 class FunctorWrapperIter : public FunctorInterface
206 FunctorWrapperIter (const Functor& theFunctor)
207 : myFunctor(theFunctor)
211 virtual void operator() (UniversalIterator& theIterator) const Standard_OVERRIDE
213 const Iterator& anIt = theIterator.DownCast<Iterator>();
218 FunctorWrapperIter (const FunctorWrapperIter&);
219 void operator = (const FunctorWrapperIter&);
220 const Functor& myFunctor;
223 //! Wrapper for functors manipulating on integer index.
224 template<class Functor>
225 class FunctorWrapperInt : public FunctorInterface
228 FunctorWrapperInt (const Functor& theFunctor)
229 : myFunctor(theFunctor)
233 virtual void operator() (UniversalIterator& theIterator) const Standard_OVERRIDE
235 Standard_Integer anIndex = theIterator.DownCast<Standard_Integer>();
240 FunctorWrapperInt (const FunctorWrapperInt&);
241 void operator = (const FunctorWrapperInt&);
242 const Functor& myFunctor;
247 //! Simple primitive for parallelization of "foreach" loops, e.g.:
249 //! for (std::iterator anIter = theBegin; anIter != theEnd; ++anIter) {}
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 Standard_EXPORT static void forEach (UniversalIterator& theBegin,
258 UniversalIterator& theEnd,
259 const FunctorInterface& theFunctor);
261 public: //! @name public methods
263 //! Returns number of logical proccesrs.
264 Standard_EXPORT static Standard_Integer NbLogicalProcessors();
266 //! Simple primitive for parallelization of "foreach" loops, equivalent to:
268 //! for (auto anIter = theBegin; anIter != theEnd; ++anIter) {
269 //! theFunctor(*anIter);
272 //! @param theBegin the first index (incusive)
273 //! @param theEnd the last index (exclusive)
274 //! @param theFunctor functor providing an interface "void operator(InputIterator theIter){}"
275 //! performing task for specified iterator position
276 //! @param isForceSingleThreadExecution if true, then no threads will be created
277 template <typename InputIterator, typename Functor>
278 static void ForEach(InputIterator theBegin,
279 InputIterator theEnd,
280 const Functor& theFunctor,
281 const Standard_Boolean isForceSingleThreadExecution = Standard_False)
283 if (isForceSingleThreadExecution)
285 for (InputIterator it(theBegin); it != theEnd; ++it)
290 UniversalIterator aBegin(new IteratorWrapper<InputIterator>(theBegin));
291 UniversalIterator aEnd (new IteratorWrapper<InputIterator>(theEnd));
292 FunctorWrapperIter<InputIterator,Functor> aFunctor (theFunctor);
293 forEach(aBegin, aEnd, aFunctor);
297 //! Simple primitive for parallelization of "for" loops, equivalent to:
299 //! for (int anIter = theBegin; anIter != theEnd; ++anIter) {
300 //! theFunctor(anIter);
303 //! @param theBegin the first index (incusive)
304 //! @param theEnd the last index (exclusive)
305 //! @param theFunctor functor providing an interface "void operator(int theIndex){}"
306 //! performing task for specified index
307 //! @param isForceSingleThreadExecution if true, then no threads will be created
308 template <typename Functor>
309 static void For(const Standard_Integer theBegin,
310 const Standard_Integer theEnd,
311 const Functor& theFunctor,
312 const Standard_Boolean isForceSingleThreadExecution = Standard_False)
314 if (isForceSingleThreadExecution)
316 for (Standard_Integer it (theBegin); it != theEnd; ++it)
321 UniversalIterator aBegin(new IteratorWrapper<Standard_Integer>(theBegin));
322 UniversalIterator aEnd (new IteratorWrapper<Standard_Integer>(theEnd));
323 FunctorWrapperInt<Functor> aFunctor (theFunctor);
324 forEach(aBegin, aEnd, aFunctor);