Each task that is ready to be completed is moved to the __ready queue. If the submission queue gets full before all tasks are submitted, the remaining tasks are moved to the __pending queue. If is_stopped is true, no new tasks are submitted to the io_uring unless it is a cancellation. If is_stopped is true and a task is not ready to be completed, the task is completed with an io_uring_cqe object w
| 234 | // If is_stopped is true and a task is not ready to be completed, the task is completed with |
| 235 | // an io_uring_cqe object with the result field set to -ECANCELED. |
| 236 | auto submit(__task_queue __tasks, __u32 __max_submissions, bool __is_stopped) noexcept |
| 237 | -> __submission_result |
| 238 | { |
| 239 | __u32 __tail = __tail_.load(STDEXEC::__std::memory_order_relaxed); |
| 240 | __u32 __head = __head_.load(STDEXEC::__std::memory_order_acquire); |
| 241 | __u32 __current_count = __tail - __head; |
| 242 | STDEXEC_ASSERT(__current_count <= __n_total_slots_); |
| 243 | __max_submissions = STDEXEC::__umin( |
| 244 | {__max_submissions, __n_total_slots_ - __current_count}); |
| 245 | __submission_result __result{}; |
| 246 | __task* __op = nullptr; |
| 247 | while (!__tasks.empty() && __result.__n_submitted < __max_submissions) |
| 248 | { |
| 249 | __u32 const __index = __tail & __mask_; |
| 250 | ::io_uring_sqe& __sqe = __entries_[__index]; |
| 251 | __op = __tasks.pop_front(); |
| 252 | STDEXEC_ASSERT(__op->__vtable_); |
| 253 | if (__op->__vtable_->__ready_(__op)) |
| 254 | { |
| 255 | __result.__ready.push_back(__op); |
| 256 | } |
| 257 | else |
| 258 | { |
| 259 | __op->__vtable_->__submit_(__op, __sqe); |
| 260 | # ifdef STDEXEC_HAS_IO_URING_ASYNC_CANCELLATION |
| 261 | __is_stopped = __is_stopped && __sqe.opcode != IORING_OP_ASYNC_CANCEL; |
| 262 | # endif |
| 263 | if (__is_stopped) |
| 264 | { |
| 265 | __stop(__op); |
| 266 | } |
| 267 | else |
| 268 | { |
| 269 | __sqe.user_data = bit_cast<__u64>(__op); |
| 270 | __array_[__index] = __index; |
| 271 | ++__result.__n_submitted; |
| 272 | ++__tail; |
| 273 | } |
| 274 | } |
| 275 | } |
| 276 | __tail_.store(__tail, STDEXEC::__std::memory_order_release); |
| 277 | while (!__tasks.empty()) |
| 278 | { |
| 279 | __op = __tasks.pop_front(); |
| 280 | if (__op->__vtable_->__ready_(__op)) |
| 281 | { |
| 282 | __result.__ready.push_back(__op); |
| 283 | } |
| 284 | else |
| 285 | { |
| 286 | __result.__pending.push_back(__op); |
| 287 | } |
| 288 | } |
| 289 | return __result; |
| 290 | } |
| 291 | }; |
| 292 | |
| 293 | class __completion_queue |