/*========================================================================= Program: Visualization Toolkit Module: vtkSMPThreadLocalImpl.h 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. =========================================================================*/ // .NAME vtkSMPThreadLocalImpl - A thread local storage implementation using // platform specific facilities. #ifndef STDThreadvtkSMPThreadLocalImpl_h #define STDThreadvtkSMPThreadLocalImpl_h #include "SMP/Common/vtkSMPThreadLocalImplAbstract.h" #include "SMP/STDThread/vtkSMPThreadLocalBackend.h" #include "SMP/STDThread/vtkSMPToolsImpl.txx" #include #include // For std::move namespace vtk { namespace detail { namespace smp { template class vtkSMPThreadLocalImpl : public vtkSMPThreadLocalImplAbstract { typedef typename vtkSMPThreadLocalImplAbstract::ItImpl ItImplAbstract; public: vtkSMPThreadLocalImpl() : Backend(GetNumberOfThreadsSTDThread()) { } explicit vtkSMPThreadLocalImpl(const T& exemplar) : Backend(GetNumberOfThreadsSTDThread()) , Exemplar(exemplar) { } ~vtkSMPThreadLocalImpl() override { vtk::detail::smp::STDThread::ThreadSpecificStorageIterator it; it.SetThreadSpecificStorage(this->Backend); for (it.SetToBegin(); !it.GetAtEnd(); it.Forward()) { delete reinterpret_cast(it.GetStorage()); } } T& Local() override { vtk::detail::smp::STDThread::StoragePointerType& ptr = this->Backend.GetStorage(); T* local = reinterpret_cast(ptr); if (!ptr) { ptr = local = new T(this->Exemplar); } return *local; } size_t size() const override { return this->Backend.GetSize(); } class ItImpl : public vtkSMPThreadLocalImplAbstract::ItImpl { public: void Increment() override { this->Impl.Forward(); } bool Compare(ItImplAbstract* other) override { return this->Impl == static_cast(other)->Impl; } T& GetContent() override { return *reinterpret_cast(this->Impl.GetStorage()); } T* GetContentPtr() override { return reinterpret_cast(this->Impl.GetStorage()); } protected: virtual ItImpl* CloneImpl() const override { return new ItImpl(*this); }; private: vtk::detail::smp::STDThread::ThreadSpecificStorageIterator Impl; friend class vtkSMPThreadLocalImpl; }; std::unique_ptr begin() override { // XXX(c++14): use std::make_unique auto it = std::unique_ptr(new ItImpl()); it->Impl.SetThreadSpecificStorage(this->Backend); it->Impl.SetToBegin(); // XXX(c++14): remove std::move and cast variable std::unique_ptr abstractIt(std::move(it)); return abstractIt; } std::unique_ptr end() override { // XXX(c++14): use std::make_unique auto it = std::unique_ptr(new ItImpl()); it->Impl.SetThreadSpecificStorage(this->Backend); it->Impl.SetToEnd(); // XXX(c++14): remove std::move and cast variable std::unique_ptr abstractIt(std::move(it)); return abstractIt; } private: vtk::detail::smp::STDThread::ThreadSpecific Backend; T Exemplar; // disable copying vtkSMPThreadLocalImpl(const vtkSMPThreadLocalImpl&) = delete; void operator=(const vtkSMPThreadLocalImpl&) = delete; }; } // namespace smp } // namespace detail } // namespace vtk #endif