Symbian platform (C++)
SDK native APIs, runtime and tooling
Loading...
Searching...
No Matches
cases.h
Go to the documentation of this file.
1// Copyright 2026 The Action Engine Authors and the Symbian SDK Authors.
2// Licensed under the Apache License, Version 2.0.
3// Adapted from A11 cpp/thread/thread/cases.h at
4// fcccb8cb6e1e67d7ba0822ac14cece9ee4c7091b.
5
6#ifndef THREAD_FIBER_CASES_H_
7#define THREAD_FIBER_CASES_H_
8
9#include <cstddef>
10#include <cstdlib>
11#include <memory>
12#include <type_traits>
13
14#include "absl/container/inlined_vector.h"
15#include "absl/time/time.h"
16#include "thread/boost_primitives.h"
17
18namespace thread {
19namespace internal {
20
21template <typename T>
22concept IsPointer = std::is_pointer_v<T>;
23
24template <typename T>
25concept IsNonConstPointer =
26 IsPointer<T> && !std::is_const_v<std::remove_pointer_t<T>>;
27
28template <typename T>
29concept IsConstPointer =
30 IsPointer<T> && std::is_const_v<std::remove_pointer_t<T>>;
31
32struct Selector {
33 static constexpr int kNonePicked = -1;
34
35 bool TryPick(int index) {
36 if (picked_case_index != kNonePicked) {
37 return false;
38 }
39 picked_case_index = index;
40 return true;
41 }
42
43 // The caller holds mu. Convert the wall deadline once; successive waits
44 // use only monotonic elapsed time.
45 bool WaitForPick(absl::Time deadline = absl::InfiniteFuture());
46
47 Mutex mu;
48 CondVar cv;
49 int picked_case_index = kNonePicked;
50};
51
52class Selectable;
53} // namespace internal
54
55struct [[nodiscard]] Case {
56 internal::Selectable* selectable;
57 absl::InlinedVector<void*, 2> arguments;
58
59 Case(internal::Selectable* selectable) : selectable(selectable) {}
60
61 Case(internal::Selectable* selectable, internal::IsPointer auto... args)
62 : selectable(selectable) {
63 (arguments.push_back(const_cast<void*>(static_cast<const void*>(args))),
64 ...);
65 }
66
67 Case(const Case&) = default;
68 Case& operator=(const Case&) = default;
69
70 template <typename... Args>
71 Case(bool, Args...) = delete;
72
73 template <typename T>
74 void AddArg(const T* arg) {
75 arguments.push_back(const_cast<void*>(static_cast<const void*>(arg)));
76 }
77
78 template <typename T>
79 void AddArg(T* arg) {
80 arguments.push_back(static_cast<void*>(arg));
81 }
82
83 void* GetArgPtr(int index) const {
84 if (index < 0 || static_cast<std::size_t>(index) >= arguments.size()) {
85 std::abort();
86 }
87 return arguments[static_cast<std::size_t>(index)];
88 }
89
90 template <typename T>
91 T* GetArgPtr(int index) const {
92 return static_cast<T*>(GetArgPtr(index));
93 }
94
95 std::size_t GetNumArgs() const { return arguments.size(); }
96};
97
98using CaseArray = absl::InlinedVector<Case, 4>;
99
100namespace internal {
101struct CaseInSelectClause {
102 const Case* case_ptr = nullptr;
103 int index = -1;
104 std::shared_ptr<Selector> selector;
105 CaseInSelectClause* prev = nullptr;
106 CaseInSelectClause* next = nullptr;
107
108 const Case* GetCase() const { return case_ptr; }
109
110 bool TryPick() { return selector->TryPick(index); }
111
112 bool Handle(bool enqueue);
113 void Unregister();
114};
115
116using CaseStateArray = absl::InlinedVector<CaseInSelectClause, 4>;
117
118class Selectable {
119 public:
120 virtual ~Selectable() = default;
121 virtual bool Handle(CaseInSelectClause* case_state, bool enqueue) = 0;
122 virtual void Unregister(CaseInSelectClause* case_state) = 0;
123};
124
125inline bool CaseInSelectClause::Handle(bool enqueue) {
126 return GetCase()->selectable->Handle(this, enqueue);
127}
128
129inline void CaseInSelectClause::Unregister() {
130 GetCase()->selectable->Unregister(this);
131}
132
133inline void PushBack(CaseInSelectClause** head, CaseInSelectClause* element) {
134 if (element->prev != nullptr) {
135 std::abort();
136 }
137 if (*head == nullptr) {
138 element->next = element;
139 element->prev = element;
140 *head = element;
141 return;
142 }
143 element->next = *head;
144 element->prev = (*head)->prev;
145 element->prev->next = element;
146 element->next->prev = element;
147}
148
149inline void UnlinkFromList(CaseInSelectClause** head,
150 CaseInSelectClause* element) {
151 if (element->prev == nullptr || *head == nullptr) {
152 std::abort();
153 }
154 if (element->next == element) {
155 *head = nullptr;
156 } else {
157 element->next->prev = element->prev;
158 element->prev->next = element->next;
159 if (*head == element) {
160 *head = element->next;
161 }
162 }
163 element->prev = nullptr;
164 element->next = nullptr;
165}
166} // namespace internal
167} // namespace thread
168
169#endif // THREAD_FIBER_CASES_H_
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
Definition channel.h:29
absl::InlinedVector< Case, 4 > CaseArray
Definition cases.h:98
A Case represents a selectable case in a Select statement.
Definition cases.h:55
absl::InlinedVector< void *, 2 > arguments
Definition cases.h:57
void AddArg(T *arg)
Definition cases.h:79
Case(bool, Args...)=delete
T * GetArgPtr(int index) const
Definition cases.h:91
void * GetArgPtr(int index) const
Definition cases.h:83
Case(internal::Selectable *selectable)
Definition cases.h:59
internal::Selectable * selectable
Definition cases.h:56
Case(const Case &)=default
Case(internal::Selectable *selectable, internal::IsPointer auto... args)
Definition cases.h:61
Case & operator=(const Case &)=default
std::size_t GetNumArgs() const
Definition cases.h:95
void AddArg(const T *arg)
Definition cases.h:74