11 #ifndef vtk_m_cont_BitField_h
12 #define vtk_m_cont_BitField_h
15 #include <vtkm/cont/vtkm_cont_export.h>
24 #include <type_traits>
36 struct StorageTagBitField;
54 constexpr
static vtkm::Id BlockSize = VTKM_ALLOCATION_ALIGNMENT;
61 template <
typename WordType>
62 using IsValidWordType =
63 std::integral_constant<bool,
65 std::is_unsigned<WordType>::value &&
67 sizeof(WordType) <=
static_cast<size_t>(BlockSize) &&
69 static_cast<size_t>(BlockSize) %
sizeof(WordType) == 0>;
73 template <
typename WordType>
74 using IsValidWordTypeAtomic =
75 std::integral_constant<bool,
77 std::is_unsigned<WordType>::value &&
79 sizeof(WordType) <=
static_cast<size_t>(BlockSize) &&
81 static_cast<size_t>(BlockSize) %
sizeof(WordType) == 0 &&
100 template <
bool IsConst>
105 template <
typename PortalType,
106 typename PointerType = decltype(std::declval<PortalType>().GetIteratorBegin())>
107 struct HasPointerAccess :
public std::is_pointer<PointerType>
112 template <
typename T>
113 using MaybeConstPointer =
typename std::conditional<IsConst, T const*, T*>::type;
114 using BufferType = MaybeConstPointer<void>;
121 template <
typename WordType>
122 using IsValidWordType = BitFieldTraits::IsValidWordType<WordType>;
125 template <
typename WordType>
126 using IsValidWordTypeAtomic = BitFieldTraits::IsValidWordTypeAtomic<WordType>;
129 "Internal error: Default word type is invalid.");
131 "Device-specific fast word type is invalid.");
134 "Internal error: Default word type is invalid.");
136 "Device-specific fast word type is invalid for atomic operations.");
140 friend class vtkm::cont::internal::Storage<bool,
vtkm::cont::internal::StorageTagBitField>;
143 VTKM_CONT BitPortalBase(BufferType rawArray, vtkm::Id numberOfBits)
145 , NumberOfBits{ numberOfBits }
150 BitPortalBase() noexcept = default;
151 BitPortalBase(const BitPortalBase&) noexcept = default;
152 BitPortalBase(BitPortalBase&&) noexcept = default;
153 BitPortalBase& operator=(const BitPortalBase&) noexcept = default;
154 BitPortalBase& operator=(BitPortalBase&&) noexcept = default;
158 vtkm::
Id GetNumberOfBits() const noexcept {
return this->NumberOfBits; }
163 template <
typename WordType = WordTypePreferred>
167 static constexpr
vtkm::Id WordSize =
static_cast<vtkm::Id>(
sizeof(WordType));
168 static constexpr
vtkm::Id WordBits = WordSize * CHAR_BIT;
169 return (this->NumberOfBits + WordBits - 1) / WordBits;
174 template <
typename WordType = WordTypePreferred>
177 if (this->NumberOfBits == 0)
179 return WordType{ 0 };
183 static_cast<vtkm::Int32>(
sizeof(WordType) * CHAR_BIT);
185 const auto maxBit = this->NumberOfBits - 1;
186 const auto coord = this->GetBitCoordinateFromIndex<WordType>(maxBit);
187 const vtkm::Int32 shift = BitsPerWord - coord.BitOffset - 1;
188 return (~WordType{ 0 }) >> shift;
193 template <
typename WordType = WordTypePreferred>
197 static constexpr
vtkm::Id BitsPerWord =
static_cast<vtkm::Id>(
sizeof(WordType) * CHAR_BIT);
198 return {
static_cast<vtkm::Id>(bitIdx / BitsPerWord),
207 void SetBit(
vtkm::Id bitIdx,
bool val)
const noexcept
210 using WordType = WordTypePreferred;
211 const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
212 const auto mask = WordType(1) << coord.BitOffset;
213 WordType* wordAddr = this->GetWordAddress<WordType>(coord.WordIndex);
227 void SetBitAtomic(
vtkm::Id bitIdx,
bool val)
const
230 using WordType = WordTypePreferred;
231 const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
232 const auto mask = WordType(1) << coord.BitOffset;
235 this->OrWordAtomic(coord.WordIndex, mask);
239 this->AndWordAtomic(coord.WordIndex, ~mask);
246 bool GetBit(
vtkm::Id bitIdx)
const noexcept
248 using WordType = WordTypePreferred;
249 const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
250 const auto word = this->GetWord<WordType>(coord.WordIndex);
251 const auto mask = WordType(1) << coord.BitOffset;
252 return (word & mask) != WordType(0);
259 bool GetBitAtomic(
vtkm::Id bitIdx)
const
261 using WordType = WordTypePreferred;
262 const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
263 const auto word = this->GetWordAtomic<WordType>(coord.WordIndex);
264 const auto mask = WordType(1) << coord.BitOffset;
265 return (word & mask) != WordType(0);
270 template <
typename WordType = WordTypePreferred>
274 *this->GetWordAddress<WordType>(wordIdx) = word;
279 template <
typename WordType = WordTypePreferred>
284 "Requested WordType does not support atomic"
285 " operations on target execution platform.");
291 template <
typename WordType = WordTypePreferred>
294 return *this->GetWordAddress<WordType>(wordIdx);
299 template <
typename WordType = WordTypePreferred>
303 "Requested WordType does not support atomic"
304 " operations on target execution platform.");
311 bool NotBitAtomic(
vtkm::Id bitIdx)
const
314 using WordType = WordTypePreferred;
315 const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
316 const auto mask = WordType(1) << coord.BitOffset;
317 const auto oldWord = this->XorWordAtomic(coord.WordIndex, mask);
318 return (oldWord & mask) != WordType(0);
323 template <
typename WordType = WordTypePreferred>
328 "Requested WordType does not support atomic"
329 " operations on target execution platform.");
330 WordType* addr = this->GetWordAddress<WordType>(wordIdx);
338 bool AndBitAtomic(
vtkm::Id bitIdx,
bool val)
const
341 using WordType = WordTypePreferred;
342 const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
343 const auto bitmask = WordType(1) << coord.BitOffset;
345 const auto wordmask = val ? ~WordType(0) : ~bitmask;
346 const auto oldWord = this->AndWordAtomic(coord.WordIndex, wordmask);
347 return (oldWord & bitmask) != WordType(0);
353 template <
typename WordType = WordTypePreferred>
358 "Requested WordType does not support atomic"
359 " operations on target execution platform.");
360 WordType* addr = this->GetWordAddress<WordType>(wordIdx);
368 bool OrBitAtomic(
vtkm::Id bitIdx,
bool val)
const
371 using WordType = WordTypePreferred;
372 const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
373 const auto bitmask = WordType(1) << coord.BitOffset;
375 const auto wordmask = val ? bitmask : WordType(0);
376 const auto oldWord = this->OrWordAtomic(coord.WordIndex, wordmask);
377 return (oldWord & bitmask) != WordType(0);
383 template <
typename WordType = WordTypePreferred>
388 "Requested WordType does not support atomic"
389 " operations on target execution platform.");
390 WordType* addr = this->GetWordAddress<WordType>(wordIdx);
398 bool XorBitAtomic(
vtkm::Id bitIdx,
bool val)
const
401 using WordType = WordTypePreferred;
402 const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
403 const auto bitmask = WordType(1) << coord.BitOffset;
405 const auto wordmask = val ? bitmask : WordType(0);
406 const auto oldWord = this->XorWordAtomic(coord.WordIndex, wordmask);
407 return (oldWord & bitmask) != WordType(0);
413 template <
typename WordType = WordTypePreferred>
418 "Requested WordType does not support atomic"
419 " operations on target execution platform.");
420 WordType* addr = this->GetWordAddress<WordType>(wordIdx);
431 bool CompareExchangeBitAtomic(
vtkm::Id bitIdx,
bool* oldBit,
bool newBit)
const
434 using WordType = WordTypePreferred;
435 const auto coord = this->GetBitCoordinateFromIndex<WordType>(bitIdx);
436 const auto bitmask = WordType(1) << coord.BitOffset;
438 WordType oldWord = this->GetWord<WordType>(coord.WordIndex);
441 bool actualBit = (oldWord & bitmask) != WordType(0);
442 if (actualBit != *oldBit)
447 else if (actualBit == newBit)
455 }
while (!this->CompareExchangeWordAtomic(coord.WordIndex, &oldWord, oldWord ^ bitmask));
466 template <
typename WordType = WordTypePreferred>
469 WordType newWord)
const
473 "Requested WordType does not support atomic"
474 " operations on target execution platform.");
475 WordType* addr = this->GetWordAddress<WordType>(wordIdx);
480 template <
typename WordType>
484 return reinterpret_cast<MaybeConstPointer<WordType>
>(this->Data) + wordId;
487 BufferType Data{
nullptr };
491 using BitPortal = BitPortalBase<false>;
493 using BitPortalConst = BitPortalBase<true>;
499 static constexpr
vtkm::Id BlockSize = detail::BitFieldTraits::BlockSize;
510 template <
typename Device>
524 template <
typename WordType>
528 template <
typename WordType,
typename Device =
void>
539 bool operator==(const
BitField& rhs)
const {
return this->Buffer == rhs.Buffer; }
552 template <
typename WordType>
556 static constexpr
vtkm::Id WordBits =
static_cast<vtkm::Id>(
sizeof(WordType) * CHAR_BIT);
557 return (this->GetNumberOfBits() + WordBits - 1) / WordBits;
570 this->Allocate(numberOfBits, preserve, token);
574 template <
typename ValueType>
580 this->Fill(value, token);
582 template <
typename ValueType>
586 this->AllocateAndFill(numberOfBits, value, token);
590 VTKM_CONT void FillImpl(
const void* word,
596 template <
typename WordType>
601 template <
typename WordType>
605 this->Fill(word, token);
612 this->Fill(value ? ~WordType{ 0 } : WordType{ 0 }, token);
617 this->Fill(value, token);
621 VTKM_CONT void ReleaseResourcesExecution();
639 return this->IsOnDevice(vtkm::cont::DeviceAdapterTagUndefined{});
645 VTKM_CONT WritePortalType WritePortal()
const;
650 VTKM_CONT ReadPortalType ReadPortal()
const;
679 mutable vtkm::cont::internal::Buffer
Buffer;
684 #endif // vtk_m_cont_BitField_h