diff --git a/datapoolglob/GlobalDataPool.cpp b/datapoolglob/GlobalDataPool.cpp index 18780904..25acaab3 100644 --- a/datapoolglob/GlobalDataPool.cpp +++ b/datapoolglob/GlobalDataPool.cpp @@ -44,18 +44,18 @@ PoolEntryIF* GlobalDataPool::getRawData( uint32_t data_pool_id ) { } } -ReturnValue_t GlobalDataPool::freeDataPoolLock() { +ReturnValue_t GlobalDataPool::unlockDataPool() { ReturnValue_t status = mutex->unlockMutex(); - if ( status != RETURN_OK ) { + if(status != RETURN_OK) { sif::error << "DataPool::DataPool: unlock of mutex failed with" " error code: " << status << std::endl; } return status; } -ReturnValue_t GlobalDataPool::lockDataPool() { - ReturnValue_t status = mutex->lockMutex(MutexIF::BLOCKING); - if ( status != RETURN_OK ) { +ReturnValue_t GlobalDataPool::lockDataPool(uint32_t timeoutMs) { + ReturnValue_t status = mutex->lockMutex(timeoutMs); + if(status != RETURN_OK) { sif::error << "DataPool::DataPool: lock of mutex failed " "with error code: " << status << std::endl; } diff --git a/datapoolglob/GlobalDataPool.h b/datapoolglob/GlobalDataPool.h index 42921a77..b9c1436f 100644 --- a/datapoolglob/GlobalDataPool.h +++ b/datapoolglob/GlobalDataPool.h @@ -95,12 +95,12 @@ public: * @brief This is a small helper function to facilitate locking the global data pool. * @details It fetches the pool's mutex id and tries to acquire the mutex. */ - ReturnValue_t lockDataPool(); + ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::BLOCKING); /** * @brief This is a small helper function to facilitate unlocking the global data pool. * @details It fetches the pool's mutex id and tries to free the mutex. */ - ReturnValue_t freeDataPoolLock(); + ReturnValue_t unlockDataPool(); /** * @brief The print call is a simple debug method. * @details It prints the current content of the data pool. diff --git a/datapoolglob/GlobalDataSet.cpp b/datapoolglob/GlobalDataSet.cpp index 503d068e..9da8d524 100644 --- a/datapoolglob/GlobalDataSet.cpp +++ b/datapoolglob/GlobalDataSet.cpp @@ -8,22 +8,22 @@ GlobDataSet::GlobDataSet(): DataSetBase() {} // (Destructor is already called) GlobDataSet::~GlobDataSet() {} -ReturnValue_t GlobDataSet::commit(bool valid) { +ReturnValue_t GlobDataSet::commit(bool valid, uint32_t lockTimeout) { setEntriesValid(valid); setSetValid(valid); - return commit(); + return commit(lockTimeout); } -ReturnValue_t GlobDataSet::commit() { - return DataSetBase::commit(); +ReturnValue_t GlobDataSet::commit(uint32_t lockTimeout) { + return DataSetBase::commit(lockTimeout); } ReturnValue_t GlobDataSet::unlockDataPool() { - return glob::dataPool.freeDataPoolLock(); + return glob::dataPool.unlockDataPool(); } -ReturnValue_t GlobDataSet::lockDataPool() { - return glob::dataPool.lockDataPool(); +ReturnValue_t GlobDataSet::lockDataPool(uint32_t timeoutMs) { + return glob::dataPool.lockDataPool(timeoutMs); } void GlobDataSet::setEntriesValid(bool valid) { diff --git a/datapoolglob/GlobalDataSet.h b/datapoolglob/GlobalDataSet.h index c2e0b577..f0bf7daa 100644 --- a/datapoolglob/GlobalDataSet.h +++ b/datapoolglob/GlobalDataSet.h @@ -44,8 +44,8 @@ public: * - @c COMMITING_WITHOUT_READING if set was not read yet and * contains non write-only variables */ - ReturnValue_t commit(bool valid); - ReturnValue_t commit() override; + ReturnValue_t commit(bool valid, uint32_t lockTimeout = MutexIF::BLOCKING); + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; /** * Set all entries @@ -74,8 +74,7 @@ private: * @details * It makes use of the lockDataPool method offered by the DataPool class. */ - ReturnValue_t lockDataPool() override; - + ReturnValue_t lockDataPool(uint32_t timeoutMs) override; /** * @brief This is a small helper function to facilitate * unlocking the global data pool diff --git a/datapoolglob/GlobalPoolVariable.h b/datapoolglob/GlobalPoolVariable.h index eb44c307..9e3eea0c 100644 --- a/datapoolglob/GlobalPoolVariable.h +++ b/datapoolglob/GlobalPoolVariable.h @@ -72,7 +72,49 @@ public: */ ~GlobPoolVar() {} + /** + * @brief This is a call to read the value from the global data pool. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the global data pool and copies the value and the valid + * information to its local attributes. In case of a failure (wrong type or + * pool id not found), the variable is set to zero and invalid. + * The read call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t read(uint32_t lockTimeout) override; + /** + * @brief The commit call writes back the variable's value to the data pool. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the valid flag is automatically set to "valid". + * The operation does NOT provide any mutual exclusive protection by itself. + * The commit call is protected with a lock. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. + */ + ReturnValue_t commit(uint32_t lockTimeout) override; + protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; /** * @brief To access the correct data pool entry on read and commit calls, * the data pool is stored. @@ -91,26 +133,6 @@ protected: */ pool_rwm_t readWriteMode; - /** - * @brief This is a call to read the value from the global data pool. - * @details - * When executed, this operation tries to fetch the pool entry with matching - * data pool id from the global data pool and copies the value and the valid - * information to its local attributes. In case of a failure (wrong type or - * pool id not found), the variable is set to zero and invalid. - * The operation does NOT provide any mutual exclusive protection by itself. - */ - ReturnValue_t read() override; - - /** - * @brief The commit call writes back the variable's value to the data pool. - * @details It checks type and size, as well as if the variable is writable. If so, - * the value is copied and the valid flag is automatically set to "valid". - * The operation does NOT provide any mutual exclusive protection by itself. - * - */ - ReturnValue_t commit() override; - /** * Empty ctor for List initialization */ @@ -138,7 +160,7 @@ public: uint8_t getValid(); - void setValid(uint8_t valid); + void setValid(bool valid) override; operator T() { return value; diff --git a/datapoolglob/GlobalPoolVariable.tpp b/datapoolglob/GlobalPoolVariable.tpp index d55ea4e0..d61d605d 100644 --- a/datapoolglob/GlobalPoolVariable.tpp +++ b/datapoolglob/GlobalPoolVariable.tpp @@ -12,8 +12,38 @@ inline GlobPoolVar::GlobPoolVar(uint32_t set_id, } } +template +inline ReturnValue_t GlobPoolVar::read(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +template +inline ReturnValue_t GlobPoolVar::commit(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = commitWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + template -inline ReturnValue_t GlobPoolVar::read() { +inline ReturnValue_t GlobPoolVar::readWithoutLock() { PoolEntry* read_out = glob::dataPool.getData(dataPoolId, 1); if (read_out != NULL) { valid = read_out->valid; @@ -29,7 +59,7 @@ inline ReturnValue_t GlobPoolVar::read() { } template -inline ReturnValue_t GlobPoolVar::commit() { +inline ReturnValue_t GlobPoolVar::commitWithoutLock() { PoolEntry* write_back = glob::dataPool.getData(dataPoolId, 1); if ((write_back != NULL) && (readWriteMode != VAR_READ)) { write_back->valid = valid; @@ -80,7 +110,7 @@ inline uint8_t GlobPoolVar::getValid() { } template -inline void GlobPoolVar::setValid(uint8_t valid) { +inline void GlobPoolVar::setValid(bool valid) { this->valid = valid; } diff --git a/datapoolglob/GlobalPoolVector.h b/datapoolglob/GlobalPoolVector.h index 24303457..93092228 100644 --- a/datapoolglob/GlobalPoolVector.h +++ b/datapoolglob/GlobalPoolVector.h @@ -102,7 +102,7 @@ public: else return false; } - void setValid(uint8_t valid) {this->valid = valid;} + void setValid(bool valid) {this->valid = valid;} uint8_t getValid() {return valid;} T &operator [](int i) {return value[i];} @@ -113,7 +113,7 @@ public: virtual size_t getSerializedSize() const override; virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian) override; -protected: + /** * @brief This is a call to read the array's values * from the global data pool. @@ -122,19 +122,43 @@ protected: * data pool id from the global data pool and copies all array values * and the valid information to its local attributes. * In case of a failure (wrong type, size or pool id not found), the - * variable is set to zero and invalid. The operation does NOT provide - * any mutual exclusive protection by itself. + * variable is set to zero and invalid. + * The read call is protected by a lock of the global data pool. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t read(); - + ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; /** * @brief The commit call copies the array values back to the data pool. * @details * It checks type and size, as well as if the variable is writable. If so, * the value is copied and the valid flag is automatically set to "valid". - * The operation does NOT provide any mutual exclusive protection by itself. + * The commit call is protected by a lock of the global data pool. + * It is recommended to use DataSets to read and commit multiple variables + * at once to avoid the overhead of unnecessary lock und unlock operations. */ - ReturnValue_t commit(); + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; + private: /** * @brief To access the correct data pool entry on read and commit calls, diff --git a/datapoolglob/GlobalPoolVector.tpp b/datapoolglob/GlobalPoolVector.tpp index 0b43191b..5710da57 100644 --- a/datapoolglob/GlobalPoolVector.tpp +++ b/datapoolglob/GlobalPoolVector.tpp @@ -12,8 +12,40 @@ inline GlobPoolVector::GlobPoolVector(uint32_t set_id, } } + template -inline ReturnValue_t GlobPoolVector::read() { +inline ReturnValue_t GlobPoolVector::read(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +template +inline ReturnValue_t GlobPoolVector::commit( + uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = commitWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +template +inline ReturnValue_t GlobPoolVector::readWithoutLock() { PoolEntry* read_out = glob::dataPool.getData(this->dataPoolId, vectorSize); if (read_out != nullptr) { @@ -33,7 +65,7 @@ inline ReturnValue_t GlobPoolVector::read() { } template -inline ReturnValue_t GlobPoolVector::commit() { +inline ReturnValue_t GlobPoolVector::commitWithoutLock() { PoolEntry* writeBack = glob::dataPool.getData(this->dataPoolId, vectorSize); if ((writeBack != nullptr) && (this->readWriteMode != VAR_READ)) { diff --git a/datapoolglob/PIDReader.h b/datapoolglob/PIDReader.h index 11206611..359b871f 100644 --- a/datapoolglob/PIDReader.h +++ b/datapoolglob/PIDReader.h @@ -15,7 +15,8 @@ class PIDReader: public PoolVariableIF { protected: uint32_t parameterId; uint8_t valid; - ReturnValue_t read() { + + ReturnValue_t readWithoutLock() { uint8_t arrayIndex = GlobalDataPool::PIDToArrayIndex(parameterId); PoolEntry* read_out = glob::dataPool.getData( GlobalDataPool::PIDToDataPoolId(parameterId), arrayIndex); @@ -36,9 +37,13 @@ protected: * Reason is the possibility to access a single DP vector element, but if we commit, * we set validity of the whole vector. */ - ReturnValue_t commit() { + ReturnValue_t commit(uint32_t lockTimeout) override { return HasReturnvaluesIF::RETURN_FAILED; } + ReturnValue_t commitWithoutLock() override { + return HasReturnvaluesIF::RETURN_FAILED; + } + /** * Empty ctor for List initialization */ @@ -71,6 +76,19 @@ public: } } + ReturnValue_t read(uint32_t lockTimeout) override { + ReturnValue_t result = glob::dataPool.lockDataPool(); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "PIDReader::read: Could not unlock data pool!" + << std::endl; + } + return result; + } /** * Copy ctor to copy classes containing Pool Variables. */ @@ -113,7 +131,7 @@ public: return valid; } - void setValid(uint8_t valid) { + void setValid(bool valid) { this->valid = valid; } diff --git a/datapoolglob/PoolRawAccess.cpp b/datapoolglob/PoolRawAccess.cpp index b10ee04c..39cfd58c 100644 --- a/datapoolglob/PoolRawAccess.cpp +++ b/datapoolglob/PoolRawAccess.cpp @@ -18,7 +18,21 @@ PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry, PoolRawAccess::~PoolRawAccess() {} -ReturnValue_t PoolRawAccess::read() { +ReturnValue_t PoolRawAccess::read(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = readWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +ReturnValue_t PoolRawAccess::readWithoutLock() { ReturnValue_t result = RETURN_FAILED; PoolEntryIF* readOut = glob::dataPool.getRawData(dataPoolId); if (readOut != nullptr) { @@ -75,7 +89,21 @@ void PoolRawAccess::handleReadError(ReturnValue_t result) { memset(value, 0, sizeof(value)); } -ReturnValue_t PoolRawAccess::commit() { +ReturnValue_t PoolRawAccess::commit(uint32_t lockTimeout) { + ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + result = commitWithoutLock(); + ReturnValue_t unlockResult = glob::dataPool.unlockDataPool(); + if(unlockResult != HasReturnvaluesIF::RETURN_OK) { + sif::error << "GlobPoolVar::read: Could not unlock global data pool" + << std::endl; + } + return result; +} + +ReturnValue_t PoolRawAccess::commitWithoutLock() { PoolEntryIF* write_back = glob::dataPool.getRawData(dataPoolId); if ((write_back != NULL) && (readWriteMode != VAR_READ)) { write_back->setValid(valid); @@ -189,7 +217,7 @@ bool PoolRawAccess::isValid() const { return false; } -void PoolRawAccess::setValid(uint8_t valid) { +void PoolRawAccess::setValid(bool valid) { this->valid = valid; } diff --git a/datapoolglob/PoolRawAccess.h b/datapoolglob/PoolRawAccess.h index 452b5397..60e3c71e 100644 --- a/datapoolglob/PoolRawAccess.h +++ b/datapoolglob/PoolRawAccess.h @@ -124,7 +124,7 @@ public: */ bool isValid() const; - void setValid(uint8_t valid); + void setValid(bool valid); /** * Getter for the remaining size. */ @@ -135,31 +135,49 @@ public: ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, bool bigEndian); -protected: /** * @brief This is a call to read the value from the global data pool. - * @details When executed, this operation tries to fetch the pool entry with matching - * data pool id from the global data pool and copies the value and the valid - * information to its local attributes. In case of a failure (wrong type or - * pool id not found), the variable is set to zero and invalid. - * The operation does NOT provide any mutual exclusive protection by itself ! - * If reading from the data pool without information about the type is desired, - * initialize the raw pool access by supplying a data set and using the data set - * read function, which calls this read function. + * @details + * When executed, this operation tries to fetch the pool entry with matching + * data pool id from the global data pool and copies the value and the valid + * information to its local attributes. In case of a failure (wrong type or + * pool id not found), the variable is set to zero and invalid. + * The call is protected by a lock of the global data pool. * @return -@c RETURN_OK Read successfull * -@c READ_TYPE_TOO_LARGE * -@c READ_INDEX_TOO_LARGE * -@c READ_ENTRY_NON_EXISTENT */ - ReturnValue_t read(); + ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override; /** * @brief The commit call writes back the variable's value to the data pool. - * @details It checks type and size, as well as if the variable is writable. If so, - * the value is copied and the valid flag is automatically set to "valid". - * The operation does NOT provide any mutual exclusive protection by itself. + * @details + * It checks type and size, as well as if the variable is writable. If so, + * the value is copied and the valid flag is automatically set to "valid". + * The call is protected by a lock of the global data pool. * */ - ReturnValue_t commit(); + ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override; + +protected: + /** + * @brief Like #read, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t readWithoutLock() override; + /** + * @brief Like #commit, but without a lock protection of the global pool. + * @details + * The operation does NOT provide any mutual exclusive protection by itself. + * This can be used if the lock is handled externally to avoid the overhead + * of consecutive lock und unlock operations. + * Declared protected to discourage free public usage. + */ + ReturnValue_t commitWithoutLock() override; ReturnValue_t handleReadOut(PoolEntryIF* read_out); void handleReadError(ReturnValue_t result);