Merge pull request 'Pool docs improvements' (#105) from pool-docs-improvements into main
All checks were successful
Rust/sat-rs/pipeline/head This commit looks good
All checks were successful
Rust/sat-rs/pipeline/head This commit looks good
Reviewed-on: #105
This commit is contained in:
commit
712dc718f9
@ -5,7 +5,14 @@ High-level documentation of the [sat-rs project](https://absatsw.irs.uni-stuttga
|
|||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
If you have not done so, install `mdbook` using `cargo install mdbook --locked`.
|
If you have not done so, install the pre-requisites first:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo install mdbook --locked
|
||||||
|
cargo install mdbook-linkcheck --locked
|
||||||
|
```
|
||||||
|
|
||||||
|
After that, you can build the book with:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mdbook build
|
mdbook build
|
||||||
|
@ -11,7 +11,8 @@ time where the OBSW might be running on Linux based systems with hundreds of MBs
|
|||||||
|
|
||||||
A useful pattern used commonly in space systems is to limit heap allocations to program
|
A useful pattern used commonly in space systems is to limit heap allocations to program
|
||||||
initialization time and avoid frequent run-time allocations. This prevents issues like
|
initialization time and avoid frequent run-time allocations. This prevents issues like
|
||||||
running out of memory (something even Rust can not protect from) or heap fragmentation.
|
running out of memory (something even Rust can not protect from) or heap fragmentation on systems
|
||||||
|
without a MMU.
|
||||||
|
|
||||||
# Using pre-allocated pool structures
|
# Using pre-allocated pool structures
|
||||||
|
|
||||||
@ -24,6 +25,12 @@ For example, a very small telecommand (TC) pool might look like this:
|
|||||||
|
|
||||||
![Example Pool](images/pools/static-pools.png)
|
![Example Pool](images/pools/static-pools.png)
|
||||||
|
|
||||||
|
The core of the pool abstractions is the
|
||||||
|
[PoolProvider trait](https://docs.rs/satrs-core/0.1.0-alpha.3/satrs_core/pool/trait.PoolProvider.html).
|
||||||
|
This trait specifies the general API a pool structure should have without making assumption
|
||||||
|
of how the data is stored.
|
||||||
|
|
||||||
|
This trait is implemented by a static memory pool implementation.
|
||||||
The code to generate this static pool would look like this:
|
The code to generate this static pool would look like this:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@ -39,21 +46,27 @@ let tc_pool = StaticMemoryPool::new(StaticPoolConfig::new(vec![
|
|||||||
|
|
||||||
It should be noted that the buckets only show the maximum size of data being stored inside them.
|
It should be noted that the buckets only show the maximum size of data being stored inside them.
|
||||||
The store will keep a separate structure to track the actual size of the data being stored.
|
The store will keep a separate structure to track the actual size of the data being stored.
|
||||||
|
|
||||||
<!-- TODO: Add explanation and references for used data-structures. Also explain core trait
|
|
||||||
to work with the pool. -->
|
|
||||||
|
|
||||||
A TC entry inside this pool has a store address which can then be sent around without having
|
A TC entry inside this pool has a store address which can then be sent around without having
|
||||||
to dynamically allocate memory. The same principle can also be applied to the telemetry (TM) and
|
to dynamically allocate memory. The same principle can also be applied to the telemetry (TM) and
|
||||||
inter-process communication (IPC) data.
|
inter-process communication (IPC) data.
|
||||||
|
|
||||||
|
You can read
|
||||||
|
|
||||||
|
- [`StaticPoolConfig` API](https://docs.rs/satrs-core/0.1.0-alpha.3/satrs_core/pool/struct.StaticPoolConfig.html)
|
||||||
|
- [`StaticMemoryPool` API](https://docs.rs/satrs-core/0.1.0-alpha.3/satrs_core/pool/struct.StaticMemoryPool.html)
|
||||||
|
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
In the future, optimized pool structures which use standard containers or are
|
||||||
|
[`Sync`](https://doc.rust-lang.org/std/marker/trait.Sync.html) by default might be added as well.
|
||||||
|
|
||||||
# Using special crates to prevent smaller allocations
|
# Using special crates to prevent smaller allocations
|
||||||
|
|
||||||
Another common way to use the heap on host systems is using containers like `String` and `Vec<u8>`
|
Another common way to use the heap on host systems is using containers like `String` and `Vec<u8>`
|
||||||
to work with data where the size is not known beforehand. The most common solution for embedded
|
to work with data where the size is not known beforehand. The most common solution for embedded
|
||||||
systems is to determine the maximum expected size and then use a pre-allocated `u8` buffer and a
|
systems is to determine the maximum expected size and then use a pre-allocated `u8` buffer and a
|
||||||
size variable. Alternatively, you can use the following crates for more convenience or a smart
|
size variable. Alternatively, you can use the following crates for more convenience or a smart
|
||||||
behaviour which at the very least reduce heap allocations:
|
behaviour which at the very least reduces heap allocations:
|
||||||
|
|
||||||
1. [`smallvec`](https://docs.rs/smallvec/latest/smallvec/).
|
1. [`smallvec`](https://docs.rs/smallvec/latest/smallvec/).
|
||||||
2. [`arrayvec`](https://docs.rs/arrayvec/latest/arrayvec/index.html) which also contains an
|
2. [`arrayvec`](https://docs.rs/arrayvec/latest/arrayvec/index.html) which also contains an
|
||||||
|
@ -203,8 +203,12 @@ impl Error for StoreError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generic trait for pool providers where the data can be modified and read in-place. This
|
/// Generic trait for pool providers which provide memory pools for variable sized data.
|
||||||
/// generally means that a shared pool structure has to be wrapped inside a lock structure.
|
///
|
||||||
|
/// It specifies a basic API to [Self::add], [Self::modify], [Self::read] and [Self::delete] data
|
||||||
|
/// in the store at its core. The API was designed so internal optimizations can be performed
|
||||||
|
/// more easily and that is is also possible to make the pool structure [Sync] without the whole
|
||||||
|
/// pool structure being wrapped inside a lock.
|
||||||
pub trait PoolProvider {
|
pub trait PoolProvider {
|
||||||
/// Add new data to the pool. The provider should attempt to reserve a memory block with the
|
/// Add new data to the pool. The provider should attempt to reserve a memory block with the
|
||||||
/// appropriate size and then copy the given data to the block. Yields a [StoreAddr] which can
|
/// appropriate size and then copy the given data to the block. Yields a [StoreAddr] which can
|
||||||
@ -251,6 +255,7 @@ pub trait PoolProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extension trait which adds guarded pool access classes.
|
||||||
pub trait PoolProviderWithGuards: PoolProvider {
|
pub trait PoolProviderWithGuards: PoolProvider {
|
||||||
/// This function behaves like [PoolProvider::read], but consumes the provided address
|
/// This function behaves like [PoolProvider::read], but consumes the provided address
|
||||||
/// and returns a RAII conformant guard object.
|
/// and returns a RAII conformant guard object.
|
||||||
@ -280,7 +285,8 @@ pub struct PoolGuard<'a, MemProvider: PoolProvider + ?Sized> {
|
|||||||
deletion_failed_error: Option<StoreError>,
|
deletion_failed_error: Option<StoreError>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This helper object
|
/// This helper object can be used to safely access pool data without worrying about memory
|
||||||
|
/// leaks.
|
||||||
impl<'a, MemProvider: PoolProvider> PoolGuard<'a, MemProvider> {
|
impl<'a, MemProvider: PoolProvider> PoolGuard<'a, MemProvider> {
|
||||||
pub fn new(pool: &'a mut MemProvider, addr: StoreAddr) -> Self {
|
pub fn new(pool: &'a mut MemProvider, addr: StoreAddr) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -390,16 +396,21 @@ mod alloc_mod {
|
|||||||
|
|
||||||
/// Pool implementation providing sub-pools with fixed size memory blocks.
|
/// Pool implementation providing sub-pools with fixed size memory blocks.
|
||||||
///
|
///
|
||||||
/// This is a simple memory pool implementation which pre-allocates all sub-pools using a given pool
|
/// This is a simple memory pool implementation which pre-allocates all subpools using a given
|
||||||
/// configuration. After the pre-allocation, no dynamic memory allocation will be performed
|
/// pool configuration. After the pre-allocation, no dynamic memory allocation will be
|
||||||
/// during run-time. This makes the implementation suitable for real-time applications and
|
/// performed during run-time. This makes the implementation suitable for real-time
|
||||||
/// embedded environments. The pool implementation will also track the size of the data stored
|
/// applications and embedded environments.
|
||||||
/// inside it.
|
///
|
||||||
|
/// The subpool bucket sizes only denote the maximum possible data size being stored inside
|
||||||
|
/// them and the pool implementation will still track the size of the data stored inside it.
|
||||||
|
/// The implementation will generally determine the best fitting subpool for given data to
|
||||||
|
/// add. Currently, the pool does not support spilling to larger subpools if the closest
|
||||||
|
/// fitting subpool is full. This might be added in the future.
|
||||||
///
|
///
|
||||||
/// Transactions with the [pool][StaticMemoryPool] are done using a generic
|
/// Transactions with the [pool][StaticMemoryPool] are done using a generic
|
||||||
/// [address][StoreAddr] type.
|
/// [address][StoreAddr] type. Adding any data to the pool will yield a store address.
|
||||||
/// Adding any data to the pool will yield a store address. Modification and read operations are
|
/// Modification and read operations are done using a reference to a store address. Deletion
|
||||||
/// done using a reference to a store address. Deletion will consume the store address.
|
/// will consume the store address.
|
||||||
pub struct StaticMemoryPool {
|
pub struct StaticMemoryPool {
|
||||||
pool_cfg: StaticPoolConfig,
|
pool_cfg: StaticPoolConfig,
|
||||||
pool: Vec<Vec<u8>>,
|
pool: Vec<Vec<u8>>,
|
||||||
|
Loading…
Reference in New Issue
Block a user