// Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BEAST_UNIT_TEST_THREAD_HPP #define BEAST_UNIT_TEST_THREAD_HPP #include #include #include #include namespace beast { namespace unit_test { /** Replacement for std::thread that handles exceptions in unit tests. */ class thread { private: suite* s_ = nullptr; std::thread t_; public: using id = std::thread::id; using native_handle_type = std::thread::native_handle_type; thread() = default; thread(thread const&) = delete; thread& operator=(thread const&) = delete; thread(thread&& other) : s_(other.s_), t_(std::move(other.t_)) { } thread& operator=(thread&& other) { s_ = other.s_; t_ = std::move(other.t_); return *this; } template explicit thread(suite& s, F&& f, Args&&... args) : s_(&s) { std::function b = std::bind(std::forward(f), std::forward(args)...); t_ = std::thread(&thread::run, this, std::move(b)); } bool joinable() const { return t_.joinable(); } std::thread::id get_id() const { return t_.get_id(); } static unsigned hardware_concurrency() noexcept { return std::thread::hardware_concurrency(); } void join() { t_.join(); s_->propagate_abort(); } void detach() { t_.detach(); } void swap(thread& other) { std::swap(s_, other.s_); std::swap(t_, other.t_); } private: void run(std::function f) { try { f(); } catch (suite::abort_exception const&) { } catch (std::exception const& e) { s_->fail("unhandled exception: " + std::string(e.what())); } catch (...) { s_->fail("unhandled exception"); } } }; } // namespace unit_test } // namespace beast #endif