/*========================================================================= Program: Visualization Toolkit Module: vtkSMPToolsImpl.txx Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #ifndef STDThreadvtkSMPToolsImpl_txx #define STDThreadvtkSMPToolsImpl_txx #include // For std::sort #include // For std::bind #include "SMP/Common/vtkSMPToolsImpl.h" #include "SMP/Common/vtkSMPToolsInternal.h" // For common vtk smp class #include "SMP/STDThread/vtkSMPThreadPool.h" // For vtkSMPThreadPool #include "vtkCommonCoreModule.h" // For export macro namespace vtk { namespace detail { namespace smp { int VTKCOMMONCORE_EXPORT GetNumberOfThreadsSTDThread(); //-------------------------------------------------------------------------------- template void ExecuteFunctorSTDThread(void* functor, vtkIdType from, vtkIdType grain, vtkIdType last) { const vtkIdType to = std::min(from + grain, last); FunctorInternal& fi = *reinterpret_cast(functor); fi.Execute(from, to); } //-------------------------------------------------------------------------------- template <> template void vtkSMPToolsImpl::For( vtkIdType first, vtkIdType last, vtkIdType grain, FunctorInternal& fi) { vtkIdType n = last - first; if (n <= 0) { return; } if (grain >= n || (!this->NestedActivated && this->IsParallel)) { fi.Execute(first, last); } else { int threadNumber = GetNumberOfThreadsSTDThread(); if (grain <= 0) { vtkIdType estimateGrain = (last - first) / (threadNumber * 4); grain = (estimateGrain > 0) ? estimateGrain : 1; } // /!\ This behaviour should be changed if we want more control on nested // (e.g only the 2 first nested For are in parallel) bool fromParallelCode = this->IsParallel.exchange(true); vtkSMPThreadPool pool(threadNumber); for (vtkIdType from = first; from < last; from += grain) { auto job = std::bind(ExecuteFunctorSTDThread, &fi, from, grain, last); pool.DoJob(job); } pool.Join(); // Atomic contortion to achieve this->IsParallel &= fromParallelCode. // This compare&exchange basically boils down to: // if (IsParallel == trueFlag) // IsParallel = fromParallelCode; // else // trueFlag = IsParallel; // Which either leaves IsParallel as false or sets it to fromParallelCode (i.e. &=). // Note that the return value of compare_exchange_weak() is not needed, // and that no looping is necessary. bool trueFlag = true; this->IsParallel.compare_exchange_weak(trueFlag, fromParallelCode); } } //-------------------------------------------------------------------------------- template <> template void vtkSMPToolsImpl::Transform( InputIt inBegin, InputIt inEnd, OutputIt outBegin, Functor transform) { auto size = std::distance(inBegin, inEnd); UnaryTransformCall exec(inBegin, outBegin, transform); this->For(0, size, 0, exec); } //-------------------------------------------------------------------------------- template <> template void vtkSMPToolsImpl::Transform( InputIt1 inBegin1, InputIt1 inEnd, InputIt2 inBegin2, OutputIt outBegin, Functor transform) { auto size = std::distance(inBegin1, inEnd); BinaryTransformCall exec( inBegin1, inBegin2, outBegin, transform); this->For(0, size, 0, exec); } //-------------------------------------------------------------------------------- template <> template void vtkSMPToolsImpl::Fill(Iterator begin, Iterator end, const T& value) { auto size = std::distance(begin, end); FillFunctor fill(value); UnaryTransformCall> exec(begin, begin, fill); this->For(0, size, 0, exec); } //-------------------------------------------------------------------------------- template <> template void vtkSMPToolsImpl::Sort( RandomAccessIterator begin, RandomAccessIterator end) { std::sort(begin, end); } //-------------------------------------------------------------------------------- template <> template void vtkSMPToolsImpl::Sort( RandomAccessIterator begin, RandomAccessIterator end, Compare comp) { std::sort(begin, end, comp); } //-------------------------------------------------------------------------------- template <> void vtkSMPToolsImpl::Initialize(int); //-------------------------------------------------------------------------------- template <> int vtkSMPToolsImpl::GetEstimatedNumberOfThreads(); } // namespace smp } // namespace detail } // namespace vtk #endif