You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We have three recursive functions that can be found by searching for -no-recursion, all of them performing tree traversal:
rxFragmentDestroyTree -- simply descends the tree to deallocate every node;
rxSessionDestroyTree -- ditto;
rxSlotEjectFragment -- a complicated beast.
All of them, especially the first two, can be transformed into recursion-free alternatives but that comes at a cost of either:
Using an additional container for keeping temporary state during traversal. Currently, we use the call stack for that.
Extending each node with additional state to allow navigation through the tree during traversal.
The first option requires log2 memory and it could be implemented by asking the user for some storage area; the required size depends on the number of nodes on the network (worst case 65535 nodes) or the number of fragments in a transfer (worst case $2^{31}$ fragments). This is not a lot of memory; the maximum depth of an AVL tree is $\lceil{} 1.44 \log_2(N) - 0.328 \rceil{}$, which in our case evaluates to 45 levels.
The second option requires linear memory that will be allocated together with each item in the tree. It is linear as opposed to logarithmic because only a small fraction of the memory will be used at any given time during tree traversal. While this solution is wasteful memory-wise, it does not complicate the API because it does not require the user to provide extra storage explicitly (it is taken from the memory resource implicitly).
Another idea that expands upon the first option is to make a static thread-local stack of 45 elements defined internally within the library. This way we can implement the first option without extending the API.
Recursive functions violate MISRA C:2012 rule 17.2.
We have three recursive functions that can be found by searching for
-no-recursion
, all of them performing tree traversal:rxFragmentDestroyTree
-- simply descends the tree to deallocate every node;rxSessionDestroyTree
-- ditto;rxSlotEjectFragment
-- a complicated beast.All of them, especially the first two, can be transformed into recursion-free alternatives but that comes at a cost of either:
The first option requires log2 memory and it could be implemented by asking the user for some storage area; the required size depends on the number of nodes on the network (worst case 65535 nodes) or the number of fragments in a transfer (worst case$2^{31}$ fragments). This is not a lot of memory; the maximum depth of an AVL tree is $\lceil{} 1.44 \log_2(N) - 0.328 \rceil{}$ , which in our case evaluates to 45 levels.
The second option requires linear memory that will be allocated together with each item in the tree. It is linear as opposed to logarithmic because only a small fraction of the memory will be used at any given time during tree traversal. While this solution is wasteful memory-wise, it does not complicate the API because it does not require the user to provide extra storage explicitly (it is taken from the memory resource implicitly).
Another idea that expands upon the first option is to make a static thread-local stack of 45 elements defined internally within the library. This way we can implement the first option without extending the API.
Originally posted by @pavel-kirienko in #43 (comment)
The text was updated successfully, but these errors were encountered: