NUMA++ 0.11.0
Loading...
Searching...
No Matches
bitmask.hpp
Go to the documentation of this file.
1/**
2 * @file
3 * @ingroup numapp_numa
4 * @copyright ESO 2024 - European Southern Observatory
5 *
6 * @brief Contains declarations for numapp::Bitmask
7 */
8#ifndef NUMAPP_BITMASK_HPP_
9#define NUMAPP_BITMASK_HPP_
10#include <iosfwd>
11#include <memory>
12#include <type_traits>
13
14#include <numa.h>
15
16namespace numapp {
17
18/**
19 * Lowlevel bitmask type.
20 *
21 * @ingroup numapp_numa
22 */
23using NumaBitmaskPtr = std::unique_ptr<struct bitmask, void (*)(struct bitmask*)>;
24
25template <class Class>
26class Bitmask;
27
28/**
29 * Invoke function for each bit in mask that matches @a value.
30 *
31 * @param bitmask Bitmask to iterate over.
32 * @param f function callable as `f(position)` where @a position is the `unsigned int` bit position.
33 * @param value to test bit for (true == bit is set, false == bit is unset).
34 *
35 * Example that starts a pinned thread for each bit in a CPU mask:
36 *
37 * @include forEachExample.cpp
38 *
39 * @par Header file
40 * @c <numapp/bitmask.hpp>
41 *
42 * @relatesalso Bitmask
43 * @sa Cpumask Nodemask
44 * @ingroup numapp_numa
45 */
46template <class Class, class F>
47void ForEach(Bitmask<Class> const& bitmask, F&& f, bool value = true);
48
49/**
50 * Generic bitmask
51 *
52 * @ingroup numapp_numa
53 */
54template <class Class>
55class Bitmask {
56public:
57 Bitmask() : m_bitmask(Class::Alloc()) {
58 }
59
60 Bitmask(Bitmask&& rhs) noexcept = default;
61 Bitmask(Bitmask const& rhs) : m_bitmask(Class::Alloc()) {
62 *this = rhs;
63 }
64 Bitmask& operator=(Bitmask&&) noexcept = default;
65 /**
66 * Copy from @a rhs to this.
67 *
68 * @param rhs bitmask to copy from.
69 * @returns reference to this.
70 */
71 Bitmask& operator=(Bitmask const& rhs) noexcept {
72 // Copy from rhs to this
73 copy_bitmask_to_bitmask(rhs.m_bitmask.get(), m_bitmask.get());
74 return *this;
75 }
76
77 /**
78 * @name Comparison
79 */
80 /// @{
81 /**
82 * @returns true if bitmask are equal.
83 */
84 [[nodiscard]] bool operator==(Bitmask const& rhs) const noexcept {
85 return numa_bitmask_equal(m_bitmask.get(), rhs.m_bitmask.get()) == 1;
86 }
87 /**
88 * @returns true if bitmask are equal.
89 */
90 [[nodiscard]] bool operator!=(Bitmask const& rhs) const noexcept {
91 return !(this == rhs);
92 }
93 /// @}
94
95 /**
96 * @name Accessors
97 */
98 /// @{
99 /**
100 * Access native bitmask type.
101 *
102 * @return pointer to libnuma bitmask type.
103 */
104 struct bitmask const* GetNative() const noexcept {
105 return m_bitmask.get();
106 }
107 /**
108 * Access native bitmask type.
109 *
110 * @return pointer to libnuma bitmask type.
111 */
112 struct bitmask* GetNative() noexcept {
113 return m_bitmask.get();
114 }
115
116 /**
117 * Query number of bits in mask.
118 *
119 * @return number of bits in mask.
120 */
121 [[nodiscard]] std::size_t GetSize() const noexcept {
122 return m_bitmask->size;
123 }
124
125 /**
126 * Test if bit in specified position is set.
127 *
128 * @param position Zero-indexed bit position to test.
129 * @return value of bit in requested @a position or false if @a position is outside valid range.
130 */
131 [[nodiscard]] bool Test(unsigned int position) const noexcept {
132 return numa_bitmask_isbitset(GetNative(), position);
133 }
134
135 /// @}
136 /**
137 * @name Modifiers
138 *
139 * If specified bit position is outside valid range no operations is performed. This behaviour
140 * is inherited from libnuma.
141 */
142 /// @{
143 /**
144 * Set bit in @a position to specified value.
145 *
146 * @note If position is outside valid range nothing is done.
147 *
148 * @param position Zero-indexed bit position to modify.
149 * @param value Bit value to set (default true).
150 * @return Reference to this object (for call chaining).
151 */
152 Bitmask& Set(unsigned int position, bool value = true) noexcept {
153 if (value) {
154 numa_bitmask_setbit(GetNative(), position);
155 } else {
156 numa_bitmask_clearbit(GetNative(), position);
157 }
158 return *this;
159 }
160
161 /**
162 * Sets bit in specified position to false.
163 *
164 * @note If position is outside valid range nothing is done.
165 *
166 * @param position Zero-indexed bit position to modify.
167 * @return Reference to this object (for call chaining).
168 */
169 Bitmask& Reset(unsigned int position) noexcept {
170 numa_bitmask_clearbit(GetNative(), position);
171 return *this;
172 }
173 /// @}
174protected:
175 /**
176 * Construction from native bitmask type can be error prone in that
177 * the mask wasn't allocated using the correction function. To prevent mistakes this is made
178 * protected so it can only be used by the concrete implementations.
179 */
180 Bitmask(NumaBitmaskPtr&& bitmask) : m_bitmask(std::move(bitmask)) {
181 }
182
183private:
184 NumaBitmaskPtr m_bitmask;
185};
186
187/**
188 * Formats @a mask and inserts it to @a os.
189 *
190 * @param os output stream to insert into.
191 * @param mask Bitmask to format.
192 * @param min_bits Minimum number of bits to format.
193 * @returns @a os
194 *
195 * @relatesalso Bitmask
196 * @ingroup numapp_numa
197 */
198template <class Class>
199std::ostream& FormatBitmask(std::ostream& os, Bitmask<Class> const& mask, int min_bits);
200
201/**
202 * Formats @a mask and inserts it to @a os.
203 *
204 * @param os output stream to insert into.
205 * @param mask Bitmask to format.
206 * @param min_bits Minimum number of bits to format.
207 * @returns @a os
208 *
209 * @relatesalso Bitmask
210 * @ingroup numapp_numa
211 */
212std::ostream& FormatBitmask(std::ostream& os, bitmask const* mask, int min_bits);
213
214template <class Class>
215std::ostream& FormatBitmask(std::ostream& os, Bitmask<Class> const& mask, int min_bits) {
216 return FormatBitmask(os, mask.GetNative(), min_bits);
217}
218
219template <class Class, class F>
220void ForEach(Bitmask<Class> const& bits, F&& f, bool value) {
221 static_assert(std::is_invocable_v<F, unsigned int>,
222 "Function must be invocable with signature `f(unsigned int)`");
223 auto const num_bits = bits.GetSize();
224 for (unsigned int position = 0u; position < num_bits; ++position) {
225 if (bits.Test(position) == value) {
226 f(position);
227 }
228 }
229}
230
231} // namespace numapp
232
233#endif // #ifndef NUMAPP_BITMASK_HPP_
Generic bitmask.
Definition bitmask.hpp:55
std::size_t GetSize() const noexcept
Query number of bits in mask.
Definition bitmask.hpp:121
bool operator==(Bitmask const &rhs) const noexcept
Definition bitmask.hpp:84
Bitmask & Set(unsigned int position, bool value=true) noexcept
Set bit in position to specified value.
Definition bitmask.hpp:152
struct bitmask * GetNative() noexcept
Access native bitmask type.
Definition bitmask.hpp:112
Bitmask & operator=(Bitmask const &rhs) noexcept
Copy from rhs to this.
Definition bitmask.hpp:71
Bitmask(NumaBitmaskPtr &&bitmask)
Construction from native bitmask type can be error prone in that the mask wasn't allocated using the ...
Definition bitmask.hpp:180
Bitmask & Reset(unsigned int position) noexcept
Sets bit in specified position to false.
Definition bitmask.hpp:169
struct bitmask const * GetNative() const noexcept
Access native bitmask type.
Definition bitmask.hpp:104
bool Test(unsigned int position) const noexcept
Test if bit in specified position is set.
Definition bitmask.hpp:131
bool operator!=(Bitmask const &rhs) const noexcept
Definition bitmask.hpp:90
std::unique_ptr< struct bitmask, void(*)(struct bitmask *)> NumaBitmaskPtr
Lowlevel bitmask type.
Definition bitmask.hpp:23
void ForEach(Bitmask< Class > const &bitmask, F &&f, bool value=true)
Invoke function for each bit in mask that matches value.
Definition bitmask.hpp:220
void ForEach(Bitmask< Class > const &bitmask, F &&f, bool value=true)
Invoke function for each bit in mask that matches value.
Definition bitmask.hpp:220
std::ostream & FormatBitmask(std::ostream &os, Bitmask< Class > const &mask, int min_bits)
Formats mask and inserts it to os.
Definition bitmask.hpp:215
std::ostream & FormatBitmask(std::ostream &os, bitmask const *mask, int min_bits)
Formats mask and inserts it to os.
Definition bitmask.cpp:13