/* * \file PoolVariable.h * * \brief This file contains the PoolVariable class, which locally represents a non-array data pool variable. * * \date 10/17/2012 * * \author Bastian Baetz */ #ifndef POOLVARIABLE_H_ #define POOLVARIABLE_H_ #include "DataSetIF.h" #include "PoolEntry.h" #include "PoolVariableIF.h" #include "../serialize/SerializeAdapter.h" #include "../serviceinterface/ServiceInterfaceStream.h" template class PoolVarList; /** * \brief This is the access class for non-array data pool entries. * * \details To ensure safe usage of the data pool, operation is not done directly on the data pool * entries, but on local copies. This class provides simple type-safe access to single * data pool entries (i.e. entries with length = 1). * The class can be instantiated as read-write and read only. * It provides a commit-and-roll-back semantic, which means that the variable's value in * the data pool is not changed until the commit call is executed. * \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 class PoolVariable: public PoolVariableIF { template friend class PoolVarList; protected: /** * \brief To access the correct data pool entry on read and commit calls, the data pool id * is stored. */ uint32_t dataPoolId; /** * \brief The valid information as it was stored in the data pool is copied to this attribute. */ uint8_t valid; /** * \brief The information whether the class is read-write or read-only is stored here. */ ReadWriteMode_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() { PoolEntry *read_out = ::dataPool.getData < T > (dataPoolId, 1); if (read_out != NULL) { valid = read_out->valid; value = *(read_out->address); return HasReturnvaluesIF::RETURN_OK; } else { value = 0; valid = false; sif::error << "PoolVariable: read of DP Variable 0x" << std::hex << dataPoolId << std::dec << " failed." << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } } /** * \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() { PoolEntry *write_back = ::dataPool.getData < T > (dataPoolId, 1); if ((write_back != NULL) && (readWriteMode != VAR_READ)) { write_back->valid = valid; *(write_back->address) = value; return HasReturnvaluesIF::RETURN_OK; } else { return HasReturnvaluesIF::RETURN_FAILED; } } /** * Empty ctor for List initialization */ PoolVariable() : dataPoolId(PoolVariableIF::NO_PARAMETER), valid( PoolVariableIF::INVALID), readWriteMode(VAR_READ), value(0) { } public: /** * \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; /** * \brief In the constructor, the variable can register itself in a DataSet (if not NULL is * passed). * \details It DOES NOT fetch the current value from the data pool, but sets the value * attribute to default (0). The value is fetched within the read() operation. * \param set_id This is the id in the global data pool this instance of the access class * corresponds to. * \param dataSet The data set in which the variable shall register itself. If NULL, * the variable is not registered. * \param setWritable If this flag is set to true, changes in the value attribute can be * written back to the data pool, otherwise not. */ PoolVariable(uint32_t set_id, DataSetIF *dataSet, ReadWriteMode_t setReadWriteMode) : dataPoolId(set_id), valid(PoolVariableIF::INVALID), readWriteMode( setReadWriteMode), value(0) { if (dataSet != NULL) { dataSet->registerVariable(this); } } /** * Copy ctor to copy classes containing Pool Variables. */ PoolVariable(const PoolVariable &rhs) : dataPoolId(rhs.dataPoolId), valid(rhs.valid), readWriteMode( rhs.readWriteMode), value(rhs.value) { } /** * \brief The classes destructor is empty. * \details If commit() was not called, the local value is * discarded and not written back to the data pool. */ ~PoolVariable() { } /** * \brief This operation returns the data pool id of the variable. */ uint32_t getDataPoolId() const { return dataPoolId; } /** * This operation sets the data pool id of the variable. * The method is necessary to set id's of data pool member variables with bad initialization. */ void setDataPoolId(uint32_t poolId) { dataPoolId = poolId; } /** * This method returns if the variable is write-only, read-write or read-only. */ ReadWriteMode_t getReadWriteMode() const { return readWriteMode; } /** * \brief With this call, the valid information of the variable is returned. */ bool isValid() const { if (valid) return true; else return false; } uint8_t getValid() { return valid; } void setValid(uint8_t valid) { this->valid = valid; } operator T() { return value; } operator T() const { return value; } PoolVariable& operator=(T newValue) { value = newValue; return *this; } PoolVariable& operator=(PoolVariable newPoolVariable) { value = newPoolVariable.value; return *this; } virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const override { return SerializeAdapter::serialize(&value, buffer, size, maxSize, streamEndianness); } virtual size_t getSerializedSize() const override { return SerializeAdapter::getSerializedSize(&value); } virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, Endianness streamEndianness) override { return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness); } }; typedef PoolVariable db_uint8_t; typedef PoolVariable db_uint16_t; typedef PoolVariable db_uint32_t; typedef PoolVariable db_int8_t; typedef PoolVariable db_int16_t; typedef PoolVariable db_int32_t; typedef PoolVariable db_bool_t; typedef PoolVariable db_float_t; typedef PoolVariable db_double_t; //Alternative (but I thing this is not as useful: code duplication, differences too small): //template //class PoolReader : public PoolVariableIF { //private: // uint32_t parameter_id; // uint8_t valid; //public: // T value; // PoolReader( uint32_t set_id, DataSetIF* set ) : parameter_id(set_id), valid(false), value(0) { // set->registerVariable( this ); // } // // ~PoolReader() {}; // // uint8_t commit() { // return HasReturnvaluesIF::RETURN_OK; // } // // uint8_t read() { // PoolEntry* read_out = ::dataPool.getData( parameter_id, 1 ); // if ( read_out != NULL ) { // valid = read_out->valid; // value = *(read_out->address); // return HasReturnvaluesIF::RETURN_OK; // } else { // value = 0; // valid = false; // return CHECKOUT_FAILED; // } // } // uint32_t getParameterId() { return parameter_id; } // bool isWritable() { return false; }; // bool isValid() { if (valid) return true; else return false; } //}; // //template //class PoolWriter : public PoolVariableIF { //private: // uint32_t parameter_id; //public: // T value; // PoolWriter( uint32_t set_id, DataSetIF* set ) : parameter_id(set_id), value(0) { // set->registerVariable( this ); // } // // ~PoolWriter() {}; // // uint8_t commit() { // PoolEntry* write_back = ::dataPool.getData( parameter_id, 1 ); // if ( write_back != NULL ) { // write_back->valid = true; // *(write_back->address) = value; // return HasReturnvaluesIF::RETURN_OK; // } else { // return CHECKOUT_FAILED; // } // } // uint8_t read() { // PoolEntry* read_out = ::dataPool.getData( parameter_id, 1 ); // if ( read_out != NULL ) { // value = *(read_out->address); // return HasReturnvaluesIF::RETURN_OK; // } else { // value = 0; // return CHECKOUT_FAILED; // } // } // uint32_t getParameterId() { return parameter_id; } // bool isWritable() { return true; }; // bool isValid() { return false; } //}; #endif /* POOLVARIABLE_H_ */