351 lines
12 KiB
C++
351 lines
12 KiB
C++
#pragma once
|
|
|
|
#include <fsfw/datapool/internal/SharedPoolAttorney.h>
|
|
|
|
#include "FSFWConfig.h"
|
|
#include "LocalPoolObjectBase.h"
|
|
#include "fsfw/datapool/DataSetIF.h"
|
|
#include "fsfw/datapool/PoolVariableIF.h"
|
|
#include "fsfw/serialize/SerializeAdapter.h"
|
|
|
|
namespace datapool {
|
|
|
|
/**
|
|
* @brief Local Pool Variable class which is used to access the local pools.
|
|
* @details
|
|
* This class is not stored in the map. Instead, it is used to access
|
|
* the pool entries by using a pointer to the map storing the pool
|
|
* entries. It can also be used to organize these pool entries into data sets.
|
|
*
|
|
* @tparam T The template parameter sets the type of the variable. Currently,
|
|
* all plain data types are supported, but in principle any type is possible.
|
|
* @ingroup data_pool
|
|
*/
|
|
template <typename T>
|
|
class PoolVariable : public PoolObjectBase {
|
|
public:
|
|
//! Default ctor is forbidden.
|
|
PoolVariable() = delete;
|
|
|
|
/**
|
|
* This constructor is used by the data creators to have pool variable
|
|
* instances which can also be stored in datasets.
|
|
*
|
|
* It does not fetch the current value from the data pool, which
|
|
* has to be done by calling the read() operation.
|
|
* Datasets can be used to access multiple local pool entries in an
|
|
* efficient way. A pointer to a dataset can be passed to register
|
|
* the pool variable in that dataset directly.
|
|
* @param poolId ID of the local pool entry.
|
|
* @param hkOwner Pointer of the owner. This will generally be the calling
|
|
* class itself which passes "this".
|
|
* @param dataSet The data set in which the variable shall register itself.
|
|
* If nullptr, the variable is not registered.
|
|
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
|
*/
|
|
PoolVariable(SharedPool& sharedPool, dp::id_t poolId, DataSetIF* dataSet = nullptr,
|
|
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
|
|
|
/**
|
|
* This constructor is used by data users like controllers to have
|
|
* access to the local pool variables of data creators by supplying
|
|
* the respective creator object ID.
|
|
*
|
|
* It does not fetch the current value from the data pool, which
|
|
* has to be done by calling the read() operation.
|
|
* Datasets can be used to access multiple local pool entries in an
|
|
* efficient way. A pointer to a dataset can be passed to register
|
|
* the pool variable in that dataset directly.
|
|
* @param poolId ID of the local pool entry.
|
|
* @param hkOwner object ID of the pool owner.
|
|
* @param dataSet The data set in which the variable shall register itself.
|
|
* If nullptr, the variable is not registered.
|
|
* @param setReadWriteMode Specify the read-write mode of the pool variable.
|
|
*
|
|
*/
|
|
PoolVariable(object_id_t poolOwner, dp::id_t poolId, DataSetIF* dataSet = nullptr,
|
|
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
|
/**
|
|
* Variation which takes the global unique identifier of a pool variable.
|
|
* @param globalPoolId
|
|
* @param dataSet
|
|
* @param setReadWriteMode
|
|
*/
|
|
PoolVariable(g_id_t globalPoolId, DataSetIF* dataSet = nullptr,
|
|
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
|
|
|
|
virtual ~PoolVariable() {};
|
|
|
|
T get() const;
|
|
|
|
/**
|
|
* @brief This is the local copy of the data pool entry.
|
|
* @details The user can work on this attribute
|
|
* just like he would on a simple local variable.
|
|
*/
|
|
T value = 0;
|
|
|
|
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
|
SerializeIF::Endianness streamEndianness) const override;
|
|
size_t getSerializedSize() const override;
|
|
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
|
SerializeIF::Endianness streamEndianness) override;
|
|
|
|
/**
|
|
* @brief This is a call to read the array's values
|
|
* from the global data pool.
|
|
* @details
|
|
* When executed, this operation tries to fetch the pool entry with matching
|
|
* data pool id from the 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 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(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
|
uint32_t timeoutMs = 20) 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 local valid flag is written back as well.
|
|
* 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 commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
|
uint32_t timeoutMs = 20) override;
|
|
|
|
PoolVariable<T>& operator=(const T& newValue);
|
|
PoolVariable<T>& operator=(const PoolVariable<T>& newPoolVariable);
|
|
|
|
//! Explicit type conversion operator. Allows casting the class to
|
|
//! its template type to perform operations on value.
|
|
explicit operator T() const;
|
|
|
|
bool operator==(const PoolVariable<T>& other) const;
|
|
bool operator==(const T& other) const;
|
|
|
|
bool operator!=(const PoolVariable<T>& other) const;
|
|
bool operator!=(const T& other) const;
|
|
|
|
bool operator<(const PoolVariable<T>& other) const;
|
|
bool operator<(const T& other) const;
|
|
|
|
bool operator>(const PoolVariable<T>& other) const;
|
|
bool operator>(const T& other) const;
|
|
|
|
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;
|
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
// std::ostream is the type for object std::cout
|
|
template <typename U>
|
|
friend std::ostream& operator<<(std::ostream& out, const LocalPoolVariable<U>& var);
|
|
#endif
|
|
};
|
|
|
|
template <typename T>
|
|
PoolVariable<T>::PoolVariable(SharedPool& sharedPool, dp::id_t poolId, DataSetIF* dataSet,
|
|
pool_rwm_t setReadWriteMode)
|
|
: PoolObjectBase(sharedPool, poolId, dataSet, setReadWriteMode) {}
|
|
|
|
template <typename T>
|
|
PoolVariable<T>::PoolVariable(object_id_t poolOwner, dp::id_t poolId, DataSetIF* dataSet,
|
|
pool_rwm_t setReadWriteMode)
|
|
: PoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
|
|
|
|
template <typename T>
|
|
PoolVariable<T>::PoolVariable(g_id_t globalPoolId, DataSetIF* dataSet, pool_rwm_t setReadWriteMode)
|
|
: PoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet, setReadWriteMode) {}
|
|
|
|
template <typename T>
|
|
ReturnValue_t PoolVariable<T>::read(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
|
if (sharedPool == nullptr) {
|
|
return readWithoutLock();
|
|
}
|
|
MutexIF* mutex = sharedPool->getPoolMutex();
|
|
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
|
if (result != returnvalue::OK) {
|
|
return result;
|
|
}
|
|
result = readWithoutLock();
|
|
mutex->unlockMutex();
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
inline ReturnValue_t PoolVariable<T>::readWithoutLock() {
|
|
if (sharedPool == nullptr) {
|
|
return PoolVariableIF::INVALID_SHARED_POOL;
|
|
}
|
|
if (readWriteMode == pool_rwm_t::VAR_WRITE) {
|
|
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
|
}
|
|
|
|
PoolEntry<T>* poolEntry = nullptr;
|
|
if (ReturnValue_t result = sharedPool->fetchPoolEntry(localPoolId, &poolEntry);
|
|
result != returnvalue::OK) {
|
|
return result;
|
|
}
|
|
|
|
this->value = *(poolEntry->getDataPtr());
|
|
this->valid = poolEntry->getValid();
|
|
return returnvalue::OK;
|
|
}
|
|
|
|
template <typename T>
|
|
inline ReturnValue_t PoolVariable<T>::commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
|
if (sharedPool == nullptr) {
|
|
return commitWithoutLock();
|
|
}
|
|
MutexIF* mutex = sharedPool->getPoolMutex();
|
|
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
|
|
if (result != returnvalue::OK) {
|
|
return result;
|
|
}
|
|
result = commitWithoutLock();
|
|
mutex->unlockMutex();
|
|
return result;
|
|
}
|
|
|
|
template <typename T>
|
|
ReturnValue_t PoolVariable<T>::commitWithoutLock() {
|
|
if (readWriteMode == pool_rwm_t::VAR_READ) {
|
|
return PoolVariableIF::INVALID_READ_WRITE_MODE;
|
|
}
|
|
|
|
PoolEntry<T>* poolEntry = nullptr;
|
|
ReturnValue_t result = sharedPool->fetchPoolEntry(localPoolId, &poolEntry);
|
|
if (result != returnvalue::OK) {
|
|
return result;
|
|
}
|
|
|
|
*(poolEntry->getDataPtr()) = this->value;
|
|
poolEntry->setValid(this->valid);
|
|
return returnvalue::OK;
|
|
}
|
|
|
|
template <typename T>
|
|
ReturnValue_t PoolVariable<T>::serialize(uint8_t** buffer, size_t* size, const size_t max_size,
|
|
SerializeIF::Endianness streamEndianness) const {
|
|
return SerializeAdapter::serialize(&value, buffer, size, max_size, streamEndianness);
|
|
}
|
|
|
|
template <typename T>
|
|
size_t PoolVariable<T>::getSerializedSize() const {
|
|
return SerializeAdapter::getSerializedSize(&value);
|
|
}
|
|
|
|
template <typename T>
|
|
ReturnValue_t PoolVariable<T>::deSerialize(const uint8_t** buffer, size_t* size,
|
|
SerializeIF::Endianness streamEndianness) {
|
|
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
|
}
|
|
template <typename T>
|
|
T PoolVariable<T>::get() const {
|
|
return value;
|
|
}
|
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
template <typename T>
|
|
inline std::ostream& operator<<(std::ostream& out, const PoolVariable<T>& var) {
|
|
out << var.value;
|
|
return out;
|
|
}
|
|
#endif
|
|
|
|
template <typename T>
|
|
PoolVariable<T>::operator T() const {
|
|
return value;
|
|
}
|
|
|
|
template <typename T>
|
|
PoolVariable<T>& PoolVariable<T>::operator=(const T& newValue) {
|
|
value = newValue;
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
PoolVariable<T>& PoolVariable<T>::operator=(const PoolVariable<T>& newPoolVariable) {
|
|
value = newPoolVariable.value;
|
|
return *this;
|
|
}
|
|
|
|
template <typename T>
|
|
bool PoolVariable<T>::operator==(const PoolVariable<T>& other) const {
|
|
return this->value == other.value;
|
|
}
|
|
|
|
template <typename T>
|
|
bool PoolVariable<T>::operator==(const T& other) const {
|
|
return this->value == other;
|
|
}
|
|
|
|
template <typename T>
|
|
bool PoolVariable<T>::operator!=(const PoolVariable& other) const {
|
|
return not(*this == other);
|
|
}
|
|
|
|
template <typename T>
|
|
bool PoolVariable<T>::operator!=(const T& other) const {
|
|
return not(*this == other);
|
|
}
|
|
|
|
template <typename T>
|
|
bool PoolVariable<T>::operator<(const PoolVariable<T>& other) const {
|
|
return this->value < other.value;
|
|
}
|
|
|
|
template <typename T>
|
|
bool PoolVariable<T>::operator<(const T& other) const {
|
|
return this->value < other;
|
|
}
|
|
|
|
template <typename T>
|
|
bool PoolVariable<T>::operator>(const PoolVariable<T>& other) const {
|
|
return not(*this < other);
|
|
}
|
|
|
|
template <typename T>
|
|
bool PoolVariable<T>::operator>(const T& other) const {
|
|
return not(*this < other);
|
|
}
|
|
|
|
template <class T>
|
|
using var_t = PoolVariable<T>;
|
|
|
|
using bool_t = PoolVariable<uint8_t>;
|
|
using u8_t = PoolVariable<uint8_t>;
|
|
using u16_t = PoolVariable<uint16_t>;
|
|
using u32_t = PoolVariable<uint32_t>;
|
|
using u64_t = PoolVariable<uint64_t>;
|
|
using i8_t = PoolVariable<int8_t>;
|
|
using i16_t = PoolVariable<int16_t>;
|
|
using i32_t = PoolVariable<int32_t>;
|
|
using i64_t = PoolVariable<int64_t>;
|
|
using f32_t = PoolVariable<float>;
|
|
using f64_t = PoolVariable<double>;
|
|
|
|
} // namespace datapool
|