mirror of
https://github.com/matrix-construct/construct
synced 2024-12-26 15:33:54 +01:00
ircd::ios: Add asio handler hook framework.
This commit is contained in:
parent
3bc716e0f5
commit
d5397c599f
2 changed files with 156 additions and 2 deletions
|
@ -20,6 +20,9 @@ namespace boost::asio
|
|||
{
|
||||
struct io_context;
|
||||
struct signal_set;
|
||||
|
||||
template<class function>
|
||||
void asio_handler_invoke(function&, ...);
|
||||
}
|
||||
|
||||
namespace ircd
|
||||
|
@ -32,6 +35,10 @@ namespace ircd
|
|||
|
||||
namespace ircd::ios
|
||||
{
|
||||
struct handler;
|
||||
struct descriptor;
|
||||
template<class function> struct handle;
|
||||
|
||||
extern const std::thread::id static_thread_id;
|
||||
extern std::thread::id main_thread_id;
|
||||
extern asio::io_context *user;
|
||||
|
@ -43,9 +50,10 @@ namespace ircd::ios
|
|||
bool available();
|
||||
asio::io_context &get();
|
||||
|
||||
void dispatch(descriptor &, std::function<void ()>);
|
||||
void post(descriptor &, std::function<void ()>);
|
||||
void dispatch(std::function<void ()>);
|
||||
void post(std::function<void ()>);
|
||||
|
||||
void init(asio::io_context &user);
|
||||
}
|
||||
|
||||
|
@ -53,11 +61,89 @@ namespace ircd
|
|||
{
|
||||
using ios::assert_main_thread;
|
||||
using ios::is_main_thread;
|
||||
|
||||
using ios::dispatch;
|
||||
using ios::post;
|
||||
}
|
||||
|
||||
struct ircd::ios::descriptor
|
||||
:instance_list<descriptor>
|
||||
{
|
||||
static uint64_t ids;
|
||||
|
||||
string_view name;
|
||||
uint64_t id {++ids};
|
||||
uint64_t calls {0};
|
||||
uint64_t faults {0};
|
||||
|
||||
descriptor(const string_view &name);
|
||||
descriptor(descriptor &&) = delete;
|
||||
descriptor(const descriptor &) = delete;
|
||||
~descriptor() noexcept;
|
||||
};
|
||||
|
||||
struct ircd::ios::handler
|
||||
{
|
||||
static void enter(handler *const &);
|
||||
static void leave(handler *const &);
|
||||
static bool fault(handler *const &);
|
||||
|
||||
ios::descriptor *descriptor;
|
||||
};
|
||||
|
||||
template<class function>
|
||||
struct ircd::ios::handle
|
||||
:handler
|
||||
{
|
||||
function f;
|
||||
|
||||
template<class... args>
|
||||
void operator()(args&&... a) const;
|
||||
|
||||
handle(ios::descriptor &d, function&& f);
|
||||
};
|
||||
|
||||
namespace ircd::ios
|
||||
{
|
||||
template<class callable,
|
||||
class function>
|
||||
void asio_handler_invoke(callable &f, handle<function> *);
|
||||
}
|
||||
|
||||
template<class function>
|
||||
ircd::ios::handle<function>::handle(ios::descriptor &d,
|
||||
function&& f)
|
||||
:handler{&d}
|
||||
,f{std::forward<function>(f)}
|
||||
{}
|
||||
|
||||
template<class function>
|
||||
template<class... args>
|
||||
void
|
||||
ircd::ios::handle<function>::operator()(args&&... a)
|
||||
const
|
||||
{
|
||||
f(std::forward<args>(a)...);
|
||||
}
|
||||
|
||||
template<class callable,
|
||||
class function>
|
||||
void
|
||||
ircd::ios::asio_handler_invoke(callable &f,
|
||||
handle<function> *const h)
|
||||
try
|
||||
{
|
||||
handler::enter(h);
|
||||
boost::asio::asio_handler_invoke(f, &h);
|
||||
handler::leave(h);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
if(handler::fault(h))
|
||||
handler::leave(h);
|
||||
else
|
||||
throw;
|
||||
}
|
||||
|
||||
inline void
|
||||
ircd::ios::assert_main_thread()
|
||||
{
|
||||
|
|
68
ircd/ios.cc
68
ircd/ios.cc
|
@ -71,6 +71,20 @@ ircd::ios::dispatch(std::function<void ()> function)
|
|||
boost::asio::dispatch(get(), std::move(function));
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ios::post(descriptor &descriptor,
|
||||
std::function<void ()> function)
|
||||
{
|
||||
boost::asio::post(get(), handle(descriptor, std::move(function)));
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ios::dispatch(descriptor &descriptor,
|
||||
std::function<void ()> function)
|
||||
{
|
||||
boost::asio::dispatch(get(), handle(descriptor, std::move(function)));
|
||||
}
|
||||
|
||||
boost::asio::io_context &
|
||||
ircd::ios::get()
|
||||
{
|
||||
|
@ -83,3 +97,57 @@ ircd::ios::available()
|
|||
{
|
||||
return bool(user);
|
||||
}
|
||||
|
||||
//
|
||||
// descriptor
|
||||
//
|
||||
|
||||
template<>
|
||||
decltype(ircd::util::instance_list<ircd::ios::descriptor>::list)
|
||||
ircd::util::instance_list<ircd::ios::descriptor>::list
|
||||
{};
|
||||
|
||||
decltype(ircd::ios::descriptor::ids)
|
||||
ircd::ios::descriptor::ids;
|
||||
|
||||
//
|
||||
// descriptor::descriptor
|
||||
//
|
||||
|
||||
ircd::ios::descriptor::descriptor(const string_view &name)
|
||||
:name{name}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::ios::descriptor::~descriptor()
|
||||
noexcept
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// handler
|
||||
//
|
||||
|
||||
bool
|
||||
ircd::ios::handler::fault(handler *const &handler)
|
||||
{
|
||||
assert(handler && handler->descriptor);
|
||||
auto &descriptor(*handler->descriptor);
|
||||
++descriptor.faults;
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ios::handler::leave(handler *const &handler)
|
||||
{
|
||||
assert(handler && handler->descriptor);
|
||||
auto &descriptor(*handler->descriptor);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::ios::handler::enter(handler *const &handler)
|
||||
{
|
||||
assert(handler && handler->descriptor);
|
||||
auto &descriptor(*handler->descriptor);
|
||||
++descriptor.calls;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue