diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp index a068d1694..51b93f110 100644 --- a/storagemanager/StorageAccessor.cpp +++ b/storagemanager/StorageAccessor.cpp @@ -1,154 +1,130 @@ -//#include -// -//ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): storeId(storeId) {} -// -//ConstStorageAccessor::~ConstStorageAccessor() { -// if(deleteData and store != nullptr) { -// sif::debug << "deleting store data" << std::endl; -// store->deleteDataNonLocking(storeId); -// } -// if(mutexLock != nullptr) { -// sif::debug << "unlocking mutex lock" << std::endl; -// mutexLock.reset(); -// } -//} -// -//ConstStorageAccessor& ConstStorageAccessor::operator=( -// ConstStorageAccessor&& other) { -// constDataPointer = other.constDataPointer; -// storeId = other.storeId; -// store = other.store; -// size_ = other.size_; -// deleteData = other.deleteData; -// this->store = other.store; -// // Transfer ownership of the lock. -// mutexLock = std::move(other.mutexLock); -// // This prevents double deletion of the resource -// other.mutexLock = nullptr; -// // This prevent premature deletion -// other.store = nullptr; -// return *this; -//} -// -//StorageAccessor::StorageAccessor(store_address_t storeId): -// ConstStorageAccessor(storeId) { -//} -// -//StorageAccessor& StorageAccessor::operator =( -// StorageAccessor&& other) { -// // Call the parent move assignment and also assign own member. -// dataPointer = other.dataPointer; -// StorageAccessor::operator=(std::move(other)); -// return * this; -//} -// -//// Call the parent move ctor and also transfer own member. -//StorageAccessor::StorageAccessor(StorageAccessor&& other): -// ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { -//} -// -//ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): -// constDataPointer(other.constDataPointer), storeId(other.storeId), -// size_(other.size_), store(other.store), deleteData(other.deleteData), -// internalState(other.internalState) { -// // Transfer ownership of the lock. -// mutexLock = std::move(other.mutexLock); -// // This prevents double deletion of the resource. Not strictly necessary, -// // from the testing I have conducted so far but I am not familiar enough -// // with move semantics so I will just set the other lock to nullptr for now. -// other.mutexLock = nullptr; -// // This prevent premature deletion -// other.store = nullptr; -//} -// -//const uint8_t* ConstStorageAccessor::data() const { -// return constDataPointer; -//} -// -//size_t ConstStorageAccessor::size() const { -// if(internalState == AccessState::UNINIT) { -// sif::warning << "StorageAccessor: Not initialized!" << std::endl; -// } -// return size_; -//} -// -//void ConstStorageAccessor::getDataCopy(uint8_t *pointer) { -// if(internalState == AccessState::UNINIT) { -// sif::warning << "StorageAccessor: Not initialized!" << std::endl; -// return; -// } -// std::copy(constDataPointer, constDataPointer + size_, pointer); -//} -// -//void ConstStorageAccessor::release() { -// deleteData = false; -//} -// -//ReturnValue_t ConstStorageAccessor::lock(MutexIF* mutex, uint32_t mutexTimeout) { -// if(mutexLock == nullptr) { -// mutexLock = std::unique_ptr(new MutexHelper(mutex, mutexTimeout)); -// return mutexLock.get()->getResult(); -// } -// else { -// sif::warning << "StorageAccessor: Attempted to lock twice. Check code!" << std::endl; -// return HasReturnvaluesIF::RETURN_FAILED; -// } -//} -// -//void ConstStorageAccessor::unlock() { -// if(mutexLock != nullptr) { -// mutexLock.reset(); -// } -//} -// -//store_address_t ConstStorageAccessor::getId() const { -// return storeId; -//} -// -//void ConstStorageAccessor::print() const { -// if(internalState == AccessState::UNINIT) { -// sif::warning << "StorageAccessor: Not initialized!" << std::endl; -// return; -// } -// sif::info << "StorageAccessor: Printing data: ["; -// for(uint16_t iPool = 0; iPool < size_; iPool++) { -// sif::info << std::hex << (int)constDataPointer[iPool]; -// if(iPool < size_ - 1){ -// sif::info << " , "; -// } -// } -// sif::info << " ] " << std::endl; -//} -// -//void ConstStorageAccessor::assignStore(StorageManagerIF* store) { -// internalState = AccessState::READ; -// this->store = store; -//} -// -// -//uint8_t* StorageAccessor::data() { -// if(internalState == AccessState::UNINIT) { -// sif::warning << "StorageAccessor: Not initialized!" << std::endl; -// } -// return dataPointer; -//} -// -//ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, -// uint16_t offset) { -// if(internalState == AccessState::UNINIT) { -// sif::warning << "StorageAccessor: Not initialized!" << std::endl; -// return HasReturnvaluesIF::RETURN_FAILED; -// } -// if(offset + size > size_) { -// sif::error << "StorageAccessor: Data too large for pool entry!" << std::endl; -// return HasReturnvaluesIF::RETURN_FAILED; -// } -// std::copy(data, data + size, dataPointer); -// return HasReturnvaluesIF::RETURN_OK; -//} -// -//void StorageAccessor::assignConstPointer() { -// constDataPointer = dataPointer; -//} -// -// +#include + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): + storeId(storeId) {} + +ConstStorageAccessor::~ConstStorageAccessor() { + if(deleteData and store != nullptr) { + sif::debug << "deleting store data" << std::endl; + store->deleteData(storeId); + } +} + +ConstStorageAccessor& ConstStorageAccessor::operator=( + ConstStorageAccessor&& other) { + constDataPointer = other.constDataPointer; + storeId = other.storeId; + store = other.store; + size_ = other.size_; + deleteData = other.deleteData; + this->store = other.store; + // This prevents premature deletion + other.store = nullptr; + return *this; +} + +StorageAccessor::StorageAccessor(store_address_t storeId): + ConstStorageAccessor(storeId) { +} + +StorageAccessor& StorageAccessor::operator =( + StorageAccessor&& other) { + // Call the parent move assignment and also assign own member. + dataPointer = other.dataPointer; + StorageAccessor::operator=(std::move(other)); + return * this; +} + +// Call the parent move ctor and also transfer own member. +StorageAccessor::StorageAccessor(StorageAccessor&& other): + ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { +} + +ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): + constDataPointer(other.constDataPointer), storeId(other.storeId), + size_(other.size_), store(other.store), deleteData(other.deleteData), + internalState(other.internalState) { + // This prevent premature deletion + other.store = nullptr; +} + +const uint8_t* ConstStorageAccessor::data() const { + return constDataPointer; +} + +size_t ConstStorageAccessor::size() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return size_; +} + +ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, + size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(constDataPointer, constDataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +void ConstStorageAccessor::release() { + deleteData = false; +} + +store_address_t ConstStorageAccessor::getId() const { + return storeId; +} + +void ConstStorageAccessor::print() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return; + } + sif::info << "StorageAccessor: Printing data: ["; + for(uint16_t iPool = 0; iPool < size_; iPool++) { + sif::info << std::hex << (int)constDataPointer[iPool]; + if(iPool < size_ - 1){ + sif::info << " , "; + } + } + sif::info << " ] " << std::endl; +} + +void ConstStorageAccessor::assignStore(StorageManagerIF* store) { + internalState = AccessState::READ; + this->store = store; +} + + +uint8_t* StorageAccessor::data() { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return dataPointer; +} + +ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, + uint16_t offset) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(offset + size > size_) { + sif::error << "StorageAccessor: Data too large for pool entry!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(data, data + size, dataPointer); + return HasReturnvaluesIF::RETURN_OK; +} + +void StorageAccessor::assignConstPointer() { + constDataPointer = dataPointer; +} + + diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index d391c5c26..2e1d44bd1 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,174 +1,152 @@ -///** -// * @brief Helper classes to facilitate safe access to storages which is also -// * conforming to RAII principles -// * @details These helper can be used together with the -// * StorageManager classes to manage access to a storage. -// * It can take care of thread-safety while also providing -// * mechanisms to automatically clear storage data and unlocking the -// * pool. -// */ -//#ifndef TEST_PROTOTYPES_STORAGEACCESSOR_H_ -//#define TEST_PROTOTYPES_STORAGEACCESSOR_H_ -// -//#include -//#include -//#include -// -// -///** -// * @brief Accessor class which can be returned by pool managers -// * or passed and set by pool managers to have safe access to the pool -// * resources. -// */ -//class ConstStorageAccessor { -// //! StorageManager classes have exclusive access to private variables. -// template -// friend class PoolManager; -// template -// friend class LocalPool; -//public: -// /** -// * @brief Simple constructor which takes the store ID of the storage -// * entry to access. -// * @param storeId -// */ -// ConstStorageAccessor(store_address_t storeId); -// -// /** -// * @brief Move ctor and move assignment allow returning accessors as -// * a returnvalue. They prevent resource being free prematurely. -// * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ -// * move-constructors-and-move-assignment-operators-cpp.md -// * @param -// * @return -// */ -// ConstStorageAccessor& operator= (ConstStorageAccessor&&); -// ConstStorageAccessor (ConstStorageAccessor&&); -// -// //! The copy ctor and copy assignemnt should be deleted implicitely -// //! according to https://foonathan.net/2019/02/special-member-functions/ -// //! but I still deleted them to make it more explicit. (remember rule of 5). -// ConstStorageAccessor& operator= (ConstStorageAccessor&) = delete; -// ConstStorageAccessor (ConstStorageAccessor&) = delete; -// -// /** -// * @brief The destructor in default configuration takes care of -// * deleting the accessed pool entry and unlocking the mutex -// */ -// virtual ~ConstStorageAccessor(); -// -// /** -// * @brief Returns a pointer to the read-only data -// * @return -// */ -// const uint8_t* data() const; -// -// /** -// * @brief Copies the read-only data to the supplied pointer -// * @param pointer -// */ -// void getDataCopy(uint8_t *pointer); -// -// /** -// * @brief Calling this will prevent the Accessor from deleting the data -// * when the destructor is called. -// */ -// void release(); -// /** -// * @brief Locks the supplied mutex. -// * @details -// * The mutex will be unlocked automatically -// * when this class is destroyed (for example when exiting the scope). -// * Only one mutex can be locked at a time! -// * @param mutex -// * @param mutexTimeout -// * @return -// */ -// ReturnValue_t lock(MutexIF* mutex, -// uint32_t mutexTimeout = MutexIF::NO_TIMEOUT); -// /** -// * @brief Unlocks the mutex (if one has been locked previously). -// * Unless this function is called, the mutex is unlocked -// * when the class exits the scope. -// */ -// void unlock(); -// -// -// /** -// * Get the size of the data -// * @return -// */ -// size_t size() const; -// -// /** -// * Get the storage ID. -// * @return -// */ -// store_address_t getId() const; -// -// void print() const; -//protected: -// const uint8_t* constDataPointer = nullptr; -// store_address_t storeId; -// size_t size_ = 0; -// //! Managing pool, has to assign itself. -// StorageManagerIF* store = nullptr; -// //! Unique pointer to the mutex lock instance. Is initialized by -// //! the pool manager. -// std::unique_ptr mutexLock = nullptr; -// bool deleteData = true; -// -// enum class AccessState { -// UNINIT, -// READ -// }; -// //! Internal state for safety reasons. -// AccessState internalState = AccessState::UNINIT; -// /** -// * Used by the pool manager instances to assign themselves to the -// * accessor. This is necessary to delete the data when the acessor -// * exits the scope ! The internal state will be considered read -// * when this function is called, so take care all data is set properly as -// * well. -// * @param -// */ -// void assignStore(StorageManagerIF*); -// -//}; -// -// -///** -// * @brief Child class for modifyable data. Also has a normal pointer member. -// */ -//class StorageAccessor: public ConstStorageAccessor { -// //! StorageManager classes have exclusive access to private variables. -// template -// friend class PoolManager; -// template -// friend class LocalPool; -//public: -// StorageAccessor(store_address_t storeId); -// /** -// * @brief Move ctor and move assignment allow returning accessors as -// * a returnvalue. They prevent resource being free prematurely. -// * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ -// * move-constructors-and-move-assignment-operators-cpp.md -// * @param -// * @return -// */ -// StorageAccessor& operator= (StorageAccessor&&); -// StorageAccessor (StorageAccessor&&); -// -// ReturnValue_t write(uint8_t *data, size_t size, -// uint16_t offset); -// uint8_t* data(); -// -//private: -// //! Non-const pointer for modifyable data. -// uint8_t* dataPointer = nullptr; -// //! For modifyable data, the const pointer is assigned to the normal -// //! pointer by the pool manager so both access functions can be used safely -// void assignConstPointer(); -//}; -// -//#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ +/** + * @brief Helper classes to facilitate safe access to storages which is also + * conforming to RAII principles + * @details These helper can be used together with the + * StorageManager classes to manage access to a storage. + * It can take care of thread-safety while also providing + * mechanisms to automatically clear storage data and unlocking the + * pool. + */ +#ifndef TEST_PROTOTYPES_STORAGEACCESSOR_H_ +#define TEST_PROTOTYPES_STORAGEACCESSOR_H_ + +#include +#include +#include + + +/** + * @brief Accessor class which can be returned by pool managers + * or passed and set by pool managers to have safe access to the pool + * resources. + */ +class ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + /** + * @brief Simple constructor which takes the store ID of the storage + * entry to access. + * @param storeId + */ + ConstStorageAccessor(store_address_t storeId); + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + ConstStorageAccessor& operator= (ConstStorageAccessor&&); + ConstStorageAccessor (ConstStorageAccessor&&); + + //! The copy ctor and copy assignemnt should be deleted implicitely + //! according to https://foonathan.net/2019/02/special-member-functions/ + //! but I still deleted them to make it more explicit. (remember rule of 5). + ConstStorageAccessor& operator= (ConstStorageAccessor&) = delete; + ConstStorageAccessor (ConstStorageAccessor&) = delete; + + /** + * @brief The destructor in default configuration takes care of + * deleting the accessed pool entry and unlocking the mutex + */ + virtual ~ConstStorageAccessor(); + + /** + * @brief Returns a pointer to the read-only data + * @return + */ + const uint8_t* data() const; + + /** + * @brief Copies the read-only data to the supplied pointer + * @param pointer + */ + ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); + + /** + * @brief Calling this will prevent the Accessor from deleting the data + * when the destructor is called. + */ + void release(); + + /** + * Get the size of the data + * @return + */ + size_t size() const; + + /** + * Get the storage ID. + * @return + */ + store_address_t getId() const; + + void print() const; +protected: + const uint8_t* constDataPointer = nullptr; + store_address_t storeId; + size_t size_ = 0; + //! Managing pool, has to assign itself. + StorageManagerIF* store = nullptr; + bool deleteData = true; + + enum class AccessState { + UNINIT, + READ + }; + //! Internal state for safety reasons. + AccessState internalState = AccessState::UNINIT; + /** + * Used by the pool manager instances to assign themselves to the + * accessor. This is necessary to delete the data when the acessor + * exits the scope ! The internal state will be considered read + * when this function is called, so take care all data is set properly as + * well. + * @param + */ + void assignStore(StorageManagerIF*); + +}; + + +/** + * @brief Child class for modifyable data. Also has a normal pointer member. + */ +class StorageAccessor: public ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + StorageAccessor(store_address_t storeId); + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + StorageAccessor& operator= (StorageAccessor&&); + StorageAccessor (StorageAccessor&&); + + ReturnValue_t write(uint8_t *data, size_t size, + uint16_t offset); + uint8_t* data(); + +private: + //! Non-const pointer for modifyable data. + uint8_t* dataPointer = nullptr; + //! For modifyable data, the const pointer is assigned to the normal + //! pointer by the pool manager so both access functions can be used safely + void assignConstPointer(); +}; + +#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */