Skip to content
Snippets Groups Projects
Commit c056439b authored by Martin Christoph Hierholzer's avatar Martin Christoph Hierholzer
Browse files

added VariableGroup, a module which contains a set of variables

parent 1cd43a53
No related branches found
No related tags found
No related merge requests found
......@@ -49,7 +49,20 @@ namespace ChimeraTK {
/* Obtain the unit of the variable */
virtual const std::string& getUnit() const = 0;
/** Read an input variable. In case of an output variable, an exception will be thrown. This function will block
* the calling thread until the variable has been read. If the UpdateMode::push flag has been set when creating
* the accessor, this function will wait until a new value has been provided to the variable. If a new value is
* already available before calling this function, the function will be non-blocking and lock-free. */
virtual void read() = 0;
/** Non-blocking read. Will return whether a new value was obtained. For pull-type varibales, always true is
* returned, independently whether the value was changed or not. */
virtual bool readNonBlocking() = 0;
/** Write an output variable. In case of an input variable, an exception will be thrown. */
virtual void write() = 0;
protected:
friend class ApplicationModule;
......@@ -79,8 +92,7 @@ namespace ChimeraTK {
/** The default accessor takes no arguments and leaves the accessor uninitialised. It will be dysfunctional
* until it is properly initialised using connectTo(). */
Accessor(ApplicationModule *owner, const std::string &name, VariableDirection direction, std::string unit,
UpdateMode mode)
Accessor(Module *owner, const std::string &name, VariableDirection direction, std::string unit, UpdateMode mode)
: _owner(owner), _name(name), _direction(direction), _unit(unit), _mode(mode), node{*this}
{
owner->registerAccessor(this);
......@@ -114,7 +126,7 @@ namespace ChimeraTK {
protected:
ApplicationModule *_owner;
Module *_owner;
std::string _name;
VariableDirection _direction;
std::string _unit;
......
......@@ -16,11 +16,6 @@
namespace ChimeraTK {
template< typename UserType >
class Accessor;
class AccessorBase;
class ApplicationModule : public Module {
public:
......@@ -37,22 +32,9 @@ namespace ChimeraTK {
protected:
template< typename UserType >
friend class Accessor;
friend class AccessorBase;
/** Called inside the constructor of Accessor: adds the accessor to the list */
void registerAccessor(AccessorBase* accessor) {
accessorList.push_back(accessor);
}
/** The thread executing mainLoop() */
boost::thread moduleThread;
/** List of accessors owned by this module */
std::list<AccessorBase*> accessorList;
};
} /* namespace ChimeraTK */
......
......@@ -9,7 +9,12 @@
#define CHIMERATK_MODULE_H
namespace ChimeraTK {
template< typename UserType >
class Accessor;
class AccessorBase;
/** Base class for ApplicationModule, DeviceModule and ControlSystemModule, to have a common interface for these
* module types. */
class Module {
......@@ -30,7 +35,22 @@ namespace ChimeraTK {
/** Terminate the module. Must be called before destruction, if run() was called previously. */
virtual void terminate() {};
protected:
template< typename UserType >
friend class Accessor;
friend class AccessorBase;
/** Called inside the constructor of Accessor: adds the accessor to the list */
void registerAccessor(AccessorBase* accessor) {
accessorList.push_back(accessor);
}
/** List of accessors owned by this module */
std::list<AccessorBase*> accessorList;
};
} /* namespace ChimeraTK */
......
......@@ -16,7 +16,7 @@
#include "Accessor.h"
/** Macros to declare a scalar variable/accessor more easily. The call to this macro must be placed inside the
* class definiton of an ApplicationModule.
* class definiton of a Module (e.g. ApplicationModule or VariableGroup).
*
* UserType is the data type of the variable.
* name will be the C++ symbol name of the variable accessor. It will be of the type ChimeraTK::ScalarAccessor<UserType>
......@@ -36,15 +36,11 @@ namespace ChimeraTK {
template< typename UserType >
class ScalarAccessor : public Accessor<UserType> {
public:
ScalarAccessor(ApplicationModule *owner, const std::string &name, VariableDirection direction, std::string unit,
ScalarAccessor(Module *owner, const std::string &name, VariableDirection direction, std::string unit,
UpdateMode mode)
: Accessor<UserType>(owner, name, direction, unit, mode)
{}
/** Read an input variable. In case of an output variable, an exception will be thrown. This function will block
* the calling thread until the variable has been read. If the UpdateMode::push flag has been set when creating
* the accessor, this function will wait until a new value has been provided to the variable. If a new value is
* already available before calling this function, the function will be non-blocking and lock-free. */
void read() {
if(Accessor<UserType>::_mode == UpdateMode::push) {
while(impl->readNonBlocking() == false) { /// @todo TODO proper blocking implementation
......@@ -59,18 +55,15 @@ namespace ChimeraTK {
}
} // LCOV_EXCL_LINE this line somehow ends up having a negative counter in the coverage report, which leads to a failure
/** Check if an input variable has new data. In case of an output variable, an exception will be thrown. If the
* wait_for_new_data access mode flag was not provided when creating the accessor, this function will return
* always false. */
//bool hasNewData(); /// @todo TODO right now impossible to implement...
/** Write an output variable. In case of an input variable, an exception will be thrown. This function never
* blocks and is always implemented in a lock-free manner. */
void write() {
impl->write();
boost::this_thread::interruption_point();
}
bool readNonBlocking() {
return impl->readNonBlocking();
}
/** Implicit type conversion to user type T to access the first element (often the only element).
* This covers already a lot of operations like arithmetics and comparison */
operator UserType() {
......
/*
* VariableGroup.h
*
* Created on: Nov 8, 2016
* Author: Martin Hierholzer
*/
#ifndef CHIMERATK_VARIABLE_GROUP_H
#define CHIMERATK_VARIABLE_GROUP_H
#include <list>
#include <boost/thread.hpp>
#include "Module.h"
namespace ChimeraTK {
class VariableGroup : public Module {
public:
/** Destructor */
virtual ~VariableGroup();
/** Wait for receiving an update for any of the push-type variables in the group. Any poll-type variables are
* read after receiving the update. If no push-type variables are in the group, this function will just read
* all variables. */
void readAny();
protected:
/** The thread executing mainLoop() */
boost::thread moduleThread;
};
} /* namespace ChimeraTK */
#endif /* CHIMERATK_VARIABLE_GROUP_H */
/*
* VariableGroup.cc
*
* Created on: Jun 27, 2016
* Author: Martin Hierholzer
*/
#include "VariableGroup.h"
#include "Accessor.h"
namespace ChimeraTK {
void VariableGroup::readAny() {
bool gotUpdate = false;
while(!gotUpdate) { /// @todo TODO FIXME make proper blocking implementation
boost::this_thread::yield();
boost::this_thread::interruption_point();
for(auto accessor : accessorList) {
if(accessor->getUpdateMode() == UpdateMode::poll) {
if(accessor->readNonBlocking()) gotUpdate = true;
}
}
}
for(auto accessor : accessorList) {
if(accessor->getUpdateMode() == UpdateMode::poll) {
accessor->read();
}
}
}
} /* namespace ChimeraTK */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment