0
0
Fork 0
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:
Jason Volk 2019-03-26 16:53:31 -07:00
parent 3bc716e0f5
commit d5397c599f
2 changed files with 156 additions and 2 deletions

View file

@ -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()
{

View file

@ -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;
}