Merge pull request 'FreeRTOS Queue Map Manager' (#423) from KSat/fsfw:mueller/freertos-queue-map-manager into development

Reviewed-on: fsfw/fsfw#423
This commit is contained in:
Steffen Gaisser 2021-06-08 14:03:45 +02:00
commit b6b144bcdb
7 changed files with 336 additions and 234 deletions

View File

@ -15,6 +15,7 @@ target_sources(${LIB_FSFW_NAME}
TaskFactory.cpp TaskFactory.cpp
Timekeeper.cpp Timekeeper.cpp
TaskManagement.cpp TaskManagement.cpp
QueueMapManager.cpp
) )
# FreeRTOS is required to link the FSFW now. It is recommended to compile # FreeRTOS is required to link the FSFW now. It is recommended to compile

View File

@ -1,129 +1,128 @@
#include "MessageQueue.h" #include "MessageQueue.h"
#include "QueueMapManager.h"
#include "../../objectmanager/ObjectManagerIF.h" #include "../../objectmanager/ObjectManagerIF.h"
#include "../../serviceinterface/ServiceInterfaceStream.h" #include "../../serviceinterface/ServiceInterfaceStream.h"
// TODO I guess we should have a way of checking if we are in an ISR and then
// use the "fromISR" versions of all calls
// As a first step towards this, introduces system context variable which needs
// to be switched manually
// Haven't found function to find system context.
MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize): MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize):
maxMessageSize(maxMessageSize) { maxMessageSize(maxMessageSize) {
handle = xQueueCreate(messageDepth, maxMessageSize); handle = xQueueCreate(messageDepth, maxMessageSize);
if (handle == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
if (handle == nullptr) { sif::error << "MessageQueue::MessageQueue: Creation failed" << std::endl;
sif::error << "MessageQueue::MessageQueue:" sif::error << "Specified Message Depth: " << messageDepth << std::endl;
<< " Creation failed." << std::endl; sif::error << "Specified Maximum Message Size: " << maxMessageSize << std::endl;
sif::error << "Specified Message Depth: " << messageDepth #else
<< std::endl; sif::printError("MessageQueue::MessageQueue: Creation failed\n");
sif::error << "Specified Maximum Message Size: " sif::printError("Specified Message Depth: %d\n", messageDepth);
<< maxMessageSize << std::endl; sif::printError("Specified MAximum Message Size: %d\n", maxMessageSize);
}
#endif #endif
}
QueueMapManager::instance()->addMessageQueue(handle, &queueId);
} }
MessageQueue::~MessageQueue() { MessageQueue::~MessageQueue() {
if (handle != nullptr) { if (handle != nullptr) {
vQueueDelete(handle); vQueueDelete(handle);
} }
} }
void MessageQueue::switchSystemContext(CallContext callContext) { void MessageQueue::switchSystemContext(CallContext callContext) {
this->callContext = callContext; this->callContext = callContext;
} }
ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, bool ignoreFault) { MessageQueueMessageIF* message, bool ignoreFault) {
return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); return sendMessageFrom(sendTo, message, this->getId(), ignoreFault);
} }
ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) { ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId()); return sendToDefaultFrom(message, this->getId());
} }
ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message, ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) { MessageQueueId_t sentFrom, bool ignoreFault) {
return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault);
} }
ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) { ReturnValue_t MessageQueue::reply(MessageQueueMessageIF* message) {
if (this->lastPartner != MessageQueueIF::NO_QUEUE) { if (this->lastPartner != MessageQueueIF::NO_QUEUE) {
return sendMessageFrom(this->lastPartner, message, this->getId()); return sendMessageFrom(this->lastPartner, message, this->getId());
} else { } else {
return NO_REPLY_PARTNER; return NO_REPLY_PARTNER;
} }
} }
ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom, MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault) { bool ignoreFault) {
return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault, return sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault,
callContext); callContext);
} }
QueueHandle_t MessageQueue::getNativeQueueHandle() {
return handle;
}
ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) { ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) {
if (result != pdPASS) { if (result != pdPASS) {
if (not ignoreFault) { if (not ignoreFault) {
InternalErrorReporterIF* internalErrorReporter = objectManager-> InternalErrorReporterIF* internalErrorReporter = objectManager->
get<InternalErrorReporterIF>( get<InternalErrorReporterIF>(objects::INTERNAL_ERROR_REPORTER);
objects::INTERNAL_ERROR_REPORTER); if (internalErrorReporter != nullptr) {
if (internalErrorReporter != nullptr) { internalErrorReporter->queueMessageNotSent();
internalErrorReporter->queueMessageNotSent(); }
} }
} return MessageQueueIF::FULL;
return MessageQueueIF::FULL; }
} return HasReturnvaluesIF::RETURN_OK;
return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message, ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) { MessageQueueId_t* receivedFrom) {
ReturnValue_t status = this->receiveMessage(message); ReturnValue_t status = this->receiveMessage(message);
if(status == HasReturnvaluesIF::RETURN_OK) { if(status == HasReturnvaluesIF::RETURN_OK) {
*receivedFrom = this->lastPartner; *receivedFrom = this->lastPartner;
} }
return status; return status;
} }
ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) { ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessageIF* message) {
BaseType_t result = xQueueReceive(handle,reinterpret_cast<void*>( BaseType_t result = xQueueReceive(handle,reinterpret_cast<void*>(
message->getBuffer()), 0); message->getBuffer()), 0);
if (result == pdPASS){ if (result == pdPASS){
this->lastPartner = message->getSender(); this->lastPartner = message->getSender();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { } else {
return MessageQueueIF::EMPTY; return MessageQueueIF::EMPTY;
} }
} }
MessageQueueId_t MessageQueue::getLastPartner() const { MessageQueueId_t MessageQueue::getLastPartner() const {
return lastPartner; return lastPartner;
} }
ReturnValue_t MessageQueue::flush(uint32_t* count) { ReturnValue_t MessageQueue::flush(uint32_t* count) {
//TODO FreeRTOS does not support flushing partially //TODO FreeRTOS does not support flushing partially
//Is always successful //Is always successful
xQueueReset(handle); xQueueReset(handle);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
MessageQueueId_t MessageQueue::getId() const { MessageQueueId_t MessageQueue::getId() const {
return reinterpret_cast<MessageQueueId_t>(handle); return queueId;
} }
void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) {
defaultDestinationSet = true; defaultDestinationSet = true;
this->defaultDestination = defaultDestination; this->defaultDestination = defaultDestination;
} }
MessageQueueId_t MessageQueue::getDefaultDestination() const { MessageQueueId_t MessageQueue::getDefaultDestination() const {
return defaultDestination; return defaultDestination;
} }
bool MessageQueue::isDefaultDestinationSet() const { bool MessageQueue::isDefaultDestinationSet() const {
return defaultDestinationSet; return defaultDestinationSet;
} }
@ -131,30 +130,25 @@ bool MessageQueue::isDefaultDestinationSet() const {
ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom, MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault, CallContext callContext) { bool ignoreFault, CallContext callContext) {
BaseType_t result = pdFALSE; BaseType_t result = pdFALSE;
QueueHandle_t destination = nullptr; if(sendTo == MessageQueueIF::NO_QUEUE) {
return MessageQueueIF::DESTINATION_INVALID;
}
if(sendTo == MessageQueueIF::NO_QUEUE or sendTo == 0x00) { QueueHandle_t destination = QueueMapManager::instance()->getMessageQueue(sendTo);
return MessageQueueIF::DESTINATION_INVALID; if(destination == nullptr) {
} return MessageQueueIF::DESTINATION_INVALID;
else { }
destination = reinterpret_cast<QueueHandle_t>(sendTo);
}
message->setSender(sentFrom); message->setSender(sentFrom);
if(callContext == CallContext::TASK) { if(callContext == CallContext::TASK) {
result = xQueueSendToBack(destination, result = xQueueSendToBack(destination, static_cast<const void*>(message->getBuffer()), 0);
static_cast<const void*>(message->getBuffer()), 0);
} }
else { else {
/* If the call context is from an interrupt, /* If the call context is from an interrupt, request a context switch if a higher priority
* request a context switch if a higher priority task task was blocked by the interrupt. */
* was blocked by the interrupt. */
BaseType_t xHigherPriorityTaskWoken = pdFALSE; BaseType_t xHigherPriorityTaskWoken = pdFALSE;
result = xQueueSendFromISR(reinterpret_cast<QueueHandle_t>(sendTo), result = xQueueSendFromISR(destination, static_cast<const void*>(message->getBuffer()),
static_cast<const void*>(message->getBuffer()),
&xHigherPriorityTaskWoken); &xHigherPriorityTaskWoken);
if(xHigherPriorityTaskWoken == pdTRUE) { if(xHigherPriorityTaskWoken == pdTRUE) {
TaskManagement::requestContextSwitch(callContext); TaskManagement::requestContextSwitch(callContext);

View File

@ -11,11 +11,6 @@
#include <freertos/queue.h> #include <freertos/queue.h>
#include <fsfw/ipc/MessageQueueMessage.h> #include <fsfw/ipc/MessageQueueMessage.h>
// TODO: this class assumes that MessageQueueId_t is the same size as void*
// (the FreeRTOS handle type), compiler will catch this but it might be nice
// to have something checking or even an always working solution
// https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/
/** /**
* @brief This class manages sending and receiving of * @brief This class manages sending and receiving of
* message queue messages. * message queue messages.
@ -40,112 +35,116 @@
* @ingroup message_queue * @ingroup message_queue
*/ */
class MessageQueue : public MessageQueueIF { class MessageQueue : public MessageQueueIF {
friend class MessageQueueSenderIF; friend class MessageQueueSenderIF;
public: public:
/** /**
* @brief The constructor initializes and configures the message queue. * @brief The constructor initializes and configures the message queue.
* @details * @details
* By making use of the according operating system call, a message queue * By making use of the according operating system call, a message queue
* is created and initialized. The message depth - the maximum number of * is created and initialized. The message depth - the maximum number of
* messages to be buffered - may be set with the help of a parameter, * messages to be buffered - may be set with the help of a parameter,
* whereas the message size is automatically set to the maximum message * whereas the message size is automatically set to the maximum message
* queue message size. The operating system sets the message queue id, or * queue message size. The operating system sets the message queue id, or
* in case of failure, it is set to zero. * in case of failure, it is set to zero.
* @param message_depth * @param message_depth
* The number of messages to be buffered before passing an error to the * The number of messages to be buffered before passing an error to the
* sender. Default is three. * sender. Default is three.
* @param max_message_size * @param max_message_size
* With this parameter, the maximum message size can be adjusted. * With this parameter, the maximum message size can be adjusted.
* This should be left default. * This should be left default.
*/ */
MessageQueue( size_t messageDepth = 3, MessageQueue( size_t messageDepth = 3,
size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE ); size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE );
/** Copying message queues forbidden */ /** Copying message queues forbidden */
MessageQueue(const MessageQueue&) = delete; MessageQueue(const MessageQueue&) = delete;
MessageQueue& operator=(const MessageQueue&) = delete; MessageQueue& operator=(const MessageQueue&) = delete;
/** /**
* @brief The destructor deletes the formerly created message queue. * @brief The destructor deletes the formerly created message queue.
* @details This is accomplished by using the delete call provided * @details This is accomplished by using the delete call provided
* by the operating system. * by the operating system.
*/ */
virtual ~MessageQueue(); virtual ~MessageQueue();
/** /**
* This function is used to switch the call context. This has to be called * This function is used to switch the call context. This has to be called
* if a message is sent or received from an ISR! * if a message is sent or received from an ISR!
* @param callContext * @param callContext
*/ */
void switchSystemContext(CallContext callContext); void switchSystemContext(CallContext callContext);
/** MessageQueueIF implementation */ /** MessageQueueIF implementation */
ReturnValue_t sendMessage(MessageQueueId_t sendTo, ReturnValue_t sendMessage(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, bool ignoreFault = false) override; MessageQueueMessageIF* message, bool ignoreFault = false) override;
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override; ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
ReturnValue_t reply(MessageQueueMessageIF* message) override; ReturnValue_t reply(MessageQueueMessageIF* message) override;
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE, MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false) override; bool ignoreFault = false) override;
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message, virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = NO_QUEUE, MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault = false) override; bool ignoreFault = false) override;
ReturnValue_t receiveMessage(MessageQueueMessageIF* message, ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t *receivedFrom) override; MessageQueueId_t *receivedFrom) override;
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override; ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override;
ReturnValue_t flush(uint32_t* count) override; ReturnValue_t flush(uint32_t* count) override;
MessageQueueId_t getLastPartner() const override; MessageQueueId_t getLastPartner() const override;
MessageQueueId_t getId() const override; MessageQueueId_t getId() const override;
void setDefaultDestination(MessageQueueId_t defaultDestination) override; void setDefaultDestination(MessageQueueId_t defaultDestination) override;
MessageQueueId_t getDefaultDestination() const override; MessageQueueId_t getDefaultDestination() const override;
bool isDefaultDestinationSet() const override; bool isDefaultDestinationSet() const override;
QueueHandle_t getNativeQueueHandle();
protected: protected:
/** /**
* @brief Implementation to be called from any send Call within * @brief Implementation to be called from any send Call within
* MessageQueue and MessageQueueSenderIF. * MessageQueue and MessageQueueSenderIF.
* @details * @details
* This method takes the message provided, adds the sentFrom information and * This method takes the message provided, adds the sentFrom information and
* passes it on to the destination provided with an operating system call. * passes it on to the destination provided with an operating system call.
* The OS's return value is returned. * The OS's return value is returned.
* @param sendTo * @param sendTo
* This parameter specifies the message queue id to send the message to. * This parameter specifies the message queue id to send the message to.
* @param message * @param message
* This is a pointer to a previously created message, which is sent. * This is a pointer to a previously created message, which is sent.
* @param sentFrom * @param sentFrom
* The sentFrom information can be set to inject the sender's queue id into * The sentFrom information can be set to inject the sender's queue id into
* the message. This variable is set to zero by default. * the message. This variable is set to zero by default.
* @param ignoreFault * @param ignoreFault
* If set to true, the internal software fault counter is not incremented * If set to true, the internal software fault counter is not incremented
* if queue is full. * if queue is full.
* @param context Specify whether call is made from task or from an ISR. * @param context Specify whether call is made from task or from an ISR.
*/ */
static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE, MessageQueueMessageIF* message, MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault=false, CallContext callContext = CallContext::TASK); bool ignoreFault=false, CallContext callContext = CallContext::TASK);
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
private: private:
bool defaultDestinationSet = false; bool defaultDestinationSet = false;
QueueHandle_t handle; QueueHandle_t handle;
MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE; MessageQueueId_t queueId = MessageQueueIF::NO_QUEUE;
MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE;
const size_t maxMessageSize; MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
//! Stores the current system context MessageQueueId_t lastPartner = MessageQueueIF::NO_QUEUE;
CallContext callContext = CallContext::TASK; const size_t maxMessageSize;
//! Stores the current system context
CallContext callContext = CallContext::TASK;
}; };
#endif /* FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ */ #endif /* FSFW_OSAL_FREERTOS_MESSAGEQUEUE_H_ */

View File

@ -0,0 +1,58 @@
#include "QueueMapManager.h"
#include "../../ipc/MutexFactory.h"
#include "../../ipc/MutexGuard.h"
QueueMapManager* QueueMapManager::mqManagerInstance = nullptr;
QueueMapManager::QueueMapManager() {
mapLock = MutexFactory::instance()->createMutex();
}
QueueMapManager* QueueMapManager::instance() {
if (mqManagerInstance == nullptr){
mqManagerInstance = new QueueMapManager();
}
return QueueMapManager::mqManagerInstance;
}
ReturnValue_t QueueMapManager::addMessageQueue(QueueHandle_t queue, MessageQueueId_t* id) {
MutexGuard lock(mapLock);
uint32_t currentId = queueCounter++;
auto returnPair = queueMap.emplace(currentId, queue);
if(not returnPair.second) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "QueueMapManager::addMessageQueue This ID is already "
"inside the map!" << std::endl;
#else
sif::printError("QueueMapManager::addMessageQueue This ID is already "
"inside the map!\n");
#endif
return HasReturnvaluesIF::RETURN_FAILED;
}
if (id != nullptr) {
*id = currentId;
}
return HasReturnvaluesIF::RETURN_OK;
}
QueueHandle_t QueueMapManager::getMessageQueue(MessageQueueId_t messageQueueId) const {
auto queueIter = queueMap.find(messageQueueId);
if(queueIter != queueMap.end()) {
return queueIter->second;
}
else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "QueueMapManager::getQueueHandle: The ID " << messageQueueId <<
" does not exists in the map!" << std::endl;
#else
sif::printWarning("QueueMapManager::getQueueHandle: The ID %d does not exist in the map!\n",
messageQueueId);
#endif
}
return nullptr;
}
QueueMapManager::~QueueMapManager() {
MutexFactory::instance()->deleteMutex(mapLock);
}

View File

@ -0,0 +1,50 @@
#ifndef FSFW_OSAL_FREERTOS_QUEUEMAPMANAGER_H_
#define FSFW_OSAL_FREERTOS_QUEUEMAPMANAGER_H_
#include "../../ipc/MutexIF.h"
#include "../../ipc/messageQueueDefinitions.h"
#include "../../ipc/MessageQueueIF.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include <map>
using QueueMap = std::map<MessageQueueId_t, QueueHandle_t>;
class QueueMapManager {
public:
//! Returns the single instance of QueueMapManager
static QueueMapManager* instance();
/**
* Insert a message queue and the corresponding QueueHandle into the map
* @param queue The message queue to insert.
* @param id The passed value will be set unless a nullptr is passed
* @return
*/
ReturnValue_t addMessageQueue(QueueHandle_t queue, MessageQueueId_t* id);
/**
* Get the message queue handle by providing a message queue ID. Returns nullptr
* if the queue ID does not exist in the internal map.
* @param messageQueueId
* @return
*/
QueueHandle_t getMessageQueue(MessageQueueId_t messageQueueId) const;
private:
//! External instantiation forbidden. Constructor still required for singleton instantiation.
QueueMapManager();
~QueueMapManager();
uint32_t queueCounter = 0;
MutexIF* mapLock;
QueueMap queueMap;
static QueueMapManager* mqManagerInstance;
};
#endif /* FSFW_OSAL_FREERTOS_QUEUEMAPMANAGER_H_ */

View File

@ -15,52 +15,49 @@ QueueMapManager::~QueueMapManager() {
} }
QueueMapManager* QueueMapManager::instance() { QueueMapManager* QueueMapManager::instance() {
if (mqManagerInstance == nullptr){ if (mqManagerInstance == nullptr){
mqManagerInstance = new QueueMapManager(); mqManagerInstance = new QueueMapManager();
} }
return QueueMapManager::mqManagerInstance; return QueueMapManager::mqManagerInstance;
} }
ReturnValue_t QueueMapManager::addMessageQueue( ReturnValue_t QueueMapManager::addMessageQueue(
MessageQueueIF* queueToInsert, MessageQueueId_t* id) { MessageQueueIF* queueToInsert, MessageQueueId_t* id) {
/* Not thread-safe, but it is assumed all message queues are created at software initialization MutexGuard lock(mapLock);
now. If this is to be made thread-safe in the future, it propably would be sufficient to lock uint32_t currentId = queueCounter++;
the increment operation here. */ auto returnPair = queueMap.emplace(currentId, queueToInsert);
uint32_t currentId = queueCounter++; if(not returnPair.second) {
auto returnPair = queueMap.emplace(currentId, queueToInsert); /* This should never happen for the atomic variable. */
if(not returnPair.second) {
/* This should never happen for the atomic variable. */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "QueueMapManager::addMessageQueue This ID is already " sif::error << "QueueMapManager::addMessageQueue This ID is already "
"inside the map!" << std::endl; "inside the map!" << std::endl;
#else #else
sif::printError("QueueMapManager::addMessageQueue This ID is already " sif::printError("QueueMapManager::addMessageQueue This ID is already "
"inside the map!\n"); "inside the map!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
if (id != nullptr) { if (id != nullptr) {
*id = currentId; *id = currentId;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
MessageQueueIF* QueueMapManager::getMessageQueue( MessageQueueIF* QueueMapManager::getMessageQueue(
MessageQueueId_t messageQueueId) const { MessageQueueId_t messageQueueId) const {
MutexGuard(mapLock, MutexIF::TimeoutType::WAITING, 50); auto queueIter = queueMap.find(messageQueueId);
auto queueIter = queueMap.find(messageQueueId); if(queueIter != queueMap.end()) {
if(queueIter != queueMap.end()) { return queueIter->second;
return queueIter->second; }
} else {
else {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "QueueMapManager::getQueueHandle: The ID " << messageQueueId << sif::warning << "QueueMapManager::getQueueHandle: The ID " << messageQueueId <<
" does not exists in the map!" << std::endl; " does not exists in the map!" << std::endl;
#else #else
sif::printWarning("QueueMapManager::getQueueHandle: The ID %d does not exist in the map!\n", sif::printWarning("QueueMapManager::getQueueHandle: The ID %d does not exist in the map!\n",
messageQueueId); messageQueueId);
#endif #endif
return nullptr; }
} return nullptr;
} }

View File

@ -15,33 +15,36 @@ using QueueMap = std::unordered_map<MessageQueueId_t, MessageQueueIF*>;
*/ */
class QueueMapManager { class QueueMapManager {
public: public:
//! Returns the single instance of SemaphoreFactory.
static QueueMapManager* instance();
/**
* Insert a message queue into the map and returns a message queue ID //! Returns the single instance of QueueMapManager.
* @param queue The message queue to insert. static QueueMapManager* instance();
* @param id The passed value will be set unless a nullptr is passed
* @return /**
*/ * Insert a message queue into the map and returns a message queue ID
ReturnValue_t addMessageQueue(MessageQueueIF* queue, MessageQueueId_t* * @param queue The message queue to insert.
id = nullptr); * @param id The passed value will be set unless a nullptr is passed
/** * @return
* Get the message queue handle by providing a message queue ID. */
* @param messageQueueId ReturnValue_t addMessageQueue(MessageQueueIF* queue, MessageQueueId_t*
* @return id = nullptr);
*/ /**
MessageQueueIF* getMessageQueue(MessageQueueId_t messageQueueId) const; * Get the message queue handle by providing a message queue ID. Returns nullptr
* if the queue ID is not contained inside the internal map.
* @param messageQueueId
* @return
*/
MessageQueueIF* getMessageQueue(MessageQueueId_t messageQueueId) const;
private: private:
//! External instantiation is forbidden. //! External instantiation is forbidden. Constructor still required for singleton instantiation.
QueueMapManager(); QueueMapManager();
~QueueMapManager(); ~QueueMapManager();
uint32_t queueCounter = 0; uint32_t queueCounter = 0;
MutexIF* mapLock; MutexIF* mapLock;
QueueMap queueMap; QueueMap queueMap;
static QueueMapManager* mqManagerInstance; static QueueMapManager* mqManagerInstance;
}; };