lasp/src/lasp/device/lasp_streammgr.h

170 lines
4.1 KiB
C++

#pragma once
#include "lasp_daq.h"
#include "lasp_siggen.h"
#include <list>
#include <memory>
#include <mutex>
class StreamMgr;
class InDataHandler {
protected:
StreamMgr &_mgr;
public:
virtual ~InDataHandler();
/**
* @brief When constructed, the handler is added to the stream manager, which
* will call the handlers's inCallback() until the point of destruction.
*
* @param mgr Stream manager.
*/
InDataHandler(StreamMgr &mgr);
/**
* @brief This function is called when input data from a DAQ is available.
*
* @param daqdata Input data from DAQ
*
* @return true if no error. False to stop the stream from running.
*/
virtual bool inCallback(const DaqData &daqdata) = 0;
};
/**
* @brief Stream manager. Used to manage the input and output streams.
* Implemented as a singleton: only one stream manager can be in existance for
* a given program.
*/
class StreamMgr {
enum class StreamType : us {
/**
* @brief Input stream
*/
input = 1 << 0,
/**
* @brief Output stream
*/
output = 1 << 1,
};
/**
* @brief Storage for streams.
*/
std::unique_ptr<Daq> _inputStream, _outputStream;
/**
* @brief All indata handlers are called when input data is available. Note
* that they can be called from different threads and should take care of
* thread-safety.
*/
std::list<InDataHandler *> _inDataHandlers;
std::mutex _inDataHandler_mtx;
/**
* @brief Signal generator in use to generate output data. Currently
* implemented as to generate the same data for all output channels.
*/
std::shared_ptr<Siggen> _siggen;
std::mutex _siggen_mtx;
StreamMgr();
friend class InDataHandler;
friend class Siggen;
// Singleton, no public destructor
~StreamMgr();
public:
StreamMgr(const StreamMgr &) = delete;
StreamMgr &operator=(const StreamMgr &) = delete;
/**
* @brief Get access to stream manager instance
*
* @return Reference to stream manager.
*/
static StreamMgr &getInstance();
/**
* @brief Start a stream.
*
* @param devinfo Device information of device
* @param config Configuration of device
*/
void startStream(const DeviceInfo &devinfo, const DaqConfiguration &config);
/**
* @brief Check if a certain stream is running. If running with no errors, it
* returns true. If an error occured, or the stream is not running, it gives
* false.
*
* @param type The type of stream to check for.
*/
bool isStreamRunningOK(const StreamType type) const {
return getStreamStatus(type).runningOK();
}
/**
* @brief Get the streamstatus object corresponding to a given stream.
*
* @param type Type of stream, input, inputType, etc.
*
* @return status object.
*/
Daq::StreamStatus getStreamStatus(const StreamType type) const;
/**
* @brief Get DAQ pointer for a given stream. Gives a nullptr if stream is
* not running.
*
* @param type The stream type to get a DAQ ptr for.
*
* @return Pointer to DAQ
*/
const Daq *getDaq(StreamType type) const;
/**
* @brief Stop stream of given type (input / output/ duplex);
*
* @param stype The stream type to stop.
*/
void stopStream(StreamType stype);
/**
* @brief Stop and delete all streams. Also called on destruction of the
* StreamMgr.
*/
void stopAllStreams();
/**
* @brief Set active signal generator for output streams. Only one `Siggen'
* is active at the same time. Siggen controls its own data race protection
* using a mutex.
*
* @param s New Siggen pointer
*/
void setSiggen(std::shared_ptr<Siggen> s);
private:
bool inCallback(const DaqData &data);
bool outCallback(DaqData &data);
void removeInDataHandler(InDataHandler &handler);
/**
* @brief Add an input data handler. The handler's inCallback() function is
* called with data when available. This function should *NOT* be called by
* the user, instead, an InDataHandler can only be created with the StreamMgr
* as argument.
*
* @param handler The handler to add.
*/
void addInDataHandler(InDataHandler &handler);
};