From dc33baaa3f2563bd194892bc05501d04ebb1f752 Mon Sep 17 00:00:00 2001 From: Martin Killenberg <martin.killenberg@desy.de> Date: Tue, 31 Oct 2017 02:24:39 +0100 Subject: [PATCH] changed updater to run in its own thread. Tests still using doocs update, which is just doing an insanely long sleep of 1 second. --- include/CSAdapterEqFct.h | 3 ++- include/DoocsUpdater.h | 12 ++++++++---- src/CSAdapterEqFct.cc | 12 +++++++++--- src/DoocsUpdater.cc | 22 ++++++++++++++++++++++ src/eq_create.cc | 1 + tests/src/testCSAdapterEqFct.cpp | 21 ++++++++++++--------- 6 files changed, 54 insertions(+), 17 deletions(-) diff --git a/include/CSAdapterEqFct.h b/include/CSAdapterEqFct.h index 3a80e50..0a7f04b 100644 --- a/include/CSAdapterEqFct.h +++ b/include/CSAdapterEqFct.h @@ -30,7 +30,8 @@ class CSAdapterEqFct : public EqFct , boost::noncopyable { boost::shared_ptr<ControlSystemPVManager> const & controlSystemPVManager, boost::shared_ptr<DoocsUpdater> const & updater, std::string fctName = std::string()); - + ~CSAdapterEqFct(); + void init(); void update(); int fct_code(); diff --git a/include/DoocsUpdater.h b/include/DoocsUpdater.h index 924437c..b368140 100644 --- a/include/DoocsUpdater.h +++ b/include/DoocsUpdater.h @@ -4,6 +4,7 @@ #include <unordered_map> #include <map> #include <mtca4u/TransferElement.h> +#include <boost/noncopyable.hpp> namespace ChimeraTK{ /** A class to synchronise DeviceToControlSystem variable to Doocs. @@ -12,13 +13,16 @@ namespace ChimeraTK{ * when the thread is started, and (FIXME can be stopped by the stop() function which * returns after the thread has been joined). This happens latest in the destructor. */ - class DoocsUpdater{ + class DoocsUpdater: public boost::noncopyable{ public: - ~DoocsUpdater(){}; + ~DoocsUpdater(); void update(); // Update all variables once. This is the intermediate solution // before we have implemented the thread, and for testing - void run(){}; - void stop(){}; + + void updateLoop(); // Endless loop with interruption point around the update function. + // Intermediate solution until we have a working/testable version of readAny() + void run(); + void stop(); void addVariable( mtca4u::TransferElement & variable, std::function<void ()> updaterFunction); protected: diff --git a/src/CSAdapterEqFct.cc b/src/CSAdapterEqFct.cc index 9e249e4..a3ae2e7 100644 --- a/src/CSAdapterEqFct.cc +++ b/src/CSAdapterEqFct.cc @@ -22,6 +22,11 @@ namespace ChimeraTK{ registerProcessVariablesInDoocs(); } + CSAdapterEqFct::~CSAdapterEqFct(){ + //stop the updater thread before any of the process variables go out of scope + updater_->stop(); + } + void CSAdapterEqFct::init(){ std::cout << "this is eqfct init of " << fct_name() << std::endl; } @@ -33,9 +38,10 @@ namespace ChimeraTK{ // dirty hack until this is moved to a thread: unlock this EqFct. The updater does the locking // and the locks are not re-entrant - unlock(); - updater_->update(); - lock(); + //unlock(); + //updater_->update(); + //lock(); + sleep(1); } int CSAdapterEqFct::fct_code(){ diff --git a/src/DoocsUpdater.cc b/src/DoocsUpdater.cc index d9e6e1e..78898fa 100644 --- a/src/DoocsUpdater.cc +++ b/src/DoocsUpdater.cc @@ -20,4 +20,26 @@ namespace ChimeraTK{ } } + void DoocsUpdater::updateLoop(){ + while(true){ + update(); + // FIXME: This is brainstorming. Use testable sleep here + boost::this_thread::sleep_for(boost::chrono::milliseconds(10)); + } + } + + void DoocsUpdater::run(){ + _syncThread = boost::thread( boost::bind( &DoocsUpdater::updateLoop, this) ); + } + + void DoocsUpdater::stop(){ + _syncThread.interrupt(); + _syncThread.join(); + } + + DoocsUpdater::~DoocsUpdater(){ + stop(); + } + + }//namespace ChimeraTK diff --git a/src/eq_create.cc b/src/eq_create.cc index fff70ed..a2594ee 100644 --- a/src/eq_create.cc +++ b/src/eq_create.cc @@ -48,4 +48,5 @@ EqFct* eq_create (int eq_code, void *) { * the config file. We start the application here. It will be launched in a separate thread. */ void post_init_epilog() { ChimeraTK::ApplicationBase::getInstance().run(); + doocsAdapter.updater->run(); } diff --git a/tests/src/testCSAdapterEqFct.cpp b/tests/src/testCSAdapterEqFct.cpp index ae36f6b..09231a7 100644 --- a/tests/src/testCSAdapterEqFct.cpp +++ b/tests/src/testCSAdapterEqFct.cpp @@ -21,9 +21,10 @@ using namespace ChimeraTK; class TestableCSAdapterEqFct: public CSAdapterEqFct{ public: TestableCSAdapterEqFct(int fctCode, - boost::shared_ptr<ControlSystemPVManager> controlSystemPVManager, - std::string fctName): - CSAdapterEqFct(fctCode, controlSystemPVManager, boost::make_shared<DoocsUpdater>(), fctName){ + boost::shared_ptr<ControlSystemPVManager> controlSystemPVManager, + boost::shared_ptr<DoocsUpdater> const & updater, + std::string fctName): + CSAdapterEqFct(fctCode, controlSystemPVManager, updater, fctName){ } std::vector< boost::shared_ptr<D_fct> > & getDoocsProperties(){ return doocsProperties_; @@ -50,7 +51,8 @@ BOOST_AUTO_TEST_CASE( testCSAdapterEqFct ) { auto csManager = doocsAdapter.getControlSystemPVManager(); VariableMapper::getInstance().directImport( getAllVariableNames(csManager ) ); // after that create the EqFct - TestableCSAdapterEqFct eqFct(42, csManager, "test"); + auto updater = boost::make_shared<DoocsUpdater>(); + TestableCSAdapterEqFct eqFct(42, csManager, updater, "test"); // Test that the right number of properties is created. // Currently the vector is still empty. @@ -86,12 +88,12 @@ BOOST_AUTO_TEST_CASE( testCSAdapterEqFct ) { // and the other direction businessLogic.fromDeviceInt->accessData(0) = 12; businessLogic.fromDeviceInt->write(); - eqFct.update(); + updater->update(); BOOST_CHECK_EQUAL( doocsProperties["FROM_DEVICE.INT "]->value(), 12); businessLogic.fromDeviceInt->accessData(0) = 15; businessLogic.fromDeviceInt->write(); - eqFct.update(); + updater->update(); BOOST_CHECK_EQUAL( doocsProperties["FROM_DEVICE.INT "]->value(), 15); } @@ -110,9 +112,10 @@ BOOST_AUTO_TEST_CASE( testWithMapping ) { VariableMapper::getInstance().prepareOutput( "EqFctTest.xml", getAllVariableNames(csManager ) ); -// in the mapping two locations are created - TestableCSAdapterEqFct toDeviceEqFct(42, csManager, "test.TO_DEVICE"); - TestableCSAdapterEqFct fromDeviceEqFct(42, csManager, "test.FROM_DEVICE"); + // in the mapping two locations are created + auto updater = boost::make_shared<DoocsUpdater>(); + TestableCSAdapterEqFct toDeviceEqFct(42, csManager, updater, "test.TO_DEVICE"); + TestableCSAdapterEqFct fromDeviceEqFct(42, csManager, updater, "test.FROM_DEVICE"); BOOST_REQUIRE( toDeviceEqFct.getDoocsProperties().size() == 1 ); BOOST_REQUIRE( fromDeviceEqFct.getDoocsProperties().size() == 1 ); -- GitLab