From 5b29b09cd910fce45575bc16533b0fc873dd0062 Mon Sep 17 00:00:00 2001 From: Martin Hierholzer <martin.hierholzer@desy.de> Date: Tue, 29 Nov 2016 10:55:31 +0100 Subject: [PATCH] changed the internal thread implementation to boost::thread and make use of the interruption points to properly terminate the application --- include/FanOut.h | 23 +++++++++++++---------- include/ImplementationAdapter.h | 17 ++++++++++++++--- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/include/FanOut.h b/include/FanOut.h index e1dd6701..189b3ed5 100644 --- a/include/FanOut.h +++ b/include/FanOut.h @@ -95,12 +95,12 @@ namespace ChimeraTK { void activate() { assert(_direction == VariableDirection::consuming); assert(!_thread.joinable()); - _thread = std::thread([this] { this->run(); }); + _thread = boost::thread([this] { this->run(); }); } void deactivate() { if(_thread.joinable()) { - requestTerminateThread = true; + _thread.interrupt(); _thread.join(); } assert(!_thread.joinable()); @@ -110,12 +110,14 @@ namespace ChimeraTK { void run() { assert(_direction == VariableDirection::consuming); while(true) { + boost::this_thread::yield(); + boost::this_thread::interruption_point(); if(hasExternalTrigger) { // wait for external trigger (if present) /// @todo TODO replace with proper blocking implementation when supported by the CSA while(externalTrigger->readNonBlocking() == false) { - if(requestTerminateThread) return; - std::this_thread::yield(); + boost::this_thread::yield(); + boost::this_thread::interruption_point(); } // receive data impl->readNonBlocking(); @@ -123,15 +125,19 @@ namespace ChimeraTK { else { // receive data while(impl->readNonBlocking() == false) { - if(requestTerminateThread) return; - std::this_thread::yield(); + boost::this_thread::yield(); + boost::this_thread::interruption_point(); } } + boost::this_thread::yield(); + boost::this_thread::interruption_point(); for(auto &slave : slaves) { // send out copies to slaves // do not send copy if no data is expected (e.g. trigger) if(slave->getNumberOfSamples() != 0) { slave->accessChannel(0) = impl->accessChannel(0); } + boost::this_thread::yield(); + boost::this_thread::interruption_point(); slave->write(); } } @@ -231,10 +237,7 @@ namespace ChimeraTK { boost::shared_ptr<mtca4u::TransferElement> externalTrigger; /** Thread handling the synchronisation, if needed */ - std::thread _thread; - - /** Flag to request termination of the synchronisation thread. */ - bool requestTerminateThread{false}; + boost::thread _thread; }; diff --git a/include/ImplementationAdapter.h b/include/ImplementationAdapter.h index a551025a..be78ad86 100644 --- a/include/ImplementationAdapter.h +++ b/include/ImplementationAdapter.h @@ -43,7 +43,7 @@ namespace ChimeraTK { _sender = boost::dynamic_pointer_cast<mtca4u::NDRegisterAccessor<UserType>>(sender); _receiver = boost::dynamic_pointer_cast<mtca4u::NDRegisterAccessor<UserType>>(receiver); assert(_sender && _receiver); - _thread = std::thread([this] { this->run(); }); + _thread = boost::thread([this] { this->run(); }); } protected: @@ -51,18 +51,29 @@ namespace ChimeraTK { /** Synchronise sender and receiver. This function is executed in the separate thread. */ void run() { while(true) { - while(!_receiver->readNonBlocking()) std::this_thread::yield(); + while(!_receiver->readNonBlocking()) { + boost::this_thread::yield(); + boost::this_thread::interruption_point(); + } _sender->accessChannel(0) = _receiver->accessChannel(0); _sender->write(); } } + void deactivate() { + if(_thread.joinable()) { + _thread.interrupt(); + _thread.join(); + } + assert(!_thread.joinable()); + } + /** Sender and receiver process variables */ boost::shared_ptr<mtca4u::NDRegisterAccessor<UserType>> _sender; boost::shared_ptr<mtca4u::NDRegisterAccessor<UserType>> _receiver; /** Thread handling the synchronisation */ - std::thread _thread; + boost::thread _thread; }; -- GitLab