This is a structure for bare metal symmetric multi-programming where each thread operates exclusively on a different section of the output.
pub struct SharedMatrix<'a> {
matrix: UnsafeCell<Matrix>,
sections: UnsafeCell<Option<[Option<MatrixSection<'a>>; N_HARTS]>>,
initializing: AtomicBool,
initialized: AtomicBool,
section_available: [AtomicBool; N_HARTS],
computation_completed: AtomicUsize,
}
impl<'a> SharedMatrix<'a> {
pub const fn new() -> Self {
SharedMatrix {
matrix: UnsafeCell::new(Matrix::zeroes()),
sections: UnsafeCell::new(None),
initializing: AtomicBool::new(false),
initialized: AtomicBool::new(false),
section_available: [
AtomicBool::new(true),
AtomicBool::new(true),
AtomicBool::new(true),
AtomicBool::new(true),
],
computation_completed: AtomicUsize::new(0),
}
}
...
}
I'd like to make the shared structure generic over the inner type, so that I can use it to share other structures than a matrix (SharedMatrix
contains some methods to allow to get mutable references to part of it and keep track of if a section is available etc.). However, when I write the generic code I run into a problem:
pub trait SectionsMut {
type Section;
fn sections_mut(&mut self) -> [Option<Self::Section>; N_HARTS];
}
pub struct SharedStructure<Inner: SectionsMut<Section = InnerSection>, InnerSection> {
data: UnsafeCell<Inner>,
sections: UnsafeCell<Option<[Option<InnerSection>; N_HARTS]>>,
initializing: AtomicBool,
initialized: AtomicBool,
section_available: [AtomicBool; N_HARTS],
computation_completed: AtomicUsize,
}
impl<Inner: SectionsMut<Section = InnerSection>, InnerSection>
SharedStructure<Inner, InnerSection>
{
pub const fn new() -> Self {
SharedStructure {
data: UnsafeCell::new(Inner::zeroes()),
sections: UnsafeCell::new(None),
initializing: AtomicBool::new(false),
initialized: AtomicBool::new(false),
section_available: [
AtomicBool::new(true),
AtomicBool::new(true),
AtomicBool::new(true),
AtomicBool::new(true),
],
computation_completed: AtomicUsize::new(0),
}
}
...
}
The new
method has to be const
because the structure needs to be initialized in a static context to be shared amongst the threads, so Inner::zeroes()
has to be const
. These are the solutions I came up with:
- Have a
pub trait ConstInit {}
that containsconst fn zeroes() -> Self
and add it as a trait bound onInner
, however a trait cannot have aconst
member - Pass a
const fn
to thenew()
method onSharedStructure
to handle the initialization, which does not compile as well
What would you advise as a possible alternative?