Skip to content
Snippets Groups Projects
ScalarAccessor.h 5.2 KiB
Newer Older
/*
 * 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>
/** Macros to declare a scalar variable/accessor more easily. The call to this macro must be placed inside the
 *  class definiton of an ApplicationModule.
 *
 *  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). */
#define SCALAR_INPUT(UserType, name, unit, mode)                                                                    \
    ChimeraTK::ScalarAccessor<UserType> name{this, #name, ChimeraTK::VariableDirection::consuming, unit, mode}
#define SCALAR_OUTPUT(UserType, name, unit)                                                                         \
    ChimeraTK::ScalarAccessor<UserType> name{this, #name, ChimeraTK::VariableDirection::feeding, unit,              \
                                             ChimeraTK::UpdateMode::push}

namespace ChimeraTK {

  /** Accessor for scalar variables (i.e. single values). */
  template< typename UserType >
  class ScalarAccessor : public Accessor<UserType> {
    public:
      ScalarAccessor(ApplicationModule *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. */
          while(impl->readNonBlocking() == false) { /// @todo TODO proper blocking implementation
            boost::this_thread::yield();
            boost::this_thread::interruption_point();
          }
          /// @todo TODO empty the queue to always receive the latest value
      } // 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() {
      }

      /** 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() {
      }

      /** Assignment operator */
      ScalarAccessor<UserType>& operator=(UserType rightHandSide) {
        impl->accessData(0) = rightHandSide;
        return *this;
      }

      /** Pre-increment operator */
      ScalarAccessor<UserType>& operator++() {
        impl->accessData(0) = ++(impl->accessData(0));
        return *this;
      }

      /** Pre-decrement operator */
      ScalarAccessor<UserType>& operator--() {
        impl->accessData(0) = --(impl->accessData(0));
        return *this;
      }

      /** Post-increment operator */
      UserType operator++(int) {
        UserType temp = impl->accessData(0);
        impl->accessData(0) = temp+1;
        return temp;
      }

      /** Post-decrement operator */
      UserType operator--(int) {
        UserType temp = impl->accessData(0);
        impl->accessData(0) = temp-1;
      void useProcessVariable(const boost::shared_ptr<TransferElement > &var) {
        impl = boost::dynamic_pointer_cast<NDRegisterAccessor<UserType>>(var);
        assert(impl);
        if(Accessor<UserType>::getDirection() == VariableDirection::consuming) {
      boost::shared_ptr< NDRegisterAccessor<UserType> > impl;

  };

} /* namespace ChimeraTK */

#endif /* CHIMERATK_SCALAR_ACCESSOR_H */