StorageManagerIF thoughts #68
Labels
No Label
API Change
Breaking API Change
bug
build
cosmetics
Documentation
duplicate
feature
help wanted
hotfix
invalid
question
Refactor
Tests
wontfix
No Milestone
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: fsfw/fsfw#68
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The Pool Manager implements thread-safe access to functions like reserveSpace / deleteData, the read functions are not protected yet from what I have seen.
Right now, the read functions take pointers and set them to the respective addresses in the local pool.
I've wondered what happens if the read function is called and then the data is changed by another thread/task before doing something with that data. I guess the read functions are not really thread-safe but maybe I have forgotten some details..
Anyway, a thread-safe implementation of a read call could be implemented like the other PoolManager functions if a copy is performed. I think this would be a nice feature anyway and it would make usage of the pool more explicit. I passed pointers to an array to the
getData()
function multiple times and wondered why no data was written to the array. AgetDataCopy()
function would be nice to get a copy of the data in the local pool (with a lock protection for the pool manager override), aretrieve()
function would also be nice to get a copy and then delete the data (again with lock protection for the pool manager override).Another way would be to lock the pool in the getData() and modifyData() calls for the pool manager by creating a mutex helper on the heap and return a
std::unique_ptr<MutexHelper> mutexLock
to that mutex helper object to the caller. then the caller has access to the locked datapool and is responsible for unlocking the datapool, or unlocking happens automatically when the pointer gets out of scope. Move semantics allow the transfer the ownership of the unique_ptr to the caller.A more simple option would be to forbid
modifyData()
in the StorageManager.UPDATE: I declared the overriden
modifyData()
private and code is still compiling without issues.On another note (maybe sth for another issue):
Usually, a message is sent with a storeId to the data in the pool, which is then expected to be deleted. It's easy to forget a deletion operation. If we send around a
std::shared_ptr
instead which is tied to a StorageHelper on the heap containing the store address which callsdeleteData()
automatically on destruction, the deletion would be performed automatically (RAII!). It's a little bit more overhead for a higher safety which does not depend on a developer forgetting something.Thread Safety LocalPool read functionto StorageManagerIF thoughtsYou're right the getData call is not thread safe. This was avoided by policy. The used pattern was:
The data in the pool can be quite large. Usually, we avoid copying such vast amount of data. There are parts of the software, where we actually can't avoid that. The weak enforcment of the deletion call is a problem, so the retrieve call might be interessting for small amounts of data but you have to know the size of the data which is coming in to prelocate an array. But otherwise you should use the modifyData call to modify the data inplace if you want to do modify it.
So you passed a pointer instead of a pointer pointer?
This will make the pattern of sending data to a third thread or modifying something in place useless. I don't think we make modifyData private. The unique_ptr solution sounds interessting. We should look into that one.
I don't think that this works. The data of a message is send over a message queue and no C++ Objects survives this very well. We would have to allocate that pointer on the heap and need to delete that one then. So, in this case someone will forget to delete the shared_ptr and thereby forgets to delete the data aswell or maybe I did not get shared_ptr right. We could do something like this: https://stackoverflow.com/questions/25667226/how-can-i-use-shared-ptr-using-postthreadmessage/25671987#25671987
The policy makes perfect sense. It would be good to document it in the pool manager. Interesting note: making modifyData() private compiled, but the unit test failed.
I actually passed pointer to pointer, but the underlying pointer was retrieved with the data() function of a std::array.
SOmething along the lines of
(see Unit Tests)
I will have a look at it again...
After some research, I have found out that std::array is not assignable.
I can look into the unique_ptr solution.Question is: what happens if the caller tries to call getData() twice and in the same scope and forgets to reset the first unique_ptr... there propably will be a mutex lock error, right?
I tried some experiments:
http://cpp.sh/9ihry
Just like you said, it's allocated on the heap. A not very elegant combination of new, move semantics, and other stuff, but it deletes itself after going out of scope. However, sending a pointer via a message queue is kind of annoying. Pointers can have different sizes.. I will test this with freeRTOS (32 bit) and on linux(64 bit), but I think I had some issues with creating mqueues on linux..
Okay, this has been basically reduced to the new Accessor objects.