AsyncBerkeley
Asynchronous Berkeley sockets. Simple.
Loading...
Searching...
No Matches
multiplexer.hpp
Go to the documentation of this file.
1/* Copyright 2025 Kevin Exton
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
20#pragma once
21#ifndef IO_MULTIPLEXER_HPP
22#define IO_MULTIPLEXER_HPP
23#include "detail/immovable.hpp"
25
26#include <variant>
31namespace io::execution {
32
37template <MuxTag Tag> struct basic_multiplexer : public Tag {
39 using multiplexer_type = Tag;
40
43 public:
45 struct task : immovable {
47 task *next = this;
48
56 std::variant<task *, void (*)(task *) noexcept> tail;
57
64 auto execute() noexcept -> void { std::get<1>(tail)(this); }
65 };
66
68 [[nodiscard]] auto is_empty() const noexcept -> bool
69 {
70 return std::get<0>(head_.tail) == &head_;
71 }
72
74 auto push(task *task) noexcept -> void
75 {
76 task->next = &head_;
77 head_.tail = std::get<0>(head_.tail)->next = task;
78 }
79
84 // NOLINTNEXTLINE(cppcoreguidelines-rvalue-reference-param-not-moved)
85 auto move_back(intrusive_task_queue &&other) noexcept -> void
86 {
87 if (!other.is_empty())
88 {
89 std::get<0>(other.head_.tail)->next = std::get<0>(head_.tail)->next;
90 std::get<0>(head_.tail)->next = other.head_.next;
91 head_.tail = other.head_.tail;
92
93 other.head_.next = std::get<0>(other.head_.tail) = &other.head_;
94 }
95 }
96
98 auto pop() noexcept -> task *
99 {
100 if (std::get<0>(head_.tail) == head_.next)
101 head_.tail = &head_;
102 return std::exchange(head_.next, head_.next->next);
103 }
104
105 private:
106 task head_{.next = &head_, .tail = &head_};
107 };
108};
109} // namespace io::execution
110#endif // IO_MULTIPLEXER_HPP
An intrusive queue of tasks.
Definition multiplexer.hpp:42
auto move_back(intrusive_task_queue &&other) noexcept -> void
Moves all tasks from one intrusive queue onto the back of another.
Definition multiplexer.hpp:85
auto push(task *task) noexcept -> void
Pushes a task onto the back of queue.
Definition multiplexer.hpp:74
auto pop() noexcept -> task *
Pops a task from the front of the queue.
Definition multiplexer.hpp:98
auto is_empty() const noexcept -> bool
Checks if the intrusive task queue is empty.
Definition multiplexer.hpp:68
This file defines concepts for the execution components.
Provides high-level interfaces for executors and completion triggers.
Definition executor.hpp:33
An intrusive task that can be executed by the multiplexer.
Definition multiplexer.hpp:45
std::variant< task *, void(*)(task *) noexcept > tail
Tail pointer variant.
Definition multiplexer.hpp:56
auto execute() noexcept -> void
Executes the task.
Definition multiplexer.hpp:64
task * next
Pointer to next in the intrusive queue.
Definition multiplexer.hpp:47
A basic multiplexer that can be used with different event types.
Definition multiplexer.hpp:37
Tag multiplexer_type
The tag type for the multiplexer.
Definition multiplexer.hpp:39