Conceptually, we're looking to create multiple memory pools, with each pool individually acting as a stack. Within each stack, we allocate objects of varying sizes and free them up in a stack-like fashion. We also want to be able to allocate memory from the stacks in an ad-hoc fashion, and not iteratively visit each stack in order.
We found the Scratchpad crate which does the stack allocation and freeing.
The problem is that an allocation is statically bound to the lifetime of the Marker
and the Marker
is statically bound to the lifetime of the Scratchpad
. While we don’t want allocations to outlive the corresponding allocated memory, the lifetime check makes it difficult (or perhaps impossible?) to put the scratchpad, markers and allocations in one object.
In the simple example shown, this can be worked around by including the Scratchpad by reference, but I’m not sure that this can be generalized to the use case that we want where multiple markers and allocations are stored together.
Here is the sample code which does not compile:
extern crate scratchpad;
use scratchpad::{MarkerFront, Scratchpad};
#[derive(Debug)]
struct Stuff<'sp: 'a, 'a> {
scratchpad: Scratchpad<&'sp mut [u8], &'sp mut [usize]>,
marker: Option<MarkerFront<'a, &'sp mut [u8], &'sp mut [usize]>>,
}
fn main() {
let pool0: &mut [u8] = &mut [0; 1024];
let pool1: &mut [usize] = &mut [0; 64];
let sp = Scratchpad::new(pool0, pool1);
let mut stuff = Stuff {
scratchpad: sp,
marker: None,
};
stuff.marker = Some(stuff.scratchpad.mark_front().unwrap());
println!("{:?}", stuff);
stuff.marker = None;
println!("{:?}", stuff);
}
error[E0597]: `stuff.scratchpad` does not live long enough
--> src/main.rs:19:25
|
19 | stuff.marker = Some(stuff.scratchpad.mark_front().unwrap());
| ^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
23 | }
| - `stuff.scratchpad` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
Sample code which does compile:
extern crate scratchpad;
use scratchpad::{MarkerFront, Scratchpad};
#[derive(Debug)]
struct Stuff<'sp: 'a, 'a> {
// This is now a reference
scratchpad: &'sp Scratchpad<&'sp mut [u8], &'sp mut [usize]>,
marker: Option<MarkerFront<'a, &'sp mut [u8], &'sp mut [usize]>>,
}
fn main() {
let pool0: &mut [u8] = &mut [0; 1024];
let pool1: &mut [usize] = &mut [0; 64];
let sp = Scratchpad::new(pool0, pool1);
let mut stuff = Stuff {
scratchpad: &sp,
marker: None,
};
stuff.marker = Some(stuff.scratchpad.mark_front().unwrap());
println!("{:?}", stuff);
stuff.marker = None;
println!("{:?}", stuff);
}