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 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BIT_FIELD_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BIT_FIELD_H_
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/atomic_operations.h"
namespace WTF {
enum class BitFieldValueConstness {
kNonConst,
kConst,
};
namespace internal {
template <class BitFieldType>
class BitFieldBase;
// Helper class for defining values in a bit field. This helper provides
// utilities to read, write and update the value in the bit field.
template <class ValueType,
size_t offset,
size_t size,
class BitFieldType,
BitFieldValueConstness is_const = BitFieldValueConstness::kNonConst>
class BitFieldValue final {
static_assert(std::is_fundamental<ValueType>::value,
"Fields in a bit field must be of a primitive type.");
static_assert(std::is_fundamental<BitFieldType>::value,
"Bit fields must be of a primitive type.");
static_assert(std::is_unsigned<BitFieldType>::value,
"Bit field must be of an unsigned type");
static_assert(sizeof(ValueType) <= sizeof(BitFieldType),
"Value in bit field cannot be bigger than the bit field");
static_assert(
offset < 8 * sizeof(BitFieldType),
"Field offset in bit field must be smaller than the bit field size");
static_assert(
size < 8 * sizeof(BitFieldType),
"Field size in bit field must be smaller than the bit field size");
static_assert(offset + size <= 8 * sizeof(BitFieldType),
"Field in bit field cannot overflow the bit field");
static_assert(size > 0, "Bit field fields cannot have 0 size.");
public:
using Type = ValueType;
template <class OtherValueType,
int other_size,
BitFieldValueConstness other_is_const =
BitFieldValueConstness::kNonConst>
using DefineNextValue = BitFieldValue<OtherValueType,
offset + size,
other_size,
BitFieldType,
other_is_const>;
// Create a bit field with the given value.
static constexpr BitFieldType encode(ValueType value) {
DCHECK(is_valid(value));
return static_cast<BitFieldType>(value) << offset;
}
// Update a bit field with the given value.
static constexpr BitFieldType update(BitFieldType previous, ValueType value) {
return (previous & ~kMask) | encode(value);
}
// Read the value from the bit field.
static constexpr ValueType decode(BitFieldType value) {
return static_cast<ValueType>((value & kMask) >> offset);
}
private:
static constexpr BitFieldValueConstness kIsConst = is_const;
static constexpr BitFieldType kValidationMask =
(BitFieldType{1} << size) - BitFieldType{1};
static constexpr BitFieldType kMask = (kValidationMask) << offset;
static_assert(kMask != 0, "Mask in which all bits are 0 is not allowed.");
static_assert(~kMask != 0, "Mask in which all bits are 1 is not allowed.");
// Confirm that the provided value fits into the bit field.
static constexpr bool is_valid(ValueType value) {
return (static_cast<BitFieldType>(value) & ~kValidationMask) == 0;
}
friend class BitFieldBase<BitFieldType>;
};
} // namespace internal
// BitField intended to be used by a single thread.
template <class BitFieldType>
class WTF_EXPORT SingleThreadedBitField {
static_assert(std::is_fundamental<BitFieldType>::value,
"Bit fields must be of a primitive type.");
static_assert(std::is_unsigned<BitFieldType>::value,
"Bit field must be of an unsigned type");
public:
template <class Type,
int size,
BitFieldValueConstness is_const = BitFieldValueConstness::kNonConst>
using DefineFirstValue =
internal::BitFieldValue<Type, 0, size, BitFieldType, is_const>;
explicit SingleThreadedBitField() : SingleThreadedBitField(0) {}
explicit SingleThreadedBitField(BitFieldType bits) : bits_(bits) {}
template <typename Value>
typename Value::Type get() const {
return Value::decode(bits_);
}
template <typename Value>
void set(typename Value::Type value) {
bits_ = Value::update(bits_, value);
}
BitFieldType bits() const { return bits_; }
protected:
BitFieldType bits_;
};
// BitField that can be written by a single thread but read by multiple threads.
template <class BitFieldType>
class WTF_EXPORT ConcurrentlyReadBitField
: public SingleThreadedBitField<BitFieldType> {
using Base = SingleThreadedBitField<BitFieldType>;
using Base::bits_;
public:
explicit ConcurrentlyReadBitField() : Base(0) {}
explicit ConcurrentlyReadBitField(BitFieldType bits) : Base(bits) {}
template <typename Value>
typename Value::Type get_concurrently() const {
return Value::decode(AsAtomicPtr(&bits_)->load(std::memory_order_relaxed));
}
template <typename Value>
void set(typename Value::Type value) {
AsAtomicPtr(&bits_)->store(Value::update(bits_, value),
std::memory_order_relaxed);
}
};
} // namespace WTF
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_BIT_FIELD_H_
|