21#include "lib/stdcompat/type_traits.h"
22#include "pw_assert/assert.h"
23#include "pw_numeric/integer_division.h"
24#include "pw_polyfill/language_feature_macros.h"
26namespace pw::thread::internal {
31inline constexpr size_t kNamedPriorities = 9;
36PW_CONSTEVAL std::array<T, kNamedPriorities> PriorityOffsets(T highest) {
37 std::array<T, kNamedPriorities> offsets{};
39 for (
unsigned i = 0; i < kNamedPriorities; ++i) {
41 uint64_t priority_value = IntegerDivisionRoundNearest<uint64_t>(
42 static_cast<uint64_t
>(highest) * i, kNamedPriorities - 1);
44 offsets[i] =
static_cast<T
>(priority_value);
52template <
typename T, T kLowest, T kHighest,
bool = kLowest <= kHighest>
55 using U = std::make_
unsigned_t<T>;
57 static constexpr U Range() { return kHighest - kLowest; }
59 constexpr AbstractLevel() : n_{} {}
60 explicit constexpr AbstractLevel(T value) : n_{value} {}
61 constexpr T value() const { return n_; }
63 constexpr
bool operator==(AbstractLevel rhs) const { return n_ == rhs.n_; }
64 constexpr
bool operator!=(AbstractLevel rhs) const { return n_ != rhs.n_; }
65 constexpr
bool operator<(AbstractLevel rhs) const { return n_ < rhs.n_; }
66 constexpr
bool operator<=(AbstractLevel rhs) const { return n_ <= rhs.n_; }
67 constexpr
bool operator>(AbstractLevel rhs) const { return n_ > rhs.n_; }
68 constexpr
bool operator>=(AbstractLevel rhs) const { return n_ >= rhs.n_; }
70 constexpr AbstractLevel operator+(U amount) const {
71 return AbstractLevel(static_cast<T>(static_cast<U>(n_) + amount));
73 constexpr AbstractLevel operator-(U amount) const {
74 return AbstractLevel(static_cast<T>(static_cast<U>(n_) - amount));
78 static_assert(kLowest <= kHighest);
82template <
typename T, T kLowest, T kHighest>
83struct AbstractLevel<T, kLowest, kHighest, false> {
85 using U = std::make_unsigned_t<T>;
87 static constexpr U Range() {
return kLowest - kHighest; }
89 constexpr AbstractLevel() : n_{} {}
90 explicit constexpr AbstractLevel(T value) : n_{value} {}
91 constexpr T value()
const {
return n_; }
93 constexpr bool operator==(AbstractLevel rhs)
const {
return n_ == rhs.n_; }
94 constexpr bool operator!=(AbstractLevel rhs)
const {
return n_ != rhs.n_; }
95 constexpr bool operator<(AbstractLevel rhs)
const {
return n_ > rhs.n_; }
96 constexpr bool operator<=(AbstractLevel rhs)
const {
return n_ >= rhs.n_; }
97 constexpr bool operator>(AbstractLevel rhs)
const {
return n_ < rhs.n_; }
98 constexpr bool operator>=(AbstractLevel rhs)
const {
return n_ <= rhs.n_; }
100 constexpr AbstractLevel operator+(U amount)
const {
101 return AbstractLevel(
static_cast<T
>(
static_cast<U
>(n_) - amount));
103 constexpr AbstractLevel operator-(U amount)
const {
104 return AbstractLevel(
static_cast<T
>(
static_cast<U
>(n_) + amount));
108 static_assert(kLowest > kHighest);
114template <
typename T,
bool = std::is_enum_v<T>>
115struct UnderlyingInteger :
public std::underlying_type<T> {};
118struct UnderlyingInteger<T, false> :
public cpp20::type_identity<T> {};
122template <
typename T, T kLowestPriority, T kHighestPriority, T kDefaultPriority>
126 static constexpr bool IsSupported() {
return Level::Range() != 0u; }
175 PW_ASSERT(*
this != maximum);
185 PW_ASSERT(*
this != minimum);
191 return *
this > minimum ?
Priority(level_ - 1) : *
this;
196 return *
this < maximum ?
Priority(level_ + 1) : *
this;
199 constexpr bool operator==(
Priority rhs)
const {
return level_ == rhs.level_; }
200 constexpr bool operator!=(
Priority rhs)
const {
return level_ != rhs.level_; }
201 constexpr bool operator<(
Priority rhs)
const {
return level_ < rhs.level_; }
202 constexpr bool operator<=(
Priority rhs)
const {
return level_ <= rhs.level_; }
203 constexpr bool operator>(
Priority rhs)
const {
return level_ > rhs.level_; }
204 constexpr bool operator>=(
Priority rhs)
const {
return level_ >= rhs.level_; }
222 const Level level(
static_cast<NativeInt
>(priority));
223 PW_ASSERT(kLevels[kLowest] <= level);
224 PW_ASSERT(level <= kLevels[kHighest]);
229 static_assert(std::is_integral_v<native_type> || std::is_enum_v<native_type>,
230 "The native priority type must be an integer or enum");
231 static_assert(
sizeof(
native_type) <=
sizeof(uint64_t),
232 "The native priority type cannot be larger than 64 bits");
234 using NativeInt =
typename UnderlyingInteger<native_type>::type;
235 using Level = AbstractLevel<NativeInt,
236 static_cast<NativeInt
>(kLowestPriority),
237 static_cast<NativeInt
>(kHighestPriority)>;
251 static_assert(kNamedPriorities ==
static_cast<size_t>(kHighest) + 1);
255 static constexpr std::array<Level, kNamedPriorities> kLevels = [] {
256 const std::array offsets = PriorityOffsets(Level::Range());
258 std::array<Level, kNamedPriorities> levels{};
259 for (
size_t i = 0; i < offsets.size(); ++i) {
260 levels[i] = Level(
static_cast<NativeInt
>(kLowestPriority)) + offsets[i];
265 static constexpr Level kDefault{
static_cast<NativeInt
>(kDefaultPriority)};
266 static_assert(kLevels[kLowest] <= kDefault && kDefault <= kLevels[kHighest],
267 "pw::thread::backend::kDefaultPriority must be between "
268 "kLowestPriority and kHighestPriority");
270 explicit constexpr Priority(Level level) : level_{level} {}
#define PW_CONSTEVAL
Definition: language_feature_macros.h:40
static constexpr Priority Highest()
Definition: priority.h:164
constexpr Priority()
Constructs a priority at the backend-specified default level.
Definition: priority.h:129
static constexpr Priority Default()
Returns a priority at the backend-specified default level.
Definition: priority.h:167
constexpr Priority NextHigher(Priority maximum=Highest()) const
Definition: priority.h:174
static constexpr bool IsSupported()
True if the pw_thread backend supports more than one priority level.
Definition: priority.h:126
static constexpr Priority VeryLow()
Priority higher than Lowest, but lower than Low, if possible.
Definition: priority.h:140
constexpr Priority NextLowerClamped(Priority minimum=Lowest()) const
Returns the next lower priority, down to the provided maximum.
Definition: priority.h:190
static constexpr Priority High()
Priority higher than MediumHigh, but lower than VeryHigh, if possible.
Definition: priority.h:156
T native_type
Definition: priority.h:209
constexpr Priority NextLower(Priority minimum=Lowest()) const
Definition: priority.h:184
static constexpr Priority MediumHigh()
Priority higher than Medium, but lower than High, if possible.
Definition: priority.h:153
static constexpr Priority Lowest()
Definition: priority.h:137
constexpr Priority NextHigherClamped(Priority maximum=Highest()) const
Returns the next higher priority, up to the provided minimum.
Definition: priority.h:195
static constexpr Priority FromNative(native_type priority)
Definition: priority.h:221
static constexpr Priority Medium()
Definition: priority.h:150
static constexpr Priority VeryHigh()
Priority higher than High, but lower than Highest, if possible.
Definition: priority.h:159
constexpr native_type native() const
Definition: priority.h:214
static constexpr Priority MediumLow()
Priority higher than Low, but lower than Medium, if possible.
Definition: priority.h:146
static constexpr Priority Low()
Priority higher than VeryLow, but lower than MediumLow, if possible.
Definition: priority.h:143