VTK  9.3.0
vtkSMPThreadLocalBackend.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
3 
4 // Thread Specific Storage is implemented as a Hash Table, with the Thread Id
5 // as the key and a Pointer to the data as the value. The Hash Table implements
6 // Open Addressing with Linear Probing. A fixed-size array (HashTableArray) is
7 // used as the hash table. The size of this array is allocated to be large
8 // enough to store thread specific data for all the threads with a Load Factor
9 // of 0.5. In case the number of threads changes dynamically and the current
10 // array is not able to accommodate more entries, a new array is allocated that
11 // is twice the size of the current array. To avoid rehashing and blocking the
12 // threads, a rehash is not performed immediately. Instead, a linked list of
13 // hash table arrays is maintained with the current array at the root and older
14 // arrays along the list. All lookups are sequentially performed along the
15 // linked list. If the root array does not have an entry, it is created for
16 // faster lookup next time. The ThreadSpecific::GetStorage() function is thread
17 // safe and only blocks when a new array needs to be allocated, which should be
18 // rare.
19 
20 #ifndef OpenMPvtkSMPThreadLocalBackend_h
21 #define OpenMPvtkSMPThreadLocalBackend_h
22 
23 #include "vtkCommonCoreModule.h" // For export macro
24 #include "vtkSystemIncludes.h"
25 
26 #include <atomic>
27 #include <omp.h>
28 
29 namespace vtk
30 {
31 namespace detail
32 {
33 namespace smp
34 {
35 namespace OpenMP
36 {
37 VTK_ABI_NAMESPACE_BEGIN
38 
39 typedef void* ThreadIdType;
40 typedef vtkTypeUInt32 HashType;
41 typedef void* StoragePointerType;
42 
43 struct Slot
44 {
45  std::atomic<ThreadIdType> ThreadId;
46  omp_lock_t ModifyLock;
48 
49  Slot();
50  ~Slot();
51 
52 private:
53  // not copyable
54  Slot(const Slot&);
55  void operator=(const Slot&);
56 };
57 
59 {
60  size_t Size, SizeLg;
61  std::atomic<size_t> NumberOfEntries;
64 
65  explicit HashTableArray(size_t sizeLg);
67 
68 private:
69  // disallow copying
71  void operator=(const HashTableArray&);
72 };
73 
74 class VTKCOMMONCORE_EXPORT ThreadSpecific final
75 {
76 public:
77  explicit ThreadSpecific(unsigned numThreads);
79 
81  size_t Size() const;
82 
83 private:
84  std::atomic<HashTableArray*> Root;
85  std::atomic<size_t> Count;
86 
88 };
89 
90 inline size_t ThreadSpecific::Size() const
91 {
92  return this->Count;
93 }
94 
96 {
97 public:
99  : ThreadSpecificStorage(nullptr)
100  , CurrentArray(nullptr)
101  , CurrentSlot(0)
102  {
103  }
104 
106  {
107  this->ThreadSpecificStorage = &threadSpecifc;
108  }
109 
110  void SetToBegin()
111  {
112  this->CurrentArray = this->ThreadSpecificStorage->Root;
113  this->CurrentSlot = 0;
114  if (!this->CurrentArray->Slots->Storage)
115  {
116  this->Forward();
117  }
118  }
119 
120  void SetToEnd()
121  {
122  this->CurrentArray = nullptr;
123  this->CurrentSlot = 0;
124  }
125 
126  bool GetInitialized() const { return this->ThreadSpecificStorage != nullptr; }
127 
128  bool GetAtEnd() const { return this->CurrentArray == nullptr; }
129 
130  void Forward()
131  {
132  for (;;)
133  {
134  if (++this->CurrentSlot >= this->CurrentArray->Size)
135  {
136  this->CurrentArray = this->CurrentArray->Prev;
137  this->CurrentSlot = 0;
138  if (!this->CurrentArray)
139  {
140  break;
141  }
142  }
143  Slot* slot = this->CurrentArray->Slots + this->CurrentSlot;
144  if (slot->Storage)
145  {
146  break;
147  }
148  }
149  }
150 
152  {
153  Slot* slot = this->CurrentArray->Slots + this->CurrentSlot;
154  return slot->Storage;
155  }
156 
158  {
159  return (this->ThreadSpecificStorage == it.ThreadSpecificStorage) &&
160  (this->CurrentArray == it.CurrentArray) && (this->CurrentSlot == it.CurrentSlot);
161  }
162 
163 private:
164  ThreadSpecific* ThreadSpecificStorage;
165  HashTableArray* CurrentArray;
166  size_t CurrentSlot;
167 };
168 
169 VTK_ABI_NAMESPACE_END
170 } // OpenMP;
171 } // namespace smp
172 } // namespace detail
173 } // namespace vtk
174 
175 #endif
176 /* VTK-HeaderTest-Exclude: vtkSMPThreadLocalBackend.h */
bool operator==(const ThreadSpecificStorageIterator &it) const
Specialization of tuple ranges and iterators for vtkAOSDataArrayTemplate.
std::atomic< ThreadIdType > ThreadId