diff --git a/nano/lib/threading.cpp b/nano/lib/threading.cpp index 09724af61..9f4ba07e7 100644 --- a/nano/lib/threading.cpp +++ b/nano/lib/threading.cpp @@ -142,56 +142,34 @@ void nano::thread_attributes::set (boost::thread::attributes & attrs) 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)) { boost::thread::attributes 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); + + // In a release build, catch and swallow any exceptions, + // In debug mode let if fall through + +#ifndef NDEBUG + run (io_ctx_a); +#else try { -#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::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 + run (io_ctx_a); } catch (std::exception const & ex) { std::cerr << ex.what () << std::endl; -#ifndef NDEBUG - throw; -#endif } 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 (); } +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::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 () { io_guard.reset (); @@ -341,4 +343,4 @@ bool nano::join_or_pass (std::thread & thread) { return false; } -} \ No newline at end of file +} diff --git a/nano/lib/threading.hpp b/nano/lib/threading.hpp index 72aabd3f1..3a2351ff9 100644 --- a/nano/lib/threading.hpp +++ b/nano/lib/threading.hpp @@ -80,14 +80,18 @@ namespace thread_attributes class thread_runner final { public: - thread_runner (boost::asio::io_context &, unsigned); + thread_runner (boost::asio::io_context &, unsigned num_threads); ~thread_runner (); + /** Tells the IO context to stop processing events.*/ void stop_event_processing (); /** Wait for IO threads to complete */ void join (); std::vector threads; boost::asio::executor_work_guard 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