Skip to content
Snippets Groups Projects
ConsumingFanOut.h 2.9 KiB
Newer Older
/*
 * ConsumingFanOut.h
 *
 *  Created on: Jun 15, 2016
 *      Author: Martin Hierholzer
 */

#ifndef CHIMERATK_CONSUMING_FAN_OUT_H
#define CHIMERATK_CONSUMING_FAN_OUT_H

#include <mtca4u/NDRegisterAccessor.h>

#include "FanOut.h"

namespace ChimeraTK {

  /** FanOut implementation which acts as a read-only (i.e. consuming) NDRegisterAccessor. The values read through
   *  this accessor will be obtained from the given feeding implementation and distributed to any number of slaves. */
  template<typename UserType>
  class ConsumingFanOut : public FanOut<UserType>, public mtca4u::NDRegisterAccessor<UserType> {

    public:
      
      ConsumingFanOut(boost::shared_ptr<mtca4u::NDRegisterAccessor<UserType>> feedingImpl)
      : FanOut<UserType>(feedingImpl)
      {
        mtca4u::NDRegisterAccessor<UserType>::buffer_2D.resize( feedingImpl->getNumberOfChannels() );
        for(size_t i=0; i<feedingImpl->getNumberOfChannels(); i++) {
          mtca4u::NDRegisterAccessor<UserType>::buffer_2D[i].resize( feedingImpl->getNumberOfSamples() );
        }
      }

      bool isReadable() const override {
      }
      
      void doReadTransfer() override {
        FanOut<UserType>::impl->read();
      }
      
      bool doReadTransferNonBlocking() override {
        return FanOut<UserType>::impl->readNonBlocking();
      }
      
      void postRead() override {
        mtca4u::NDRegisterAccessor<UserType>::buffer_2D[0].swap(FanOut<UserType>::impl->accessChannel(0));
        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) = mtca4u::NDRegisterAccessor<UserType>::buffer_2D[0];
          }
          slave->write();
        }
      }

      void write() override {
        throw std::logic_error("Write operation called on read-only variable.");
      }
      
      bool isSameRegister(const boost::shared_ptr<const mtca4u::TransferElement>& e) const override {
        // only true if the very instance of the transfer element is the same
        return e.get() == this;
      }
      
      std::vector<boost::shared_ptr<mtca4u::TransferElement> > getHardwareAccessingElements() override {
        return { boost::enable_shared_from_this<mtca4u::TransferElement>::shared_from_this() };
      }
      
      void replaceTransferElement(boost::shared_ptr<mtca4u::TransferElement>) override {
        // You can't replace anything here. Just do nothing.
      }
      
    protected:

      boost::shared_ptr<mtca4u::NDRegisterAccessor<UserType>> impl;

      std::list<boost::shared_ptr<mtca4u::NDRegisterAccessor<UserType>>> slaves;

  };

} /* namespace ChimeraTK */

#endif /* CHIMERATK_CONSUMING_FAN_OUT_H */