co_usb
Loading...
Searching...
No Matches
any_event_handler.hpp
Go to the documentation of this file.
1
6#pragma once
7
9#include <concepts>
10#include <memory_resource>
11#include <type_traits>
12#include <utility>
13
14namespace co_usb::ev
15{
16
18
31{
33
34 explicit any_event_handler () noexcept
35 {
36 }
37
38 template <detail::EventHandler HandlerTy, typename... Args>
39 requires(!std::same_as<HandlerTy, any_event_handler> &&
40 !std::same_as<HandlerTy, event_handler_ref> &&
41 std::constructible_from<HandlerTy, Args...>)
42 explicit any_event_handler(std::pmr::memory_resource *memres, Args &&...args)
43 : m_vtable(make_vtable<HandlerTy>()), m_memres(memres),
44 m_storage(construct_storage<HandlerTy>(m_memres, std::forward<Args>(args)...))
45 {
46 }
47
48 template <detail::EventHandler HandlerTy, typename... Args>
49 requires(!std::same_as<HandlerTy, any_event_handler> &&
50 !std::same_as<HandlerTy, event_handler_ref> &&
51 std::constructible_from<HandlerTy, Args...>)
52 explicit any_event_handler(Args &&...args)
53 : m_vtable(make_vtable<HandlerTy>()), m_memres(std::pmr::get_default_resource()),
54 m_storage(construct_storage<HandlerTy>(m_memres, std::forward<Args>(args)...))
55 {
56 }
57
58 template <detail::EventHandler HandlerTy, typename... Args>
59 requires(!std::same_as<HandlerTy, any_event_handler> &&
60 !std::same_as<HandlerTy, event_handler_ref> &&
61 std::constructible_from<HandlerTy, Args...>)
62 auto emplace (std::pmr::memory_resource *memres, Args &&...args)
63 {
64 destroy();
65 m_memres = memres;
66 m_storage = construct_storage<HandlerTy>(m_memres, std::forward<Args>(args)...);
67 m_vtable = make_vtable<HandlerTy>();
68 }
69
70 template <detail::EventHandler HandlerTy, typename... Args>
71 requires(!std::same_as<HandlerTy, any_event_handler> &&
72 !std::same_as<HandlerTy, event_handler_ref> &&
73 std::constructible_from<HandlerTy, Args...>)
74 auto emplace (Args &&...args)
75 {
76 emplace<HandlerTy>(m_memres, std::forward<Args>(args)...);
77 }
78
79 any_event_handler(any_event_handler const &other) = delete;
81
83 : m_vtable(other.m_vtable), m_memres(other.m_memres), m_storage(other.m_storage)
84 {
85 other.m_storage = nullptr;
86 }
87
89 {
90 if (this == &other)
91 {
92 return *this;
93 }
94 destroy();
95 m_vtable = other.m_vtable;
96 m_memres = other.m_memres;
97 m_storage = other.m_storage;
98 other.m_storage = nullptr;
99 return *this;
100 }
101
103 {
104 destroy();
105 }
106
107 auto valid () const noexcept -> bool
108 {
109 return m_storage;
110 }
111
112 auto start (libusb_context *usb_ctx, std::stop_token stop) -> bool
113 {
114 if (!m_storage)
115 {
116 return false;
117 }
118 return m_vtable.start_fn(m_storage, usb_ctx, std::move(stop));
119 }
120
121 auto ref () noexcept -> void
122 {
123 if (!m_storage)
124 {
125 return;
126 }
127 return m_vtable.ref_fn(m_storage);
128 }
129
130 auto unref () noexcept -> void
131 {
132 if (!m_storage)
133 {
134 return;
135 }
136 return m_vtable.unref_fn(m_storage);
137 }
138
139 auto stop () -> void
140 {
141 if (!m_storage)
142 {
143 return;
144 }
145 return m_vtable.stop_fn(m_storage);
146 }
147
148 private:
149 struct vtable
150 {
151 using start_fn_t = auto (*)(void *, libusb_context *, std::stop_token) -> bool;
152 using ref_fn_t = auto (*)(void *) noexcept -> void;
153 using unref_fn_t = auto (*)(void *) noexcept -> void;
154 using stop_fn_t = auto (*)(void *) -> void;
155 using dtor_fn_t = auto (*)(void *) -> void;
156
157 start_fn_t start_fn{nullptr};
158 ref_fn_t ref_fn{nullptr};
159 unref_fn_t unref_fn{nullptr};
160 stop_fn_t stop_fn{nullptr};
161 dtor_fn_t dtor_fn{nullptr};
162 size_t size;
163 size_t align;
164 };
165
166 template <detail::EventHandler HandlerTy, typename... Args>
167 auto construct_storage (std::pmr::memory_resource *memres, Args &&...args) -> void *
168 {
169 using handler_t = std::remove_cvref_t<HandlerTy>;
170 const auto size = sizeof(handler_t);
171 const auto align = alignof(handler_t);
172 void *const ptr = memres->allocate(size, align);
173 try
174 {
175 new (ptr) handler_t(std::forward<Args>(args)...);
176 }
177 catch (...)
178 {
179 memres->deallocate(ptr, size, align);
180 throw;
181 }
182 return ptr;
183 }
184
185 template <detail::EventHandler HandlerTy> static auto make_vtable () -> vtable
186 {
187 return vtable{
188 .start_fn = +[] (void *orig, libusb_context *ctx, std::stop_token stop) -> bool
189 { return static_cast<HandlerTy *>(orig)->start(ctx, stop); },
190 .ref_fn = +[] (void *orig) noexcept -> void
191 { return static_cast<HandlerTy *>(orig)->ref(); },
192 .unref_fn = +[] (void *orig) noexcept -> void
193 { return static_cast<HandlerTy *>(orig)->unref(); },
194 .stop_fn = +[] (void *orig) -> void { return static_cast<HandlerTy *>(orig)->stop(); },
195 .dtor_fn = +[] (void *orig) -> void
196 { return static_cast<HandlerTy *>(orig)->~HandlerTy(); },
197 .size = sizeof(HandlerTy),
198 .align = alignof(HandlerTy),
199 };
200 }
201
202 auto destroy () -> void
203 {
204 if (!m_storage)
205 return;
206 m_vtable.dtor_fn(m_storage);
207 m_memres->deallocate(m_storage, m_vtable.size, m_vtable.align);
208 m_storage = nullptr;
209 }
210
211 vtable m_vtable;
212 std::pmr::memory_resource *m_memres = std::pmr::get_default_resource();
213 void *m_storage{nullptr};
214};
215static_assert(detail::EventHandler<any_event_handler>, "Not a proper USB event handler");
216
217} // namespace co_usb::ev
Concept defining an event handler for libusb.
Definition event_handler.hpp:42
Specification and implementation of EventHandler concept.
Definition any_event_handler.hpp:15
Owning type-erased wrapper for EventHandler.
Definition any_event_handler.hpp:31
auto unref() noexcept -> void
Definition any_event_handler.hpp:130
any_event_handler(Args &&...args)
Definition any_event_handler.hpp:52
auto start(libusb_context *usb_ctx, std::stop_token stop) -> bool
Definition any_event_handler.hpp:112
any_event_handler(any_event_handler &&other) noexcept
Definition any_event_handler.hpp:82
auto emplace(std::pmr::memory_resource *memres, Args &&...args)
Definition any_event_handler.hpp:62
any_event_handler(any_event_handler const &other)=delete
any_event_handler & operator=(any_event_handler const &other)=delete
any_event_handler() noexcept
Definition any_event_handler.hpp:34
any_event_handler(std::pmr::memory_resource *memres, Args &&...args)
Definition any_event_handler.hpp:42
auto stop() -> void
Definition any_event_handler.hpp:139
any_event_handler & operator=(any_event_handler &&other) noexcept
Definition any_event_handler.hpp:88
~any_event_handler()
Definition any_event_handler.hpp:102
friend event_handler_ref
Definition any_event_handler.hpp:32
auto ref() noexcept -> void
Definition any_event_handler.hpp:121
auto valid() const noexcept -> bool
Definition any_event_handler.hpp:107
Type-erased reference to any event handler.
Definition event_handler_ref.hpp:34