1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
// .NAME vtkSMPThreadLocalImpl - A thread local storage implementation using
// platform specific facilities.
#ifndef OpenMPvtkSMPThreadLocalImpl_h
#define OpenMPvtkSMPThreadLocalImpl_h
#include "SMP/Common/vtkSMPThreadLocalImplAbstract.h"
#include "SMP/OpenMP/vtkSMPThreadLocalBackend.h"
#include "SMP/OpenMP/vtkSMPToolsImpl.txx"
#include <iterator>
#include <utility> // For std::move
namespace vtk
{
namespace detail
{
namespace smp
{
VTK_ABI_NAMESPACE_BEGIN
template <typename T>
class vtkSMPThreadLocalImpl<BackendType::OpenMP, T> : public vtkSMPThreadLocalImplAbstract<T>
{
typedef typename vtkSMPThreadLocalImplAbstract<T>::ItImpl ItImplAbstract;
public:
vtkSMPThreadLocalImpl()
: Backend(GetNumberOfThreadsOpenMP())
{
}
explicit vtkSMPThreadLocalImpl(const T& exemplar)
: Backend(GetNumberOfThreadsOpenMP())
, Exemplar(exemplar)
{
}
~vtkSMPThreadLocalImpl() override
{
OpenMP::ThreadSpecificStorageIterator it;
it.SetThreadSpecificStorage(Backend);
for (it.SetToBegin(); !it.GetAtEnd(); it.Forward())
{
delete reinterpret_cast<T*>(it.GetStorage());
}
}
T& Local() override
{
OpenMP::StoragePointerType& ptr = this->Backend.GetStorage();
T* local = reinterpret_cast<T*>(ptr);
if (!ptr)
{
ptr = local = new T(this->Exemplar);
}
return *local;
}
size_t size() const override { return this->Backend.Size(); }
class ItImpl : public vtkSMPThreadLocalImplAbstract<T>::ItImpl
{
public:
void Increment() override { this->Impl.Forward(); }
bool Compare(ItImplAbstract* other) override
{
return this->Impl == static_cast<ItImpl*>(other)->Impl;
}
T& GetContent() override { return *reinterpret_cast<T*>(this->Impl.GetStorage()); }
T* GetContentPtr() override { return reinterpret_cast<T*>(this->Impl.GetStorage()); }
protected:
ItImpl* CloneImpl() const override { return new ItImpl(*this); };
private:
OpenMP::ThreadSpecificStorageIterator Impl;
friend class vtkSMPThreadLocalImpl<BackendType::OpenMP, T>;
};
std::unique_ptr<ItImplAbstract> begin() override
{
auto it = std::make_unique<ItImpl>();
it->Impl.SetThreadSpecificStorage(this->Backend);
it->Impl.SetToBegin();
return it;
}
std::unique_ptr<ItImplAbstract> end() override
{
auto it = std::make_unique<ItImpl>();
it->Impl.SetThreadSpecificStorage(this->Backend);
it->Impl.SetToEnd();
return it;
}
private:
OpenMP::ThreadSpecific Backend;
T Exemplar;
// disable copying
vtkSMPThreadLocalImpl(const vtkSMPThreadLocalImpl&) = delete;
void operator=(const vtkSMPThreadLocalImpl&) = delete;
};
VTK_ABI_NAMESPACE_END
} // namespace smp
} // namespace detail
} // namespace vtk
#endif
/* VTK-HeaderTest-Exclude: vtkSMPThreadLocalImpl.h */
|