diff --git a/datapool/DataSetBase.cpp b/datapool/DataSetBase.cpp index 6ff2fc83..9104c8e7 100644 --- a/datapool/DataSetBase.cpp +++ b/datapool/DataSetBase.cpp @@ -31,20 +31,14 @@ ReturnValue_t DataSetBase::registerVariable( return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t DataSetBase::read() { +ReturnValue_t DataSetBase::read(uint32_t lockTimeout) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; if (state == States::DATA_SET_UNINITIALISED) { - lockDataPool(); + lockDataPool(lockTimeout); for (uint16_t count = 0; count < fillCount; count++) { - if (registeredVariables[count]->getReadWriteMode() - != PoolVariableIF::VAR_WRITE - && registeredVariables[count]->getDataPoolId() - != PoolVariableIF::NO_PARAMETER) { - ReturnValue_t status = registeredVariables[count]->read(); - if (status != HasReturnvaluesIF::RETURN_OK) { - result = INVALID_PARAMETER_DEFINITION; - break; - } + ReturnValue_t result = readVariable(count); + if(result != RETURN_OK) { + break; } } state = States::DATA_SET_WAS_READ; @@ -58,47 +52,53 @@ ReturnValue_t DataSetBase::read() { return result; } -ReturnValue_t DataSetBase::commit() { +ReturnValue_t DataSetBase::readVariable(uint16_t count) { + ReturnValue_t result = DataSetIF::INVALID_PARAMETER_DEFINITION; + // These checks are often performed by the respective + // variable implementation too, but I guess a double check does not hurt. + if (registeredVariables[count]->getReadWriteMode() != + PoolVariableIF::VAR_WRITE and + registeredVariables[count]->getDataPoolId() + != PoolVariableIF::NO_PARAMETER) + { + result = registeredVariables[count]->readWithoutLock(); + } + return result; +} + +ReturnValue_t DataSetBase::commit(uint32_t lockTimeout) { if (state == States::DATA_SET_WAS_READ) { - handleAlreadyReadDatasetCommit(); + handleAlreadyReadDatasetCommit(lockTimeout); return HasReturnvaluesIF::RETURN_OK; } else { - return handleUnreadDatasetCommit(); + return handleUnreadDatasetCommit(lockTimeout); } } -ReturnValue_t DataSetBase::lockDataPool() { - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t DataSetBase::unlockDataPool() { - return HasReturnvaluesIF::RETURN_FAILED; -} - -void DataSetBase::handleAlreadyReadDatasetCommit() { - lockDataPool(); +void DataSetBase::handleAlreadyReadDatasetCommit(uint32_t lockTimeout) { + lockDataPool(lockTimeout); for (uint16_t count = 0; count < fillCount; count++) { if (registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_READ && registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) { - registeredVariables[count]->commit(); + registeredVariables[count]->commitWithoutLock(); } } state = States::DATA_SET_UNINITIALISED; unlockDataPool(); } -ReturnValue_t DataSetBase::handleUnreadDatasetCommit() { +ReturnValue_t DataSetBase::handleUnreadDatasetCommit(uint32_t lockTimeout) { ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; - lockDataPool(); + lockDataPool(lockTimeout); for (uint16_t count = 0; count < fillCount; count++) { if (registeredVariables[count]->getReadWriteMode() == PoolVariableIF::VAR_WRITE && registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) { - registeredVariables[count]->commit(); + registeredVariables[count]->commitWithoutLock(); } else if (registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) { if (result != COMMITING_WITHOUT_READING) { @@ -113,6 +113,15 @@ ReturnValue_t DataSetBase::handleUnreadDatasetCommit() { return result; } + +ReturnValue_t DataSetBase::lockDataPool(uint32_t timeoutMs) { + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t DataSetBase::unlockDataPool() { + return HasReturnvaluesIF::RETURN_OK; +} + ReturnValue_t DataSetBase::serialize(uint8_t** buffer, size_t* size, const size_t maxSize, bool bigEndian) const { ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; diff --git a/datapool/DataSetBase.h b/datapool/DataSetBase.h index 6b468c11..8bf9a99a 100644 --- a/datapool/DataSetBase.h +++ b/datapool/DataSetBase.h @@ -2,6 +2,7 @@ #define FRAMEWORK_DATAPOOL_DATASETBASE_H_ #include #include +#include /** * @brief The DataSetBase class manages a set of locally checked out variables. @@ -21,7 +22,8 @@ * of the set, the DataSet class automatically sets the valid flag in the * data pool to invalid (without) changing the variable's value. * - * The base class lockDataPo + * The base class lockDataPool und unlockDataPool implementation are empty + * and should be implemented to protect the underlying pool type. * @author Bastian Baetz * @ingroup data_pool */ @@ -49,14 +51,15 @@ public: * * The data pool is locked during the whole read operation and * freed afterwards.The state changes to "was written" after this operation. - * @return - @c RETURN_OK if all variables were read successfully. - * - @c INVALID_PARAMETER_DEFINITION if PID, size or type of the - * requested variable is invalid. - * - @c SET_WAS_ALREADY_READ if read() is called twice without calling - * commit() in between + * @return + * - @c RETURN_OK if all variables were read successfully. + * - @c INVALID_PARAMETER_DEFINITION if PID, size or type of the + * requested variable is invalid. + * - @c SET_WAS_ALREADY_READ if read() is called twice without calling + * commit() in between */ - virtual ReturnValue_t read(); - + virtual ReturnValue_t read(uint32_t lockTimeout = + MutexIF::BLOCKING) override; /** * @brief The commit call initializes writing back the registered variables. * @details @@ -67,23 +70,30 @@ public: * The data pool is locked during the whole commit operation and * freed afterwards. The state changes to "was committed" after this operation. * - * If the set does contain at least one variable which is not write-only commit() - * can only be called after read(). If the set only contains variables which are - * write only, commit() can be called without a preceding read() call. + * If the set does contain at least one variable which is not write-only + * commit() can only be called after read(). If the set only contains + * variables which are write only, commit() can be called without a + * preceding read() call. * @return - @c RETURN_OK if all variables were read successfully. * - @c COMMITING_WITHOUT_READING if set was not read yet and * contains non write-only variables */ - virtual ReturnValue_t commit(); + virtual ReturnValue_t commit(uint32_t lockTimeout = + MutexIF::BLOCKING) override; - /* DataSetIF implementation */ + /** + * Register the passed pool variable instance into the data set. + * @param variable + * @return + */ virtual ReturnValue_t registerVariable( PoolVariableIF* variable) override; /** * Provides the means to lock the underlying data structure to ensure * thread-safety. Default implementation is empty * @return Always returns -@c RETURN_OK */ - virtual ReturnValue_t lockDataPool() override; + virtual ReturnValue_t lockDataPool(uint32_t timeoutMs = + MutexIF::BLOCKING) override; /** * Provides the means to unlock the underlying data structure to ensure * thread-safety. Default implementation is empty @@ -98,12 +108,12 @@ public: virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) override; - //SHOULDDO we could use a linked list of datapool variables + // SHOULDDO we could use a linked list of datapool variables //!< This definition sets the maximum number of variables to //! register in one DataSet. static const uint8_t DATA_SET_MAX_SIZE = 63; -protected: +protected: /** * @brief The fill_count attribute ensures that the variables * register in the correct array position and that the maximum @@ -128,8 +138,10 @@ protected: */ PoolVariableIF* registeredVariables[DATA_SET_MAX_SIZE] = { }; - void handleAlreadyReadDatasetCommit(); - ReturnValue_t handleUnreadDatasetCommit(); +private: + ReturnValue_t readVariable(uint16_t count); + void handleAlreadyReadDatasetCommit(uint32_t lockTimeout); + ReturnValue_t handleUnreadDatasetCommit(uint32_t lockTimeout); }; #endif /* FRAMEWORK_DATAPOOL_DATASETBASE_H_ */ diff --git a/datapool/DataSetIF.h b/datapool/DataSetIF.h index d9cc4966..9c5b13c8 100644 --- a/datapool/DataSetIF.h +++ b/datapool/DataSetIF.h @@ -2,6 +2,7 @@ #define DATASETIF_H_ #include +#include class PoolVariableIF; /** @@ -33,20 +34,23 @@ public: */ virtual ~DataSetIF() {} + virtual ReturnValue_t read(uint32_t lockTimeout) = 0; + virtual ReturnValue_t commit(uint32_t lockTimeout) = 0; /** * @brief This operation provides a method to register local data pool * variables to register in a data set by passing itself * to this DataSet operation. */ - virtual ReturnValue_t registerVariable( PoolVariableIF* variable ) = 0; + virtual ReturnValue_t registerVariable(PoolVariableIF* variable) = 0; +private: /** * @brief Most underlying data structures will have a pool like structure * and will require a lock and unlock mechanism to ensure * thread-safety * @return Lock operation result */ - virtual ReturnValue_t lockDataPool() = 0; + virtual ReturnValue_t lockDataPool(uint32_t timeoutMs) = 0; /** * @brief Unlock call corresponding to the lock call. * @return Unlock operation result diff --git a/datapool/PoolVariableIF.h b/datapool/PoolVariableIF.h index 0cbc18c5..3086bbe8 100644 --- a/datapool/PoolVariableIF.h +++ b/datapool/PoolVariableIF.h @@ -21,18 +21,10 @@ class PoolVariableIF : public SerializeIF { friend class DataSetBase; friend class GlobDataSet; friend class LocalDataSet; -protected: - /** - * @brief The commit call shall write back a newly calculated local - * value to the data pool. - */ - virtual ReturnValue_t commit() = 0; - /** - * @brief The read call shall read the value of this parameter from - * the data pool and store the content locally. - */ - virtual ReturnValue_t read() = 0; public: + static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF; + static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0); + static constexpr bool VALID = 1; static constexpr bool INVALID = 0; static constexpr uint32_t NO_PARAMETER = 0; @@ -61,9 +53,43 @@ public: /** * @brief With this call, the valid information of the variable is set. */ - // why not just use a boolean here? - virtual void setValid(uint8_t validity) = 0; + virtual void setValid(bool validity) = 0; + /** + * @brief The commit call shall write back a newly calculated local + * value to the data pool. + * @details + * It is assumed that these calls are implemented in a thread-safe manner! + */ + virtual ReturnValue_t commit(uint32_t lockTimeout) = 0; + /** + * @brief The read call shall read the value of this parameter from + * the data pool and store the content locally. + * @details + * It is assumbed that these calls are implemented in a thread-safe manner! + */ + virtual ReturnValue_t read(uint32_t lockTimeout) = 0; + +protected: + + /** + * @brief Same as commit with the difference that comitting will be + * performed without a lock + * @return + * This can be used if the lock protection is handled externally + * to avoid the overhead of locking and unlocking consecutively. + * Declared protected to avoid free public usage. + */ + virtual ReturnValue_t readWithoutLock() = 0; + /** + * @brief Same as commit with the difference that comitting will be + * performed without a lock + * @return + * This can be used if the lock protection is handled externally + * to avoid the overhead of locking and unlocking consecutively. + * Declared protected to avoid free public usage. + */ + virtual ReturnValue_t commitWithoutLock() = 0; }; using pool_rwm_t = PoolVariableIF::ReadWriteMode_t;