15#ifndef THREAD_FIBER_CASES_H_
16#define THREAD_FIBER_CASES_H_
21#include <absl/container/inlined_vector.h>
22#include <absl/log/check.h>
23#include <absl/log/log.h>
25#include "thread/boost_primitives.h"
30concept IsPointer = std::is_pointer_v<T>;
33concept IsNonConstPointer =
34 IsPointer<T> && !std::is_const_v<std::remove_pointer_t<T>>;
37concept IsConstPointer =
38 IsPointer<T> && std::is_const_v<std::remove_pointer_t<T>>;
41 static constexpr int kNonePicked = -1;
43 bool TryPick(
int case_index) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu) {
44 if (picked_case_index != kNonePicked) {
48 picked_case_index = case_index;
54 bool WaitForPickUntil(absl::Time deadline) ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu) {
55 while (picked_case_index == internal::Selector::kNonePicked) {
56 if (cv.WaitWithDeadline(&mu, deadline) &&
57 picked_case_index == internal::Selector::kNonePicked) {
66 int picked_case_index ABSL_GUARDED_BY(mu) = kNonePicked;
82struct [[nodiscard]] Case {
84 absl::InlinedVector<void* absl_nullable, 2>
arguments;
86 Case(internal::Selectable* absl_nonnull s) : selectable(s) {}
88 Case(internal::Selectable* absl_nullable s, internal::IsPointer
auto... args)
90 (arguments.push_back(
const_cast<void*
>(
static_cast<const void*
>(args))),
99 template <
typename... Args>
100 Case(
bool, Args... args) =
delete;
102 template <
typename T>
104 arguments.push_back(
const_cast<void*
>(
static_cast<const void*
>(arg)));
107 template <
typename T>
109 arguments.push_back(
static_cast<void*
>(arg));
112 [[nodiscard]]
void* absl_nonnull
GetArgPtr(
int index)
const {
113 if (index < 0 ||
static_cast<size_t>(index) >= arguments.size()) {
114 LOG(FATAL) <<
"Case::GetArgOrDie: index out of bounds: " << index
115 <<
", arguments.size() = " << arguments.size();
118 return arguments[
static_cast<size_t>(index)];
121 template <
typename T>
122 [[nodiscard]] T* absl_nonnull
GetArgPtr(
int index)
const {
123 return static_cast<T*
>(GetArgPtr(index));
126 [[nodiscard]]
size_t GetNumArgs()
const {
return arguments.size(); }
131typedef absl::InlinedVector<Case, 4>
CaseArray;
134struct CaseInSelectClause {
135 const Case* absl_nullable case_ptr =
nullptr;
137 internal::Selector* absl_nonnull selector =
139 CaseInSelectClause* absl_nullable prev =
141 CaseInSelectClause* absl_nullable next =
nullptr;
143 [[nodiscard]]
const Case* absl_nonnull GetCase()
const {
return case_ptr; }
146 bool TryPick() ABSL_EXCLUSIVE_LOCKS_REQUIRED(selector->
mu) {
147 return selector->TryPick(index);
150 bool Handle(
bool enqueue);
159 virtual ~Selectable() =
default;
163 virtual bool Handle(CaseInSelectClause* absl_nonnull case_state,
167 virtual void Unregister(CaseInSelectClause* absl_nonnull case_state) = 0;
170inline bool CaseInSelectClause::Handle(
bool enqueue) {
171 return GetCase()->selectable->Handle(
this, enqueue);
174inline void CaseInSelectClause::Unregister() {
175 GetCase()->selectable->Unregister(
this);
180inline void PushBack(CaseInSelectClause* absl_nonnull* absl_nonnull head,
181 CaseInSelectClause* absl_nonnull element) {
182 CHECK_EQ(element->prev,
nullptr)
183 <<
"Attempted to enqueue a CaseInSelectClause that is already on a list";
185 if (*head ==
nullptr) {
187 element->next = element;
188 element->prev = element;
191 CHECK_NE((*head)->prev,
nullptr)
192 <<
"Waiter list head is corrupt: non-null head has null prev";
195 element->next = *head;
196 element->prev = element->next->prev;
197 element->prev->next = element;
198 element->next->prev = element;
203 CaseInSelectClause* absl_nonnull element) {
204 if (element->next == element) {
209 element->next->prev = element->prev;
210 element->prev->next = element->next;
211 if (*head == element) {
212 *head = element->next;
217 element->prev =
nullptr;
Definition boost_primitives.h:110
Definition boost_primitives.h:34
static bool reader selector mu
Definition channel_waiter_state.cc:61
void PushBack(CaseInSelectClause **head, CaseInSelectClause *element)
Definition cases.h:133
void UnlinkFromList(CaseInSelectClause **head, CaseInSelectClause *element)
Definition cases.h:149
absl::InlinedVector< CaseInSelectClause, 4 > CaseStateArray
Definition cases.h:116
absl::InlinedVector< Case, 4 > CaseArray
Definition cases.h:98
A Case represents a selectable case in a Select statement.
Definition cases.h:55
Case(internal::Selectable *absl_nullable s, internal::IsPointer auto... args)
Definition cases.h:88
Case(internal::Selectable *absl_nonnull s)
Definition cases.h:86
void AddArg(T *absl_nonnull arg)
Definition cases.h:108
T *absl_nonnull GetArgPtr(int index) const
Definition cases.h:122
size_t GetNumArgs() const
Definition cases.h:126
void AddArg(const T *absl_nonnull arg)
Definition cases.h:103
Case(const Case &)=default
Case & operator=(const Case &)=default
void *absl_nonnull GetArgPtr(int index) const
Definition cases.h:112
internal::Selectable *absl_nonnull selectable
Definition cases.h:83
Case(bool, Args... args)=delete
absl::InlinedVector< void *absl_nullable, 2 > arguments
Definition cases.h:84