File: bit_field.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (156 lines) | stat: -rw-r--r-- 5,432 bytes parent folder | download | duplicates (11)
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_