#ifndef _STIMULUS_PRODUCER_H #define _STIMULUS_PRODUCER_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include "deviceAttachmentSpec.h" namespace smo { namespace stim_buff { // Forward declaration class StimulusBuffer; /** * StimulusProducer manages a collection of stimulus frames with simultaneity stamps. * * This producer is designed to hold stimulus frames that have been assembled * from raw sensor data (e.g., Livox Avia point cloud data) and are ready * for processing by the mind layer. * * The producer provides thread-safe operations for adding frames, retrieving * frames, and managing the producer state. */ class StimulusProducer { public: explicit StimulusProducer( const std::shared_ptr &deviceAttachmentSpec, boost::asio::io_service& ioService_) : deviceAttachmentSpec(deviceAttachmentSpec), ioService(ioService_), shouldContinue(false), timer(ioService), nDeferrals(0) {} virtual ~StimulusProducer() = default; // Non-copyable, movable StimulusProducer(const StimulusProducer&) = delete; StimulusProducer& operator=(const StimulusProducer&) = delete; StimulusProducer(StimulusProducer&&) = default; StimulusProducer& operator=(StimulusProducer&&) = default; // Control methods virtual void start() { std::cout << __func__ << ": Starting stimulus producer for device " << deviceAttachmentSpec->deviceSelector << std::endl; shouldContinue = true; nDeferrals = 0; scheduleNextTimeout(); } virtual void stop(); void allowNextStimulusFrame() { frameAssemblyRateLimiter.release(); } virtual std::shared_ptr getAttachedStimulusBuffer( const std::shared_ptr& spec) const; virtual std::shared_ptr getOrCreateAttachedStimulusBuffer( const std::shared_ptr &deviceAttachmentSpec) = 0; // Check if any attached buffer has the specified qualeIfaceApi bool hasBufferWithQualeIfaceApi(const std::string& qualeIfaceApi) const; protected: SpinLock frameAssemblyRateLimiter; // Virtual functions for derived classes to override virtual int getStopDelayMs() const { return CONFIG_STIMBUFF_FRAME_PERIOD_MS; } virtual void stimFrameProductionTimesliceInd() = 0; private: void onTimeout(const boost::system::error_code& error); public: std::shared_ptr deviceAttachmentSpec; std::vector> attachedStimulusBuffers; private: boost::asio::io_service& ioService; protected: SpinLock shouldContinueLock; bool shouldContinue; private: boost::asio::deadline_timer timer; size_t nDeferrals; std::chrono::high_resolution_clock::time_point deferralStartTime; void scheduleNextTimeout(int delayMs = CONFIG_STIMBUFF_FRAME_PERIOD_MS); }; } // namespace stim_buff } // namespace smo #endif // _STIMULUS_PRODUCER_H