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