return m_IoService;
}
-IoEngine::IoEngine() : m_IoService(), m_KeepAlive(m_IoService), m_AlreadyExpiredTimer(m_IoService)
+IoEngine::IoEngine() : m_IoService(), m_KeepAlive(m_IoService), m_Threads(decltype(m_Threads)::size_type(std::thread::hardware_concurrency())), m_AlreadyExpiredTimer(m_IoService)
{
m_AlreadyExpiredTimer.expires_at(boost::posix_time::neg_infin);
m_CpuBoundSemaphore.store(concurrency - 1u);
}
- for (auto i (std::thread::hardware_concurrency()); i; --i) {
- std::thread(&IoEngine::RunEventLoop, this).detach();
+ for (auto& thread : m_Threads) {
+ thread = std::thread(&IoEngine::RunEventLoop, this);
+ }
+}
+
+IoEngine::~IoEngine()
+{
+ for (auto& thread : m_Threads) {
+ m_IoService.post([]() {
+ throw TerminateIoThread();
+ });
+ }
+
+ for (auto& thread : m_Threads) {
+ thread.join();
}
}
try {
m_IoService.run();
+ break;
+ } catch (const TerminateIoThread&) {
break;
} catch (const std::exception& e) {
Log(LogCritical, "IoEngine", "Exception during I/O operation!");
#include "base/lazy-init.hpp"
#include <atomic>
+#include <exception>
#include <memory>
+#include <thread>
+#include <vector>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/spawn.hpp>
IoEngine(IoEngine&&) = delete;
IoEngine& operator=(const IoEngine&) = delete;
IoEngine& operator=(IoEngine&&) = delete;
+ ~IoEngine();
static IoEngine& Get();
boost::asio::io_service m_IoService;
boost::asio::io_service::work m_KeepAlive;
+ std::vector<std::thread> m_Threads;
boost::asio::deadline_timer m_AlreadyExpiredTimer;
std::atomic_uint_fast32_t m_CpuBoundSemaphore;
};
+class TerminateIoThread : public std::exception
+{
+};
+
#endif /* IO_ENGINE_H */