Converting thread entrypoint from lamda to nano::thread_runner::run. (#4147)
This commit is contained in:
parent
59b9c38f1e
commit
430346c0ff
2 changed files with 42 additions and 36 deletions
|
|
@ -142,56 +142,34 @@ void nano::thread_attributes::set (boost::thread::attributes & attrs)
|
||||||
attrs_l->set_stack_size (8000000); // 8MB
|
attrs_l->set_stack_size (8000000); // 8MB
|
||||||
}
|
}
|
||||||
|
|
||||||
nano::thread_runner::thread_runner (boost::asio::io_context & io_ctx_a, unsigned service_threads_a) :
|
nano::thread_runner::thread_runner (boost::asio::io_context & io_ctx_a, unsigned num_threads) :
|
||||||
io_guard (boost::asio::make_work_guard (io_ctx_a))
|
io_guard (boost::asio::make_work_guard (io_ctx_a))
|
||||||
{
|
{
|
||||||
boost::thread::attributes attrs;
|
boost::thread::attributes attrs;
|
||||||
nano::thread_attributes::set (attrs);
|
nano::thread_attributes::set (attrs);
|
||||||
for (auto i (0u); i < service_threads_a; ++i)
|
for (auto i (0u); i < num_threads; ++i)
|
||||||
{
|
{
|
||||||
threads.emplace_back (attrs, [&io_ctx_a] () {
|
threads.emplace_back (attrs, [this, &io_ctx_a] () {
|
||||||
nano::thread_role::set (nano::thread_role::name::io);
|
nano::thread_role::set (nano::thread_role::name::io);
|
||||||
|
|
||||||
|
// In a release build, catch and swallow any exceptions,
|
||||||
|
// In debug mode let if fall through
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
run (io_ctx_a);
|
||||||
|
#else
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
#if NANO_ASIO_HANDLER_TRACKING == 0
|
run (io_ctx_a);
|
||||||
io_ctx_a.run ();
|
|
||||||
#else
|
|
||||||
nano::timer<> timer;
|
|
||||||
timer.start ();
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
timer.restart ();
|
|
||||||
// Run at most 1 completion handler and record the time it took to complete (non-blocking)
|
|
||||||
auto count = io_ctx_a.poll_one ();
|
|
||||||
if (count == 1 && timer.since_start ().count () >= NANO_ASIO_HANDLER_TRACKING)
|
|
||||||
{
|
|
||||||
auto timestamp = std::chrono::duration_cast<std::chrono::microseconds> (std::chrono::system_clock::now ().time_since_epoch ()).count ();
|
|
||||||
std::cout << (boost::format ("[%1%] io_thread held for %2%ms") % timestamp % timer.since_start ().count ()).str () << std::endl;
|
|
||||||
}
|
|
||||||
// Sleep for a bit to give more time slices to other threads
|
|
||||||
std::this_thread::sleep_for (std::chrono::milliseconds (5));
|
|
||||||
std::this_thread::yield ();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
catch (std::exception const & ex)
|
catch (std::exception const & ex)
|
||||||
{
|
{
|
||||||
std::cerr << ex.what () << std::endl;
|
std::cerr << ex.what () << std::endl;
|
||||||
#ifndef NDEBUG
|
|
||||||
throw;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
|
||||||
/*
|
|
||||||
* In a release build, catch and swallow the
|
|
||||||
* io_context exception, in debug mode pass it
|
|
||||||
* on
|
|
||||||
*/
|
|
||||||
throw;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -201,6 +179,30 @@ nano::thread_runner::~thread_runner ()
|
||||||
join ();
|
join ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void nano::thread_runner::run (boost::asio::io_context & io_ctx_a)
|
||||||
|
{
|
||||||
|
#if NANO_ASIO_HANDLER_TRACKING == 0
|
||||||
|
io_ctx_a.run ();
|
||||||
|
#else
|
||||||
|
nano::timer<> timer;
|
||||||
|
timer.start ();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
timer.restart ();
|
||||||
|
// Run at most 1 completion handler and record the time it took to complete (non-blocking)
|
||||||
|
auto count = io_ctx_a.poll_one ();
|
||||||
|
if (count == 1 && timer.since_start ().count () >= NANO_ASIO_HANDLER_TRACKING)
|
||||||
|
{
|
||||||
|
auto timestamp = std::chrono::duration_cast<std::chrono::microseconds> (std::chrono::system_clock::now ().time_since_epoch ()).count ();
|
||||||
|
std::cout << (boost::format ("[%1%] io_thread held for %2%ms") % timestamp % timer.since_start ().count ()).str () << std::endl;
|
||||||
|
}
|
||||||
|
// Sleep for a bit to give more time slices to other threads
|
||||||
|
std::this_thread::sleep_for (std::chrono::milliseconds (5));
|
||||||
|
std::this_thread::yield ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void nano::thread_runner::join ()
|
void nano::thread_runner::join ()
|
||||||
{
|
{
|
||||||
io_guard.reset ();
|
io_guard.reset ();
|
||||||
|
|
|
||||||
|
|
@ -80,14 +80,18 @@ namespace thread_attributes
|
||||||
class thread_runner final
|
class thread_runner final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
thread_runner (boost::asio::io_context &, unsigned);
|
thread_runner (boost::asio::io_context &, unsigned num_threads);
|
||||||
~thread_runner ();
|
~thread_runner ();
|
||||||
|
|
||||||
/** Tells the IO context to stop processing events.*/
|
/** Tells the IO context to stop processing events.*/
|
||||||
void stop_event_processing ();
|
void stop_event_processing ();
|
||||||
/** Wait for IO threads to complete */
|
/** Wait for IO threads to complete */
|
||||||
void join ();
|
void join ();
|
||||||
std::vector<boost::thread> threads;
|
std::vector<boost::thread> threads;
|
||||||
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> io_guard;
|
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> io_guard;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void run (boost::asio::io_context &);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Default memory order of normal std::atomic operations is std::memory_order_seq_cst which provides
|
/* Default memory order of normal std::atomic operations is std::memory_order_seq_cst which provides
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue