/// @copyright 2020 ECCI, Universidad de Costa Rica. All rights reserved /// This code is released under the GNU Public License version 3 /// @author Jeisson Hidalgo-Céspedes <jeisson.hidalgo@ucr.ac.cr> #ifndef DISPATCHER_HPP #define DISPATCHER_HPP #include <exception> #include <map> #include "Consumer.hpp" /** * @brief A dispatcher is both, a consumer of its own queue, and a producer * for many queues. For each data that is pushed to its queue, the dispatcher * distributes the data to another queues, using key-values */ template <typename KeyType, typename DataType> class Dispatcher : public Consumer<DataType> { /// Objects of this class cannot be copied DISABLE_COPY(Dispatcher); protected: /// Alias to the inherited queue for a more meaninguful identifier Queue<DataType>*& fromQueue = Consumer<DataType>::consumingQueue; /// This thread will distribute elements to the following queues std::map<KeyType, Queue<DataType>*> toQueues; public: /// Constructor explicit Dispatcher(Queue<DataType>* consumingQueue = nullptr , const DataType& stopCondition = DataType() , bool createOwnQueue = false) : Consumer<DataType>(consumingQueue, stopCondition, createOwnQueue) { } /// Destructor virtual ~Dispatcher() { } /// Register a map. When the data to be consumed has this key, it will be /// redirected to the the given queue inline void registerRedirect(const KeyType& key, Queue<DataType>* toQueue) { this->toQueues[key] = toQueue; } /// Override this method to process any data extracted from the queue void consume(DataType data) override { const KeyType& key = this->extractKey(data); const auto& itr = this->toQueues.find(key); if ( itr == this->toQueues.end() ) { throw std::runtime_error("dispatcher: queue's key not found"); } itr->second->push(data); } /// Override this method to extract the key from a data stored in fromQueue virtual KeyType extractKey(const DataType& data) const = 0; }; #endif // DISPATCHER_HPP