Newer
Older
Martin Christoph Hierholzer
committed
/*
* ScalarAccessor.h
*
* Created on: Jun 07, 2016
* Author: Martin Hierholzer
*/
#ifndef CHIMERATK_SCALAR_ACCESSOR_H
#define CHIMERATK_SCALAR_ACCESSOR_H
#include <string>
#include <boost/smart_ptr/shared_ptr.hpp>
Martin Christoph Hierholzer
committed
#include <boost/thread.hpp>
Martin Christoph Hierholzer
committed
#include "Accessor.h"
Martin Christoph Hierholzer
committed
/** Macros to declare a scalar variable/accessor more easily. The call to this macro must be placed inside the
Martin Christoph Hierholzer
committed
* class definiton of a Module (e.g. ApplicationModule or VariableGroup).
Martin Christoph Hierholzer
committed
*
* 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>
* unit is the engineering unit as a character constant.
* mode can be either ChimeraTK::UpdateMode::push or ChimeraTK::UpdateMode::poll, deciding whether a call to read()
* will block until new data is available (push) or just return the latest value (poll, might not be fully realtime
* capable). */
Martin Christoph Hierholzer
committed
#define CTK_SCALAR_INPUT(UserType, name, unit, mode, description) \
ChimeraTK::ScalarAccessor<UserType> name{this, #name, ChimeraTK::VariableDirection::consuming, unit, mode, \
description}
#define CTK_SCALAR_OUTPUT(UserType, name, unit, description) \
Martin Christoph Hierholzer
committed
ChimeraTK::ScalarAccessor<UserType> name{this, #name, ChimeraTK::VariableDirection::feeding, unit, \
Martin Christoph Hierholzer
committed
ChimeraTK::UpdateMode::push, description}
Martin Christoph Hierholzer
committed
namespace ChimeraTK {
/** Accessor for scalar variables (i.e. single values). */
template< typename UserType >
class ScalarAccessor : public Accessor<UserType> {
public:
Martin Christoph Hierholzer
committed
ScalarAccessor(Module *owner, const std::string &name, VariableDirection direction, std::string unit,
Martin Christoph Hierholzer
committed
UpdateMode mode, const std::string &description)
: Accessor<UserType>(owner, name, direction, unit, 1, mode, description)
Martin Christoph Hierholzer
committed
{}
Martin Christoph Hierholzer
committed
/** Default constructor creates a dysfunction accessor (to be assigned with a real accessor later) */
ScalarAccessor() {}
Martin Christoph Hierholzer
committed
void read() {
Martin Christoph Hierholzer
committed
if(Accessor<UserType>::_mode == UpdateMode::push) {
while(impl->readNonBlocking() == false) { /// @todo TODO proper blocking implementation
Martin Christoph Hierholzer
committed
boost::this_thread::yield();
boost::this_thread::interruption_point();
}
Martin Christoph Hierholzer
committed
}
else {
/// @todo TODO empty the queue to always receive the latest value
impl->readNonBlocking();
Martin Christoph Hierholzer
committed
boost::this_thread::interruption_point();
Martin Christoph Hierholzer
committed
}
} // LCOV_EXCL_LINE this line somehow ends up having a negative counter in the coverage report, which leads to a failure
Martin Christoph Hierholzer
committed
void write() {
impl->write();
Martin Christoph Hierholzer
committed
boost::this_thread::interruption_point();
Martin Christoph Hierholzer
committed
}
Martin Christoph Hierholzer
committed
bool readNonBlocking() {
boost::this_thread::interruption_point();
Martin Christoph Hierholzer
committed
return impl->readNonBlocking();
}
Martin Christoph Hierholzer
committed
/** 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() {
return impl->accessData(0);
Martin Christoph Hierholzer
committed
}
/** Assignment operator */
ScalarAccessor<UserType>& operator=(UserType rightHandSide) {
impl->accessData(0) = rightHandSide;
Martin Christoph Hierholzer
committed
return *this;
}
/** Pre-increment operator */
ScalarAccessor<UserType>& operator++() {
impl->accessData(0) = ++(impl->accessData(0));
Martin Christoph Hierholzer
committed
return *this;
}
/** Pre-decrement operator */
ScalarAccessor<UserType>& operator--() {
impl->accessData(0) = --(impl->accessData(0));
Martin Christoph Hierholzer
committed
return *this;
}
/** Post-increment operator */
UserType operator++(int) {
UserType temp = impl->accessData(0);
impl->accessData(0) = temp+1;
Martin Christoph Hierholzer
committed
return temp;
}
/** Post-decrement operator */
UserType operator--(int) {
UserType temp = impl->accessData(0);
impl->accessData(0) = temp-1;
Martin Christoph Hierholzer
committed
return temp;
}
bool isInitialised() const {
return impl != nullptr;
}
void useProcessVariable(const boost::shared_ptr<TransferElement > &var) {
impl = boost::dynamic_pointer_cast<NDRegisterAccessor<UserType>>(var);
Martin Christoph Hierholzer
committed
assert(impl);
if(Accessor<UserType>::getDirection() == VariableDirection::consuming) {
assert(impl->isReadable());
Martin Christoph Hierholzer
committed
}
else {
assert(impl->isWriteable());
Martin Christoph Hierholzer
committed
}
}
Martin Christoph Hierholzer
committed
using Accessor<UserType>::impl;
Martin Christoph Hierholzer
committed
};
} /* namespace ChimeraTK */
#endif /* CHIMERATK_SCALAR_ACCESSOR_H */