26#ifndef MYSQL_HARNESS_NET_TS_EXECUTOR_H_
27#define MYSQL_HARNESS_NET_TS_EXECUTOR_H_
30#include <condition_variable>
40#include <unordered_map>
51template <
class CompletionToken,
class Signature>
54template <
class CompletionToken,
class Signature>
68template <
class CompletionToken,
class Signature>
69class async_completion;
71template <
class CompletionToken,
class Signature>
80 std::is_same<CompletionToken, completion_handler_type>::value,
99template <class T, class ProtoAllocator =
std::allocator<
void>>
102template <class T, class ProtoAllocator =
std::allocator<
void>>
108template <class T, class ProtoAllocator, typename =
std::void_t<>>
112 static type __get(
const T & ,
const ProtoAllocator &a)
noexcept {
117template <
class T,
class ProtoAllocator>
119 std::void_t<typename T::allocator_type>> {
120 using type =
typename T::allocator_type;
122 static type __get(
const T &t,
const ProtoAllocator & )
noexcept {
123 return t.get_allocator();
127template <
class T,
class ProtoAllocator>
129 static auto get(
const T &t,
130 const ProtoAllocator &a = ProtoAllocator()) noexcept {
132 return Impl::__get(t, a);
142template <
class T,
class ProtoAllocator>
144 const T &t,
const ProtoAllocator &a)
noexcept {
151 using std::logic_error::logic_error;
185 template <
class Service>
187 delete static_cast<Service *
>(svc);
191 template <
class Service>
207 return std::type_index(
typeid(
Key));
215 std::unordered_map<service_key_type, service *>
keys_;
217 template <
typename Service,
class... Args>
220 ServicePtr{
new Service{*
this, std::forward<Args>(args)...}});
225 template <
class Service>
228 template <
class Service>
231 template <
class Service,
class... Args>
236template <
class Service>
240 static_assert(std::is_base_of<execution_context::service, Key>::value,
241 "Key must derive from execution_context::service");
242 static_assert(std::is_base_of<Key, Service>::value,
243 "Service must derive from Key");
245 auto key = execution_context::service_key<Key>();
250 if (svc ==
nullptr) {
255 return static_cast<Key &
>(*svc);
258template <
class Service,
class... Args>
262 static_assert(std::is_base_of<execution_context::service, Key>::value,
263 "Key must derive from execution_context::service");
264 static_assert(std::is_base_of<Key, Service>::value,
265 "Service must derive from Key");
267 auto key = execution_context::service_key<Key>();
271 if (svc ==
nullptr) {
273 svc = ctx.
add_service<Service>(std::forward(args)...);
276 "can't make_service(), Service already exists");
279 return static_cast<Service &
>(*svc);
282template <
class Service>
286 std::lock_guard<std::mutex> lk(ctx.services_mtx_);
287 return ctx.keys_.count(execution_context::service_key<Key>()) > 0;
311template <
class T,
class = std::
void_t<>>
329template <
class T,
typename U = std::remove_const_t<T>>
331 void (*f)() =
nullptr,
332 const std::allocator<int> &a = {})
335 std::is_copy_constructible<T>,
337 std::is_same<
decltype(*__const_x == *__const_x),
bool>,
338 std::is_same<
decltype(*__const_x != *__const_x),
bool>,
339 std::is_void<
decltype(__x->on_work_started())>,
340 std::is_void<
decltype(__x->on_work_finished())>,
341 std::is_void<
decltype(__x->dispatch(std::move(f), a))>,
342 std::is_void<
decltype(__x->post(std::move(f), a))>,
343 std::is_void<
decltype(__x->defer(std::move(f), a))>>::value,
346 std::void_t<
decltype(__x->context()),
void()>>;
367template <
class T,
class Executor,
typename = std::
void_t<>>
370template <
class T,
class Executor>
372 : std::is_convertible<Executor, typename T::executor_type> {};
376template <
class T,
class Executor>
379template <
class T,
class Executor>
383template <
class T,
class Executor,
typename = std::
void_t<>>
387 static type __get(
const T & ,
const Executor &ex)
noexcept {
392template <
class T,
class Executor>
394 std::void_t<typename T::executor_type>> {
395 using type =
typename T::executor_type;
397 static type __get(
const T &t,
const Executor & )
noexcept {
398 return t.get_executor();
402template <
class T,
class Executor = system_executor>
403struct associated_executor;
405template <
class T,
class Executor = system_executor>
408template <
class T,
class Executor>
410 static auto get(
const T &t,
const Executor &ex = Executor()) noexcept {
412 return Impl::__get(t, ex);
420template <
class T,
class Executor>
422 const T &t,
const Executor &ex)
noexcept;
424template <
class T,
class ExecutorContext>
425associated_executor_t<T, typename ExecutorContext::executor_type>
433template <
class T,
class Executor>
435 const T &t,
const Executor &ex)
noexcept {
439template <
class T,
class ExecutorContext>
440associated_executor_t<T, typename ExecutorContext::executor_type>
451template <
class Executor>
458 ex_.on_work_started();
461 :
ex_{other.ex_},
owns_{other.owns_} {
463 ex_.on_work_started();
467 :
ex_{std::move(other.ex_)},
owns_{std::exchange(other.owns_,
false)} {}
473 ex_.on_work_finished();
483 ex_.on_work_finished();
495template <
class Executor>
497 requires(is_executor_v<Executor>)
502template <
class ExecutionContext>
505 requires(std::is_convertible_v<ExecutionContext &, execution_context &>)
512 requires(!is_executor_v<T> &&
513 !std::is_convertible_v<T &, execution_context &>)
519template <
class T,
class U>
522 std::forward<U>(u)))) {
538 template <
class Func,
class ProtoAllocator>
539 void dispatch(Func &&f,
const ProtoAllocator &a)
const;
540 template <
class Func,
class ProtoAllocator>
541 void post(Func &&f,
const ProtoAllocator &a)
const;
542 template <
class Func,
class ProtoAllocator>
543 void defer(Func &&f,
const ProtoAllocator &a)
const;
574 std::lock_guard<std::mutex> lk(
mtx_);
580 std::lock_guard<std::mutex> lk(
mtx_);
595 std::function<void()> f;
597 std::unique_lock<std::mutex> lk(
mtx_);
603 f = std::move(
tasks_.front());
610 void post_(std::function<
void()> f) {
611 std::lock_guard<std::mutex> lk(
mtx_);
618 tasks_.push(std::move(f));
630 std::condition_variable
cv_;
641template <
class Func,
class ProtoAllocator>
646template <
class Func,
class ProtoAllocator>
648 std::decay_t<Func>{std::forward<Func>(f)}();
650template <
class Func,
class ProtoAllocator>
652 post(std::forward<Func>(f), a);
664template <
class CompletionHandler>
684template <
class CompletionHandler>
692template <
class CompletionToken>
706template <
class Executor,
class CompletionToken>
707typename async_result<std::decay_t<CompletionToken>, void()>::return_type
708dispatch(
const Executor &ex, CompletionToken &&token)
709 requires(is_executor_v<Executor>)
723template <
class ExecutionContext,
class CompletionToken>
724typename async_result<std::decay_t<CompletionToken>, void()>::return_type
726 requires(std::is_convertible_v<ExecutionContext &, execution_context &>)
729 std::forward<CompletionToken>(token));
737template <
class CompletionToken>
738auto post(CompletionToken &&token) {
751template <
class Executor,
class CompletionToken>
752typename async_result<std::decay_t<CompletionToken>, void()>::return_type
753post(
const Executor &ex, CompletionToken &&token)
754 requires(is_executor_v<Executor>)
768template <
class ExecutionContext,
class CompletionToken>
769typename async_result<std::decay_t<CompletionToken>, void()>::return_type
771 requires(std::is_convertible_v<ExecutionContext &, execution_context &>)
773 return net::post(ctx.get_executor(), std::forward<CompletionToken>(token));
778template <
class CompletionToken>
779auto defer(CompletionToken &&token) {
792template <
class Executor,
class CompletionToken>
793typename async_result<std::decay_t<CompletionToken>, void()>::return_type
794defer(
const Executor &ex, CompletionToken &&token)
795 requires(is_executor_v<Executor>)
809template <
class ExecutionContext,
class CompletionToken>
810typename async_result<std::decay_t<CompletionToken>, void()>::return_type
812 requires(std::is_convertible_v<ExecutionContext &, execution_context &>)
814 return net::defer(ctx.get_executor(), std::forward<CompletionToken>(token));
819template <
class Executor>
828 template <
class ProtoAllocator>
829 strand(std::allocator_arg_t,
const ProtoAllocator & , Executor ex)
835 template <
class OtherExecutor>
838 template <
class OtherExecutor>
840 :
inner_ex_{std::move(other.inner_ex_)} {}
854 template <
class OtherExecutor>
861 template <
class OtherExecutor>
883 template <
class Func,
class ProtoAllocator>
884 void dispatch(Func &&f,
const ProtoAllocator & )
const {
886 std::forward<Func>(f)();
889 template <
class Func,
class ProtoAllocator>
890 void post(Func &&f,
const ProtoAllocator &a)
const;
891 template <
class Func,
class ProtoAllocator>
892 void defer(Func &&f,
const ProtoAllocator &a)
const;
901template <
class Executor>
904template <
class Executor>
918 [e](
auto &svc) { svc.ptr_->notify_fork(e); });
921 [e](
auto &svc) { svc.ptr_->notify_fork(e); });
930 svc.ptr_->shutdown();
execution context for SQL.
Definition: sql_exec_context.h:39
The handler class is the interface for dynamically loadable storage engines.
Definition: handler.h:4583
Definition: executor.h:72
std::conditional_t< std::is_same< CompletionToken, completion_handler_type >::value, completion_handler_type &, completion_handler_type > handler_type
Definition: executor.h:81
async_completion & operator=(const async_completion &)=delete
handler_type completion_handler
Definition: executor.h:90
async_completion(CompletionToken &t)
Definition: executor.h:84
async_completion(const async_completion &)=delete
result_type result
Definition: executor.h:91
typename result_type::completion_handler_type completion_handler_type
Definition: executor.h:76
Definition: executor.h:55
void return_type
Definition: executor.h:58
CompletionToken completion_handler_type
Definition: executor.h:57
return_type get()
Definition: executor.h:64
async_result(const async_result &)=delete
async_result(completion_handler_type &)
Definition: executor.h:60
async_result & operator=(const async_result &)=delete
Definition: executor.h:291
virtual ~service()=default
virtual void shutdown() noexcept=0
service(const service &)=delete
service & operator=(const service &)=delete
service(execution_context &owner)
Definition: executor.h:293
execution_context & context_
Definition: executor.h:304
virtual void notify_fork(fork_event) noexcept
Definition: executor.h:301
execution_context & context() noexcept
Definition: executor.h:297
Definition: executor.h:154
friend bool has_service(const execution_context &ctx) noexcept
Definition: executor.h:283
service * add_service(Args &&...args)
Definition: executor.h:218
std::list< ServicePtr > services_
Definition: executor.h:214
execution_context(const execution_context &)=delete
void shutdown() noexcept
Definition: executor.h:926
void destroy() noexcept
Definition: executor.h:176
static void service_deleter(service *svc)
Definition: executor.h:186
friend Service & make_service(execution_context &ctx, Args &&...args)
Definition: executor.h:259
void notify_fork(fork_event e)
Definition: executor.h:914
execution_context()=default
execution_context & operator=(const execution_context &)=delete
virtual ~execution_context()
Definition: executor.h:164
static service_key_type service_key()
maps selected type to unique identifier.
Definition: executor.h:206
std::mutex services_mtx_
Definition: executor.h:211
friend Service::key_type & use_service(execution_context &ctx)
Definition: executor.h:237
std::type_index service_key_type
Definition: executor.h:200
std::unordered_map< service_key_type, service * > keys_
Definition: executor.h:215
Definition: executor.h:452
Executor executor_type
Definition: executor.h:454
executor_work_guard(const executor_work_guard &other) noexcept
Definition: executor.h:460
bool owns_
Definition: executor.h:490
executor_type get_executor() const noexcept
Definition: executor.h:477
executor_work_guard(executor_work_guard &&other) noexcept
Definition: executor.h:466
void reset() noexcept
Definition: executor.h:481
Executor ex_
Definition: executor.h:489
executor_work_guard(const executor_type &ex) noexcept
Definition: executor.h:456
executor_work_guard & operator=(const executor_work_guard &other)=delete
~executor_work_guard()
Definition: executor.h:471
bool owns_work() const noexcept
Definition: executor.h:479
static constexpr Value * contains(const Key *k)
check if a callstack contains a pointer already.
Definition: callstack.h:151
function object for net::dispatch(), net::post(), net::defer().
Definition: executor.h:665
Dispatcher(CompletionHandler &handler)
Definition: executor.h:667
decltype(net::make_work_guard(handler_)) work_guard_
Definition: executor.h:681
CompletionHandler handler_
Definition: executor.h:680
void operator()()
Definition: executor.h:671
Definition: executor.h:149
Definition: executor.h:820
void post(Func &&f, const ProtoAllocator &a) const
strand(Executor ex)
Definition: executor.h:826
strand operator=(const strand< OtherExecutor > &other) noexcept
Definition: executor.h:855
strand(strand< OtherExecutor > &&other) noexcept
Definition: executor.h:839
strand(const strand< OtherExecutor > &other) noexcept
Definition: executor.h:836
Executor inner_ex_
Definition: executor.h:895
bool running_in_this_thread() const noexcept
Definition: executor.h:874
void defer(Func &&f, const ProtoAllocator &a) const
strand operator=(strand< OtherExecutor > &&other) noexcept
Definition: executor.h:862
strand operator=(strand &&other) noexcept
Definition: executor.h:848
void on_work_started() const noexcept
Definition: executor.h:880
void on_work_finished() const noexcept
Definition: executor.h:881
void dispatch(Func &&f, const ProtoAllocator &) const
Definition: executor.h:884
execution_context & context() const noexcept
Definition: executor.h:878
Executor inner_executor_type
Definition: executor.h:822
strand(strand &&other) noexcept
Definition: executor.h:833
strand operator=(const strand &other) noexcept
Definition: executor.h:842
std::queue< std::function< void()> > jobs_
Definition: executor.h:898
strand(std::allocator_arg_t, const ProtoAllocator &, Executor ex)
Definition: executor.h:829
strand(const strand &other) noexcept
Definition: executor.h:832
inner_executor_type get_inner_executor() const noexcept
Definition: executor.h:872
bool running_
Definition: executor.h:897
Definition: executor.h:559
static system_context & get_() noexcept
Definition: executor.h:623
bool stopped_
Definition: executor.h:632
void join()
Definition: executor.h:583
std::condition_variable cv_
Definition: executor.h:630
std::queue< std::function< void()> > tasks_
Definition: executor.h:631
void run_()
Definition: executor.h:593
std::thread thread_
Definition: executor.h:628
system_context(const system_context &)=delete
bool stopped() const noexcept
Definition: executor.h:579
~system_context() override
Definition: executor.h:566
void post_(std::function< void()> f)
Definition: executor.h:610
std::mutex mtx_
Definition: executor.h:629
friend class system_executor
Definition: executor.h:591
executor_type get_executor() noexcept
Definition: executor.h:571
system_context & operator=(const system_context &)=delete
void stop()
Definition: executor.h:573
system_context(__tag)
Definition: executor.h:589
Definition: executor.h:529
system_executor()=default
void dispatch(Func &&f, const ProtoAllocator &a) const
Definition: executor.h:647
void defer(Func &&f, const ProtoAllocator &a) const
Definition: executor.h:651
void on_work_finished() const noexcept
Definition: executor.h:536
system_context & context() const noexcept
Definition: executor.h:637
void on_work_started() const noexcept
Definition: executor.h:535
void post(Func &&f, const ProtoAllocator &a) const
Definition: executor.h:642
Header for compiler-dependent features.
#define MY_COMPILER_DIAGNOSTIC_PUSH()
save the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:277
#define MY_COMPILER_DIAGNOSTIC_POP()
restore the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:278
static QUEUE queue
Definition: myisampack.cc:210
void for_each(const Shards< COUNT > &shards, Function &&f) noexcept
Iterate over the shards.
Definition: ut0counter.h:323
std::string_view Key
The key type for the hash structure in HashJoinRowBuffer.
Definition: hash_join_buffer.h:108
int key_type
Definition: method.h:38
Definition: http_server_component.cc:34
auto executor_requirements(U *__x=nullptr, const U *__const_x=nullptr, void(*f)()=nullptr, const std::allocator< int > &a={}) -> std::enable_if_t< std::conjunction< std::is_copy_constructible< T >, std::is_same< decltype(*__const_x== *__const_x), bool >, std::is_same< decltype(*__const_x != *__const_x), bool >, std::is_void< decltype(__x->on_work_started())>, std::is_void< decltype(__x->on_work_finished())>, std::is_void< decltype(__x->dispatch(std::move(f), a))>, std::is_void< decltype(__x->post(std::move(f), a))>, std::is_void< decltype(__x->defer(std::move(f), a))> >::value, std::void_t< decltype(__x->context()), void()> >
Dispatcher< CompletionHandler > make_dispatcher(CompletionHandler &handler)
Definition: executor.h:685
constexpr bool uses_executor_v
Definition: executor.h:380
bool operator!=(const system_executor &, const system_executor &)
Definition: executor.h:551
bool has_service(const execution_context &ctx) noexcept
Definition: executor.h:283
auto defer(CompletionToken &&token)
Definition: executor.h:779
typename associated_executor< T, Executor >::type associated_executor_t
Definition: executor.h:406
executor_work_guard< Executor > make_work_guard(const Executor &ex)
Definition: executor.h:496
Service & make_service(execution_context &ctx, Args &&...args)
Definition: executor.h:259
associated_allocator_t< T > get_associated_allocator(const T &t) noexcept
Definition: executor.h:138
auto dispatch(CompletionToken &&token)
Definition: executor.h:693
auto post(CompletionToken &&token)
queue a function call for later execution.
Definition: executor.h:738
constexpr executor_arg_t executor_arg
Definition: executor.h:361
Service::key_type & use_service(execution_context &ctx)
Definition: executor.h:237
typename associated_allocator< T, ProtoAllocator >::type associated_allocator_t
Definition: executor.h:104
constexpr bool is_executor_v
Definition: executor.h:356
associated_executor_t< T > get_associated_executor(const T &t) noexcept
Definition: executor.h:429
bool operator==(const system_executor &, const system_executor &)
Definition: executor.h:547
fork_event
Definition: executor.h:48
Definition: gcs_xcom_synode.h:64
std::conditional_t< !std::is_array< T >::value, std::unique_ptr< T, detail::Deleter< T > >, std::conditional_t< detail::is_unbounded_array_v< T >, std::unique_ptr< T, detail::Array_deleter< std::remove_extent_t< T > > >, void > > unique_ptr
The following is a common type that is returned by all the ut::make_unique (non-aligned) specializati...
Definition: ut0new.h:2440
MY_COMPILER_CLANG_DIAGNOSTIC_IGNORE("-Winconsistent-missing-destructor-override") static Scope_guard static_guard([]()
Definition: protobuf_plugin.cc:33
required string key
Definition: replication_asynchronous_connection_failover.proto:60
required string type
Definition: replication_group_member_actions.proto:34
static type __get(const T &t, const ProtoAllocator &) noexcept
Definition: executor.h:122
typename T::allocator_type type
Definition: executor.h:120
Definition: executor.h:109
static type __get(const T &, const ProtoAllocator &a) noexcept
Definition: executor.h:112
ProtoAllocator type
Definition: executor.h:110
Definition: executor.h:128
static auto get(const T &t, const ProtoAllocator &a=ProtoAllocator()) noexcept
Definition: executor.h:129
static type __get(const T &t, const Executor &) noexcept
Definition: executor.h:397
typename T::executor_type type
Definition: executor.h:395
Definition: executor.h:384
static type __get(const T &, const Executor &ex) noexcept
Definition: executor.h:387
Executor type
Definition: executor.h:385
Definition: executor.h:409
static auto get(const T &t, const Executor &ex=Executor()) noexcept
Definition: executor.h:410
Definition: executor.h:190
ServicePtr(Service *svc)
Definition: executor.h:192
std::unique_ptr< service, void(*)(service *)> ptr_
Definition: executor.h:197
bool active_
Definition: executor.h:195
Definition: executor.h:359
Definition: executor.h:312
Definition: executor.h:368
Definition: executor.h:353
Definition: executor.h:588
Definition: executor.h:377