39 requires(!std::same_as<HandlerTy, any_event_handler> &&
40 !std::same_as<HandlerTy, event_handler_ref> &&
41 std::constructible_from<HandlerTy, Args...>)
43 : m_vtable(make_vtable<HandlerTy>()), m_memres(memres),
44 m_storage(construct_storage<HandlerTy>(m_memres, std::forward<Args>(args)...))
49 requires(!std::same_as<HandlerTy, any_event_handler> &&
50 !std::same_as<HandlerTy, event_handler_ref> &&
51 std::constructible_from<HandlerTy, 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)...))
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)
66 m_storage = construct_storage<HandlerTy>(m_memres, std::forward<Args>(args)...);
67 m_vtable = make_vtable<HandlerTy>();
71 requires(!std::same_as<HandlerTy, any_event_handler> &&
72 !std::same_as<HandlerTy, event_handler_ref> &&
73 std::constructible_from<HandlerTy, Args...>)
76 emplace<HandlerTy>(m_memres, std::forward<Args>(args)...);
83 : m_vtable(other.m_vtable), m_memres(other.m_memres), m_storage(other.m_storage)
85 other.m_storage =
nullptr;
95 m_vtable = other.m_vtable;
96 m_memres = other.m_memres;
97 m_storage = other.m_storage;
98 other.m_storage =
nullptr;
107 auto valid () const noexcept ->
bool
112 auto start (libusb_context *usb_ctx, std::stop_token
stop) ->
bool
118 return m_vtable.start_fn(m_storage, usb_ctx, std::move(
stop));
121 auto ref () noexcept ->
void
127 return m_vtable.ref_fn(m_storage);
136 return m_vtable.unref_fn(m_storage);
145 return m_vtable.stop_fn(m_storage);
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;
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};
166 template <detail::EventHandler HandlerTy,
typename... Args>
167 auto construct_storage (std::pmr::memory_resource *memres, Args &&...args) ->
void *
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);
175 new (ptr) handler_t(std::forward<Args>(args)...);
179 memres->deallocate(ptr, size, align);
185 template <detail::EventHandler HandlerTy>
static auto make_vtable () -> 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),
202 auto destroy () ->
void
206 m_vtable.dtor_fn(m_storage);
207 m_memres->deallocate(m_storage, m_vtable.size, m_vtable.align);
212 std::pmr::memory_resource *m_memres = std::pmr::get_default_resource();
213 void *m_storage{
nullptr};