jeudi 25 juin 2020

packing a nested packed structs in a flat buffer in c++

I have something like the following code in my code base.

struct Data {
    int metadata_;
    int data_[3];
} __attribute__((__packed__));

struct GroupData {
    int metadata_;
    Data points_[4];
} __attribute__((__packed__));

struct Container {
    int metadata_; // encodes data about number clouds, and points
    GroupData point_clouds_[];
} __attribute__((__packed__));

I am tasked to design the code such to support varible size of data and points in my Data and GroupData structs with the following requirements.

  1. the container must remian POD (no cost serialization and deserialzation since we send this data over network very frequently)
  2. it must be as fast as possible, cost of adding virtual function and using type erasure maybe too much.
  3. sender of the data knows the size of data and points at compile time
  4. receiver on the other hand, can only parse this sizes from the metadata of Container, and should be able to easily consume this.

I have a couple of ideas on how to approach this problem, however each technique comes with some major drawbacks, I was wondering if someone with more experience would have a better solution to the problem?

template the sizes

template <int N>
struct Data {
  int data_[N];
  ///...
};

template <int N, int M>
struct GroupData {
  Data<M> points_[N];
  ...
};

struct container {
  int metadata_;
  uint8_t bytes[];

  template <int N, int M>
  gsl::span<GroupData<M, N>> points() {
    return //...
  }
};

pros: great for sender cons: ugly for receiver, since it doesn;t know the sizes at compile time.

flexible member arrays

struct Data {
  int metadata_;
  int data_[];
} __attribute__((__packed__));

struct GroupData {
  int metadata_;
  Data points_[];
} __attribute__((__packed__));

struct Container {
  int metadata_;  // encodes data about number clouds, and points
  uint8_t point_clouds_bytes_[];
  // custom iterator, custom operator to access the data based on the size
  // available at run time.
} __attribute__((__packed__));

pros: it removes the size templates requirements for receiver cons: everything else, size of the structs are not known at copile time, span can not be used, iterators wouldn;t work, everything has to be handled maually.

https://godbolt.org/z/cfF_6H

Aucun commentaire:

Enregistrer un commentaire