25#ifndef MYSQL_HARNESS_NET_TS_EXECUTOR_H_
26#define MYSQL_HARNESS_NET_TS_EXECUTOR_H_
29#include <condition_variable>
39#include <unordered_map>
50template <
class CompletionToken,
class Signature>
53template <
class CompletionToken,
class Signature>
67template <
class CompletionToken,
class Signature>
68class async_completion;
70template <
class CompletionToken,
class Signature>
79 std::is_same<CompletionToken, completion_handler_type>::value,
98template <class T, class ProtoAllocator =
std::allocator<
void>>
101template <class T, class ProtoAllocator =
std::allocator<
void>>
107template <class T, class ProtoAllocator, typename =
std::void_t<>>
111 static type __get(
const T & ,
const ProtoAllocator &a)
noexcept {
116template <
class T,
class ProtoAllocator>
118 std::void_t<typename T::allocator_type>> {
119 using type =
typename T::allocator_type;
121 static type __get(
const T &t,
const ProtoAllocator & )
noexcept {
122 return t.get_allocator();
126template <
class T,
class ProtoAllocator>
128 static auto get(
const T &t,
129 const ProtoAllocator &a = ProtoAllocator()) noexcept {
131 return Impl::__get(t, a);
141template <
class T,
class ProtoAllocator>
143 const T &t,
const ProtoAllocator &a)
noexcept {
150 using std::logic_error::logic_error;
184 template <
class Service>
186 delete static_cast<Service *
>(svc);
190 template <
class Service>
206 return std::type_index(
typeid(
Key));
214 std::unordered_map<service_key_type, service *>
keys_;
216 template <
typename Service,
class... Args>
219 ServicePtr{
new Service{*
this, std::forward<Args>(args)...}});
224 template <
class Service>
227 template <
class Service>
230 template <
class Service,
class... Args>
235template <
class Service>
239 static_assert(std::is_base_of<execution_context::service, Key>::value,
240 "Key must derive from execution_context::service");
241 static_assert(std::is_base_of<Key, Service>::value,
242 "Service must derive from Key");
244 auto key = execution_context::service_key<Key>();
249 if (svc ==
nullptr) {
254 return static_cast<Key &
>(*svc);
257template <
class Service,
class... Args>
261 static_assert(std::is_base_of<execution_context::service, Key>::value,
262 "Key must derive from execution_context::service");
263 static_assert(std::is_base_of<Key, Service>::value,
264 "Service must derive from Key");
266 auto key = execution_context::service_key<Key>();
270 if (svc ==
nullptr) {
272 svc = ctx.
add_service<Service>(std::forward(args)...);
275 "can't make_service(), Service already exists");
278 return static_cast<Service &
>(*svc);
281template <
class Service>
285 std::lock_guard<std::mutex> lk(ctx.services_mtx_);
286 return ctx.keys_.count(execution_context::service_key<Key>()) > 0;
310template <
class T,
class = std::
void_t<>>
328template <
class T,
typename U = std::remove_const_t<T>>
330 void (*f)() =
nullptr,
331 const std::allocator<int> &a = {})
334 std::is_copy_constructible<T>,
336 std::is_same<
decltype(*__const_x == *__const_x),
bool>,
337 std::is_same<
decltype(*__const_x != *__const_x),
bool>,
338 std::is_void<
decltype(__x->on_work_started())>,
339 std::is_void<
decltype(__x->on_work_finished())>,
340 std::is_void<
decltype(__x->dispatch(std::move(f), a))>,
341 std::is_void<
decltype(__x->post(std::move(f), a))>,
342 std::is_void<
decltype(__x->defer(std::move(f), a))>>::value,
345 std::void_t<
decltype(__x->context()),
void()>>;
366template <
class T,
class Executor,
typename = std::
void_t<>>
369template <
class T,
class Executor>
371 : std::is_convertible<Executor, typename T::executor_type> {};
375template <
class T,
class Executor>
378template <
class T,
class Executor>
382template <
class T,
class Executor,
typename = std::
void_t<>>
386 static type __get(
const T & ,
const Executor &ex)
noexcept {
391template <
class T,
class Executor>
393 std::void_t<typename T::executor_type>> {
394 using type =
typename T::executor_type;
396 static type __get(
const T &t,
const Executor & )
noexcept {
397 return t.get_executor();
401template <
class T,
class Executor = system_executor>
402struct associated_executor;
404template <
class T,
class Executor = system_executor>
407template <
class T,
class Executor>
409 static auto get(
const T &t,
const Executor &ex = Executor()) noexcept {
411 return Impl::__get(t, ex);
419template <
class T,
class Executor>
421 const T &t,
const Executor &ex)
noexcept;
423template <
class T,
class ExecutorContext>
424associated_executor_t<T, typename ExecutorContext::executor_type>
432template <
class T,
class Executor>
434 const T &t,
const Executor &ex)
noexcept {
438template <
class T,
class ExecutorContext>
439associated_executor_t<T, typename ExecutorContext::executor_type>
450template <
class Executor>
457 ex_.on_work_started();
460 :
ex_{other.ex_},
owns_{other.owns_} {
462 ex_.on_work_started();
466 :
ex_{std::move(other.ex_)},
owns_{std::exchange(other.owns_,
false)} {}
472 ex_.on_work_finished();
482 ex_.on_work_finished();
504template <
class Executor>
510template <
class ExecutionContext>
512 std::is_convertible<ExecutionContext &, execution_context &>::value,
513 executor_work_guard<typename ExecutionContext::executor_type>>
519std::enable_if_t<!is_executor<T>::value &&
520 !std::is_convertible<T &, execution_context &>::value,
521 executor_work_guard<associated_executor_t<T>>>
526template <
class T,
class U>
529 std::forward<U>(u)))) {
545 template <
class Func,
class ProtoAllocator>
546 void dispatch(Func &&f,
const ProtoAllocator &a)
const;
547 template <
class Func,
class ProtoAllocator>
548 void post(Func &&f,
const ProtoAllocator &a)
const;
549 template <
class Func,
class ProtoAllocator>
550 void defer(Func &&f,
const ProtoAllocator &a)
const;
581 std::lock_guard<std::mutex> lk(
mtx_);
587 std::lock_guard<std::mutex> lk(
mtx_);
602 std::function<void()> f;
604 std::unique_lock<std::mutex> lk(
mtx_);
610 f = std::move(
tasks_.front());
617 void post_(std::function<
void()> f) {
618 std::lock_guard<std::mutex> lk(
mtx_);
625 tasks_.push(std::move(f));
637 std::condition_variable
cv_;
648template <
class Func,
class ProtoAllocator>
653template <
class Func,
class ProtoAllocator>
655 std::decay_t<Func>{std::forward<Func>(f)}();
657template <
class Func,
class ProtoAllocator>
659 post(std::forward<Func>(f), a);
671template <
class CompletionHandler>
691template <
class CompletionHandler>
699template <
class CompletionToken>
713template <
class Executor,
class CompletionToken>
715 is_executor<Executor>::value,
716 typename async_result<std::decay_t<CompletionToken>, void()>::return_type>
717dispatch(
const Executor &ex, CompletionToken &&token) {
730template <
class ExecutionContext,
class CompletionToken>
732 std::is_convertible<ExecutionContext &, execution_context &>::value,
733 typename async_result<std::decay_t<CompletionToken>, void()>::return_type>
736 std::forward<CompletionToken>(token));
744template <
class CompletionToken>
745auto post(CompletionToken &&token) {
758template <
class Executor,
class CompletionToken>
760 is_executor<Executor>::value,
761 typename async_result<std::decay_t<CompletionToken>, void()>::return_type>
762post(
const Executor &ex, CompletionToken &&token) {
775template <
class ExecutionContext,
class CompletionToken>
777 std::is_convertible<ExecutionContext &, execution_context &>::value,
778 typename async_result<std::decay_t<CompletionToken>, void()>::return_type>
780 return net::post(ctx.get_executor(), std::forward<CompletionToken>(token));
785template <
class CompletionToken>
786auto defer(CompletionToken &&token) {
799template <
class Executor,
class CompletionToken>
801 is_executor<Executor>::value,
802 typename async_result<std::decay_t<CompletionToken>, void()>::return_type>
803defer(
const Executor &ex, CompletionToken &&token) {
816template <
class ExecutionContext,
class CompletionToken>
818 std::is_convertible<ExecutionContext &, execution_context &>::value,
819 typename async_result<std::decay_t<CompletionToken>, void()>::return_type>
821 return net::defer(ctx.get_executor(), std::forward<CompletionToken>(token));
826template <
class Executor>
835 template <
class ProtoAllocator>
836 strand(std::allocator_arg_t,
const ProtoAllocator & , Executor ex)
842 template <
class OtherExecutor>
845 template <
class OtherExecutor>
847 :
inner_ex_{std::move(other.inner_ex_)} {}
861 template <
class OtherExecutor>
868 template <
class OtherExecutor>
890 template <
class Func,
class ProtoAllocator>
891 void dispatch(Func &&f,
const ProtoAllocator & )
const {
893 std::forward<Func>(f)();
896 template <
class Func,
class ProtoAllocator>
897 void post(Func &&f,
const ProtoAllocator &a)
const;
898 template <
class Func,
class ProtoAllocator>
899 void defer(Func &&f,
const ProtoAllocator &a)
const;
908template <
class Executor>
911template <
class Executor>
925 [e](
auto &svc) { svc.ptr_->notify_fork(e); });
928 [e](
auto &svc) { svc.ptr_->notify_fork(e); });
937 svc.ptr_->shutdown();
execution context for SQL.
Definition: sql_exec_context.h:42
The handler class is the interface for dynamically loadable storage engines.
Definition: handler.h:4501
Definition: executor.h:71
std::conditional_t< std::is_same< CompletionToken, completion_handler_type >::value, completion_handler_type &, completion_handler_type > handler_type
Definition: executor.h:80
async_completion & operator=(const async_completion &)=delete
handler_type completion_handler
Definition: executor.h:89
async_completion(CompletionToken &t)
Definition: executor.h:83
async_completion(const async_completion &)=delete
result_type result
Definition: executor.h:90
typename result_type::completion_handler_type completion_handler_type
Definition: executor.h:75
Definition: executor.h:54
void return_type
Definition: executor.h:57
CompletionToken completion_handler_type
Definition: executor.h:56
return_type get()
Definition: executor.h:63
async_result(const async_result &)=delete
async_result(completion_handler_type &)
Definition: executor.h:59
async_result & operator=(const async_result &)=delete
Definition: executor.h:290
virtual ~service()=default
virtual void shutdown() noexcept=0
service(const service &)=delete
service & operator=(const service &)=delete
service(execution_context &owner)
Definition: executor.h:292
execution_context & context_
Definition: executor.h:303
virtual void notify_fork(fork_event) noexcept
Definition: executor.h:300
execution_context & context() noexcept
Definition: executor.h:296
Definition: executor.h:153
friend bool has_service(const execution_context &ctx) noexcept
Definition: executor.h:282
std::list< ServicePtr > services_
Definition: executor.h:213
execution_context(const execution_context &)=delete
void shutdown() noexcept
Definition: executor.h:933
void destroy() noexcept
Definition: executor.h:175
static void service_deleter(service *svc)
Definition: executor.h:185
friend Service & make_service(execution_context &ctx, Args &&... args)
Definition: executor.h:258
void notify_fork(fork_event e)
Definition: executor.h:921
service * add_service(Args &&... args)
Definition: executor.h:217
execution_context()=default
execution_context & operator=(const execution_context &)=delete
virtual ~execution_context()
Definition: executor.h:163
static service_key_type service_key()
maps selected type to unique identifier.
Definition: executor.h:205
std::mutex services_mtx_
Definition: executor.h:210
friend Service::key_type & use_service(execution_context &ctx)
Definition: executor.h:236
std::type_index service_key_type
Definition: executor.h:199
std::unordered_map< service_key_type, service * > keys_
Definition: executor.h:214
Definition: executor.h:451
Executor executor_type
Definition: executor.h:453
executor_work_guard(const executor_work_guard &other) noexcept
Definition: executor.h:459
bool owns_
Definition: executor.h:489
executor_type get_executor() const noexcept
Definition: executor.h:476
executor_work_guard(executor_work_guard &&other) noexcept
Definition: executor.h:465
void reset() noexcept
Definition: executor.h:480
Executor ex_
Definition: executor.h:488
executor_work_guard(const executor_type &ex) noexcept
Definition: executor.h:455
executor_work_guard & operator=(const executor_work_guard &other)=delete
~executor_work_guard()
Definition: executor.h:470
bool owns_work() const noexcept
Definition: executor.h:478
static constexpr Value * contains(const Key *k)
check if a callstack contains a pointer already.
Definition: callstack.h:150
function object for net::dispatch(), net::post(), net::defer().
Definition: executor.h:672
Dispatcher(CompletionHandler &handler)
Definition: executor.h:674
decltype(net::make_work_guard(handler_)) work_guard_
Definition: executor.h:688
CompletionHandler handler_
Definition: executor.h:687
void operator()()
Definition: executor.h:678
Definition: executor.h:148
Definition: executor.h:827
void post(Func &&f, const ProtoAllocator &a) const
strand(Executor ex)
Definition: executor.h:833
strand operator=(const strand< OtherExecutor > &other) noexcept
Definition: executor.h:862
strand(strand< OtherExecutor > &&other) noexcept
Definition: executor.h:846
strand(const strand< OtherExecutor > &other) noexcept
Definition: executor.h:843
Executor inner_ex_
Definition: executor.h:902
bool running_in_this_thread() const noexcept
Definition: executor.h:881
void defer(Func &&f, const ProtoAllocator &a) const
strand operator=(strand< OtherExecutor > &&other) noexcept
Definition: executor.h:869
strand operator=(strand &&other) noexcept
Definition: executor.h:855
void on_work_started() const noexcept
Definition: executor.h:887
void on_work_finished() const noexcept
Definition: executor.h:888
void dispatch(Func &&f, const ProtoAllocator &) const
Definition: executor.h:891
execution_context & context() const noexcept
Definition: executor.h:885
Executor inner_executor_type
Definition: executor.h:829
strand(strand &&other) noexcept
Definition: executor.h:840
strand operator=(const strand &other) noexcept
Definition: executor.h:849
std::queue< std::function< void()> > jobs_
Definition: executor.h:905
strand(std::allocator_arg_t, const ProtoAllocator &, Executor ex)
Definition: executor.h:836
strand(const strand &other) noexcept
Definition: executor.h:839
inner_executor_type get_inner_executor() const noexcept
Definition: executor.h:879
bool running_
Definition: executor.h:904
Definition: executor.h:566
static system_context & get_() noexcept
Definition: executor.h:630
bool stopped_
Definition: executor.h:639
void join()
Definition: executor.h:590
std::condition_variable cv_
Definition: executor.h:637
std::queue< std::function< void()> > tasks_
Definition: executor.h:638
void run_()
Definition: executor.h:600
std::thread thread_
Definition: executor.h:635
system_context(const system_context &)=delete
bool stopped() const noexcept
Definition: executor.h:586
~system_context() override
Definition: executor.h:573
void post_(std::function< void()> f)
Definition: executor.h:617
std::mutex mtx_
Definition: executor.h:636
friend class system_executor
Definition: executor.h:598
executor_type get_executor() noexcept
Definition: executor.h:578
system_context & operator=(const system_context &)=delete
void stop()
Definition: executor.h:580
system_context(__tag)
Definition: executor.h:596
Definition: executor.h:536
system_executor()=default
void dispatch(Func &&f, const ProtoAllocator &a) const
Definition: executor.h:654
void defer(Func &&f, const ProtoAllocator &a) const
Definition: executor.h:658
void on_work_finished() const noexcept
Definition: executor.h:543
system_context & context() const noexcept
Definition: executor.h:644
void on_work_started() const noexcept
Definition: executor.h:542
void post(Func &&f, const ProtoAllocator &a) const
Definition: executor.h:649
Header for compiler-dependent features.
#define MY_COMPILER_DIAGNOSTIC_PUSH()
save the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:284
#define MY_COMPILER_DIAGNOSTIC_POP()
restore the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:285
static QUEUE queue
Definition: myisampack.cc:209
void for_each(const Shards< COUNT > &shards, Function &&f) noexcept
Iterate over the shards.
Definition: ut0counter.h:322
int key_type
Definition: http_request.h:49
std::string_view Key
The key type for the hash structure in HashJoinRowBuffer.
Definition: hash_join_buffer.h:107
Definition: authentication.cc:35
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:692
constexpr bool uses_executor_v
Definition: executor.h:379
bool operator!=(const system_executor &, const system_executor &)
Definition: executor.h:558
bool has_service(const execution_context &ctx) noexcept
Definition: executor.h:282
Service & make_service(execution_context &ctx, Args &&... args)
Definition: executor.h:258
auto defer(CompletionToken &&token)
Definition: executor.h:786
std::enable_if_t< is_executor< Executor >::value, executor_work_guard< Executor > > make_work_guard(const Executor &ex)
Definition: executor.h:506
typename associated_executor< T, Executor >::type associated_executor_t
Definition: executor.h:405
associated_allocator_t< T > get_associated_allocator(const T &t) noexcept
Definition: executor.h:137
auto dispatch(CompletionToken &&token)
Definition: executor.h:700
auto post(CompletionToken &&token)
queue a function call for later execution.
Definition: executor.h:745
constexpr executor_arg_t executor_arg
Definition: executor.h:360
Service::key_type & use_service(execution_context &ctx)
Definition: executor.h:236
typename associated_allocator< T, ProtoAllocator >::type associated_allocator_t
Definition: executor.h:103
constexpr bool is_executor_v
Definition: executor.h:355
associated_executor_t< T > get_associated_executor(const T &t) noexcept
Definition: executor.h:428
bool operator==(const system_executor &, const system_executor &)
Definition: executor.h:554
fork_event
Definition: executor.h:47
Definition: varlen_sort.h:183
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:2437
MY_COMPILER_CLANG_DIAGNOSTIC_IGNORE("-Winconsistent-missing-destructor-override") extern "C"
Definition: protobuf_plugin.cc:31
required string key
Definition: replication_asynchronous_connection_failover.proto:59
required string type
Definition: replication_group_member_actions.proto:33
static type __get(const T &t, const ProtoAllocator &) noexcept
Definition: executor.h:121
typename T::allocator_type type
Definition: executor.h:119
Definition: executor.h:108
static type __get(const T &, const ProtoAllocator &a) noexcept
Definition: executor.h:111
ProtoAllocator type
Definition: executor.h:109
Definition: executor.h:127
static auto get(const T &t, const ProtoAllocator &a=ProtoAllocator()) noexcept
Definition: executor.h:128
static type __get(const T &t, const Executor &) noexcept
Definition: executor.h:396
typename T::executor_type type
Definition: executor.h:394
Definition: executor.h:383
static type __get(const T &, const Executor &ex) noexcept
Definition: executor.h:386
Executor type
Definition: executor.h:384
Definition: executor.h:408
static auto get(const T &t, const Executor &ex=Executor()) noexcept
Definition: executor.h:409
Definition: executor.h:189
ServicePtr(Service *svc)
Definition: executor.h:191
std::unique_ptr< service, void(*)(service *)> ptr_
Definition: executor.h:196
bool active_
Definition: executor.h:194
Definition: executor.h:358
Definition: executor.h:311
Definition: executor.h:367
Definition: executor.h:352
Definition: executor.h:595
Definition: executor.h:376