Skip to content

Replace to_tuple and from_tuple with a field pointer based approach #11

@aapoalas

Description

@aapoalas

While safer (and avoids issues with mistakenly deriving SoAble on a type with Drop), it may be less efficient (depending on compiler optimisations) and at the very least more redundant to rely on the SoAble::to_tuple / SoAble::from_tuple methods for moving between T and "T inside SoAVec allocation".

A more optimal but unsafe choice would be a method SoAble::get_field_pointers that takes an exclusive reference to possibly uninitialised T, and returns T::TupleRepr::Pointers pointing at the fields of T. This API can be used to then efficiently either copy data out of T (when moving from T to "T inside SoAVec allocation") field by field, or to initialise the fields of T (when doing the reverse).

fn push(value: T) {
  let mut value = MaybeUninit::new(value); // moves value into MU; dropping the MU does not drop `value` anymore.
  let field_pointers = unsafe { T::get_field_pointers(&mut value) }; // probably unsafe to do this, gotta think on it
  let soa_pointers = T::TupleRepr::get_pointers(self.buf.as_ptr(), self.capacity(), self.len());
  T::TupleRepr::copy(field_pointers, soa_pointers, 1); // copy field pointers into soa
}

fn pop() -> Option<T> {
  if self.is_empty() {
    return None;
  }
  let mut value: MaybeUninit::uninit();
  let field_pointers = T::get_field_pointers(&mut value);
  self.set_len(self.len() - 1);
  let soa_pointers = T::TupleRepr::get_pointers(self.buf.as_ptr(), self.capacity(), self.len());
  T::TupleRepr::copy(soa_pointers, field_pointers, 1); // copy soa pointers into value; this initialises it
  Some(value.assume_init())
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions