106 Observation(
Result result,
size_t generation) : result(result), generation(generation) {}
115 : m_Request(request),
116 m_Generation(generation),
117 m_Ready(request.waitUntilAcknowledged(generation)) {}
120 m_Request.consume(m_Generation);
123 explicit operator bool()
const {
135 : m_Request(requestReleased, this),
143 m_ReleaseFailures(0),
144 m_AcknowledgementWaiters() {
145 for (
size_t i = 0; i < 7; ++i) {
150 bool configure(
RequestQueue& queue,
size_t priority, uint64_t p1 = 0, uint64_t p2 = 0,
151 uint64_t p3 = 0, uint64_t p4 = 0, uint64_t p5 = 0, uint64_t p6 = 0,
153 if (m_Configured || priority >= REQUEST_QUEUE_NUM_PRIORITIES || !m_Request.isAvailable()) {
158 m_Priority = priority;
159 m_Parameters[0] = p1;
160 m_Parameters[1] = p2;
161 m_Parameters[2] = p3;
162 m_Parameters[3] = p4;
163 m_Parameters[4] = p5;
164 m_Parameters[5] = p6;
165 m_Parameters[6] = p7;
170 Observation observe() {
172 return Observation(Result::QueueStopped, 0);
174 if (!m_Configured || m_Stopping) {
175 return Observation(Result::QueueStopped, 0);
178 const size_t generation = (m_Observed += 1);
179 auto result = publishGeneration(generation,
true);
180 return Observation(result, generation);
184 void acknowledge(
size_t generation) {
186 auto guard = m_AcknowledgementWaiters.acquire();
188 advance(m_Acknowledged, generation);
203 auto guard = m_AcknowledgementWaiters.acquire();
211 void cancel(
size_t generation) {
215 bool isIdle()
const {
216 return m_Request.isAvailable() && (m_Stopping || m_Consumed >= m_Observed);
219 size_t observedGeneration()
const {
223 static bool canAcknowledge(
Result result) {
224 return result == Result::Accepted || result == Result::Coalesced;
227 bool hasPublicationFailure()
const {
228 return static_cast<size_t>(m_ReleaseFailures) != 0;
233 while (value < target) {
234 const size_t current = value;
235 if (current >= target || value.compareAndSwap(current, target)) {
241 static Result translate(RequestQueue::PreallocatedPublishResult result) {
242 using QueueResult = RequestQueue::PreallocatedPublishResult;
244 case QueueResult::Accepted:
245 return Result::Accepted;
246 case QueueResult::QueueStopped:
247 return Result::QueueStopped;
248 case QueueResult::QueueFull:
249 return Result::QueueFull;
250 case QueueResult::InvalidPriority:
251 return Result::InvalidPriority;
252 case QueueResult::TokenBusy:
253 return Result::TokenBusy;
255 return Result::TokenBusy;
258 static void requestReleased(
void* context) {
259 reinterpret_cast<PortChangeRequest*
>(context)->released();
266 auto guard = m_AcknowledgementWaiters.acquire();
272 const size_t observed = m_Observed;
273 if (observed <= m_Consumed) {
277 const Result result = publishGeneration(observed,
false);
278 if (result != Result::Accepted && result != Result::Coalesced) {
279 m_ReleaseFailures += 1;
283 Result publishGeneration(
size_t generation,
bool tryIdle) {
285 m_Request, m_Priority, m_Parameters[0], m_Parameters[1], m_Parameters[2], m_Parameters[3],
286 m_Parameters[4], m_Parameters[5], m_Parameters[6], generation);
287 if (tryIdle && result == RequestQueue::PreallocatedPublishResult::TokenBusy) {
288 result = m_Queue->
publishPreallocated(m_Request, m_Priority, m_Parameters[0], m_Parameters[1],
289 m_Parameters[2], m_Parameters[3], m_Parameters[4],
290 m_Parameters[5], m_Parameters[6], generation);
293 if (result == RequestQueue::PreallocatedPublishResult::TokenBusy) {
294 return Result::Coalesced;
296 return translate(result);
299 bool waitUntilAcknowledged(
size_t generation) {
302 auto guard = m_AcknowledgementWaiters.acquire();
306 if (m_Acknowledged >= generation) {
315 return !m_Stopping && m_Acknowledged >= generation;
319 void consume(
size_t generation) {
320 advance(m_Consumed, generation);
326 uint64_t m_Parameters[7];
MUST_USE_RESULT PreallocatedPublishResult republishPreallocatedWhileReleasing(PreallocatedRequest &request, size_t priority, uint64_t p1=0, uint64_t p2=0, uint64_t p3=0, uint64_t p4=0, uint64_t p5=0, uint64_t p6=0, uint64_t p7=0, uint64_t p8=0)
MUST_USE_RESULT PreallocatedPublishResult publishPreallocated(PreallocatedRequest &request, size_t priority, uint64_t p1=0, uint64_t p2=0, uint64_t p3=0, uint64_t p4=0, uint64_t p5=0, uint64_t p6=0, uint64_t p7=0, uint64_t p8=0)