Skip to content

Commit

Permalink
config: Manage slots in blocks
Browse files Browse the repository at this point in the history
  • Loading branch information
MattiasTF committed Feb 24, 2025
1 parent 93aee89 commit 2cdba30
Show file tree
Hide file tree
Showing 19 changed files with 701 additions and 285 deletions.
102 changes: 0 additions & 102 deletions software/src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,34 +27,6 @@
#include "tools.h"
#include "string_builder.h"

#define UINT_SLOTS 512
Config::ConfUint::Slot *uint_buf = nullptr;
size_t uint_buf_size = 0;

#define INT_SLOTS 128
Config::ConfInt::Slot *int_buf = nullptr;
size_t int_buf_size = 0;

#define FLOAT_SLOTS 384
Config::ConfFloat::Slot *float_buf = nullptr;
size_t float_buf_size = 0;

#define STRING_SLOTS 384
Config::ConfString::Slot *string_buf = nullptr;
size_t string_buf_size = 0;

#define ARRAY_SLOTS 64
Config::ConfArray::Slot *array_buf = nullptr;
size_t array_buf_size = 0;

#define OBJECT_SLOTS 256
Config::ConfObject::Slot *object_buf = nullptr;
size_t object_buf_size = 0;

#define UNION_SLOTS 32
Config::ConfUnion::Slot *union_buf = nullptr;
size_t union_buf_size = 0;

static ConfigRoot nullconf = Config{Config::ConfVariant{}};
static ConfigRoot confirmconf;

Expand Down Expand Up @@ -818,77 +790,3 @@ void Config::set_updated(uint8_t api_backend_flag)
ASSERT_MAIN_THREAD();
value.updated |= api_backend_flag;
}

void config_pre_init()
{
uint_buf = Config::ConfUint::allocSlotBuf(UINT_SLOTS);
int_buf = Config::ConfInt::allocSlotBuf(INT_SLOTS);
float_buf = Config::ConfFloat::allocSlotBuf(FLOAT_SLOTS);
string_buf = Config::ConfString::allocSlotBuf(STRING_SLOTS);
array_buf = Config::ConfArray::allocSlotBuf(ARRAY_SLOTS);
object_buf = Config::ConfObject::allocSlotBuf(OBJECT_SLOTS);
union_buf = Config::ConfUnion::allocSlotBuf(UNION_SLOTS);

uint_buf_size = UINT_SLOTS;
int_buf_size = INT_SLOTS;
float_buf_size = FLOAT_SLOTS;
string_buf_size = STRING_SLOTS;
array_buf_size = ARRAY_SLOTS;
object_buf_size = OBJECT_SLOTS;
union_buf_size = UNION_SLOTS;
}

template<typename T>
static void shrinkToFit(typename T::Slot * &buf, size_t &buf_size) {
ASSERT_MAIN_THREAD();
size_t last_used_slot = 0;
int empty_slots = 0;

// Search for last used slot first.
// All empty slots behind the last used slot will be cut off.
size_t pos = buf_size;
while (pos > 0) {
pos--;
if (!T::slotEmpty(pos)) {
last_used_slot = pos;
break;
}
}
while (pos > 0) {
pos--;
if (T::slotEmpty(pos)) {
empty_slots++;
}
}

// Shrink the buffer so that the last used slot fits
// (we are not allowed to move used slots in the buffer!)
// and we have SLOT_HEADROOM free slots.
// If there are empty slots before the last used one, prefer those.
// If there are not enough, add some empty slots behind the last used one.
size_t new_size = last_used_slot + 1 + (size_t)std::max(0, SLOT_HEADROOM - empty_slots);

// Don't increase buffer size. It will be increased automatically when required.
if (new_size >= buf_size)
return;

auto new_buf = T::allocSlotBuf(new_size);

for (size_t i = 0; i <= last_used_slot; ++i)
new_buf[i] = std::move(buf[i]);

T::freeSlotBuf(buf);
buf = new_buf;
buf_size = new_size;
}

void config_post_setup()
{
shrinkToFit<Config::ConfUint>(uint_buf, uint_buf_size);
shrinkToFit<Config::ConfInt>(int_buf, int_buf_size);
shrinkToFit<Config::ConfFloat>(float_buf, float_buf_size);
shrinkToFit<Config::ConfString>(string_buf, string_buf_size);
shrinkToFit<Config::ConfArray>(array_buf, array_buf_size);
shrinkToFit<Config::ConfObject>(object_buf, object_buf_size);
shrinkToFit<Config::ConfUnion>(union_buf, union_buf_size);
}
22 changes: 7 additions & 15 deletions software/src/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ struct Config;

class StringBuilder;

void config_pre_init();
void config_post_setup();

struct ConfigRoot;
Expand Down Expand Up @@ -81,10 +80,9 @@ struct Config {
Slot *getSlot();

public:
static bool slotEmpty(size_t i);
static bool slotEmpty(const Slot *slot);
static constexpr const char *variantName = "ConfString";
static Slot *allocSlotBuf(size_t elements);
static void freeSlotBuf(Slot *buf);

CoolString *getVal();
const CoolString *getVal() const;
Expand Down Expand Up @@ -113,10 +111,9 @@ struct Config {
void setSlot(float val, float min, float max);

public:
static bool slotEmpty(size_t i);
static bool slotEmpty(const Slot *slot);
static constexpr const char *variantName = "ConfFloat";
static Slot *allocSlotBuf(size_t elements);
static void freeSlotBuf(Slot *buf);

float getVal() const;
float getMin() const;
Expand All @@ -143,10 +140,9 @@ struct Config {
Slot *getSlot();

public:
static bool slotEmpty(size_t i);
static bool slotEmpty(const Slot *slot);
static constexpr const char *variantName = "ConfInt";
static Slot *allocSlotBuf(size_t elements);
static void freeSlotBuf(Slot *buf);

int32_t *getVal();
const int32_t *getVal() const;
Expand All @@ -171,10 +167,9 @@ struct Config {
Slot *getSlot();

public:
static bool slotEmpty(size_t i);
static bool slotEmpty(const Slot *slot);
static constexpr const char *variantName = "ConfUint";
static Slot *allocSlotBuf(size_t elements);
static void freeSlotBuf(Slot *buf);

uint32_t *getVal();
const uint32_t *getVal() const;
Expand Down Expand Up @@ -207,10 +202,9 @@ struct Config {
Slot *getSlot();

public:
static bool slotEmpty(size_t i);
static bool slotEmpty(const Slot *slot);
static constexpr const char *variantName = "ConfArray";
static Slot *allocSlotBuf(size_t elements);
static void freeSlotBuf(Slot *buf);

Config *get(size_t i);
const Config *get(size_t i) const;
Expand All @@ -236,10 +230,9 @@ struct Config {
uint16_t idx;

public:
static bool slotEmpty(size_t i);
static bool slotEmpty(const Slot *slot);
static constexpr const char *variantName = "ConfObject";
static Slot *allocSlotBuf(size_t elements);
static void freeSlotBuf(Slot *buf);

Config *get(const char *s, size_t s_len);
const Config *get(const char *s, size_t s_len) const;
Expand All @@ -265,10 +258,9 @@ struct Config {
Slot *getSlot();

public:
static bool slotEmpty(size_t i);
static bool slotEmpty(const Slot *slot);
static constexpr const char *variantName = "ConfUnion";
static Slot *allocSlotBuf(size_t elements);
static void freeSlotBuf(Slot *buf);

uint8_t getTag() const;
bool changeUnionVariant(uint8_t tag);
Expand Down
24 changes: 11 additions & 13 deletions software/src/config/conf_array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,21 @@
*/

#include "config/private.h"
#include "config/slot_allocator.h"

#include "event_log_prefix.h"
#include "main_dependencies.h"

bool Config::ConfArray::slotEmpty(size_t i)
bool Config::ConfArray::slotEmpty(const Slot *slot)
{
return !array_buf[i].inUse;
return !slot->inUse;
}

Config::ConfArray::Slot *Config::ConfArray::allocSlotBuf(size_t elements)
{
return new Config::ConfArray::Slot[elements];
}

void Config::ConfArray::freeSlotBuf(Config::ConfArray::Slot *buf)
{
delete[] buf;
}

[[gnu::noinline]]
[[gnu::noreturn]]
static void abort_on_index_oob(size_t index, const std::vector<Config> *val, const Config::ConfArray *this_arr)
Expand Down Expand Up @@ -65,15 +61,15 @@ const Config *Config::ConfArray::get(size_t i) const
return &(*val)[i];
}

std::vector<Config> *Config::ConfArray::getVal() { return &array_buf[idx].val; }
const std::vector<Config> *Config::ConfArray::getVal() const { return &array_buf[idx].val; }
std::vector<Config> *Config::ConfArray::getVal() { return &get_slot<Config::ConfArray>(idx)->val; }
const std::vector<Config> *Config::ConfArray::getVal() const { return &get_slot<Config::ConfArray>(idx)->val; }

const Config::ConfArray::Slot *Config::ConfArray::getSlot() const { return &array_buf[idx]; }
Config::ConfArray::Slot *Config::ConfArray::getSlot() { return &array_buf[idx]; }
const Config::ConfArray::Slot *Config::ConfArray::getSlot() const { return get_slot<Config::ConfArray>(idx); }
Config::ConfArray::Slot *Config::ConfArray::getSlot() { return get_slot<Config::ConfArray>(idx); }

Config::ConfArray::ConfArray(std::vector<Config> val, const Config *prototype, uint16_t minElements, uint16_t maxElements, int8_t variantType)
{
idx = nextSlot<Config::ConfArray>(array_buf, array_buf_size);
idx = nextSlot<Config::ConfArray>();
auto *slot = this->getSlot();
slot->inUse = true;

Expand All @@ -92,7 +88,7 @@ Config::ConfArray::ConfArray(std::vector<Config> val, const Config *prototype, u

Config::ConfArray::ConfArray(const ConfArray &cpy)
{
idx = nextSlot<Config::ConfArray>(array_buf, array_buf_size);
idx = nextSlot<Config::ConfArray>();
// We have to mark this slot as in use here:
// This array could contain a nested array that will be copied over
// The inner array's copy constructor then takes the first free slot, i.e.
Expand All @@ -119,6 +115,8 @@ Config::ConfArray::~ConfArray()
slot->minElements = 0;
slot->maxElements = 0;
slot->variantType = 0;

notify_free_slot<Config::ConfArray>(idx);
}

Config::ConfArray &Config::ConfArray::operator=(const ConfArray &cpy)
Expand Down
41 changes: 21 additions & 20 deletions software/src/config/conf_float.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,73 +18,72 @@
*/

#include "config/private.h"
#include "config/slot_allocator.h"
#include "tools/malloc.h"

bool Config::ConfFloat::slotEmpty(size_t i) {
return float_buf[i].val == 0
&& float_buf[i].min == 0
&& float_buf[i].max == 0;
bool Config::ConfFloat::slotEmpty(const Slot *slot) {
return slot->val == 0
&& slot->min == 0
&& slot->max == 0;
}
Config::ConfFloat::Slot *Config::ConfFloat::allocSlotBuf(size_t elements)
{
return (Config::ConfFloat::Slot *)calloc_32bit_addressed(elements, sizeof(Config::ConfFloat::Slot));
}

void Config::ConfFloat::freeSlotBuf(Config::ConfFloat::Slot *buf)
{
free_any(buf);
}

typedef union {
float f;
uint32_t u;
} float_uint;

float Config::ConfFloat::getVal() const {
float_uint result;
result.u = float_buf[idx].val;
result.u = get_slot<Config::ConfFloat>(idx)->val;
return result.f;
}

void Config::ConfFloat::setVal(float f) {
float_uint v;
v.f = f;
float_buf[idx].val = v.u;
get_slot<Config::ConfFloat>(idx)->val = v.u;
}

float Config::ConfFloat::getMin() const {
float_uint result;
result.u = float_buf[idx].min;
result.u = get_slot<Config::ConfFloat>(idx)->min;
return result.f;
}

void Config::ConfFloat::setSlot(float val, float min, float max) {
Slot *slot = get_slot<Config::ConfFloat>(idx);

float_uint va, mi, ma;
va.f = val;
mi.f = min;
ma.f = max;
float_buf[idx].val = va.u;
float_buf[idx].min = mi.u;
float_buf[idx].max = ma.u;
slot->val = va.u;
slot->min = mi.u;
slot->max = ma.u;
}

float Config::ConfFloat::getMax() const {
float_uint result;
result.u = float_buf[idx].max;
result.u = get_slot<Config::ConfFloat>(idx)->max;
return result.f;
}

const Config::ConfFloat::Slot *Config::ConfFloat::getSlot() const { return &float_buf[idx]; }
Config::ConfFloat::Slot *Config::ConfFloat::getSlot() { return &float_buf[idx]; }
const Config::ConfFloat::Slot *Config::ConfFloat::getSlot() const { return get_slot<Config::ConfFloat>(idx); }
Config::ConfFloat::Slot *Config::ConfFloat::getSlot() { return get_slot<Config::ConfFloat>(idx); }

Config::ConfFloat::ConfFloat(float val, float min, float max)
{
idx = nextSlot<Config::ConfFloat>(float_buf, float_buf_size);
idx = nextSlot<Config::ConfFloat>();
this->setSlot(val, min, max);
}

Config::ConfFloat::ConfFloat(const ConfFloat &cpy)
{
idx = nextSlot<Config::ConfFloat>(float_buf, float_buf_size);
idx = nextSlot<Config::ConfFloat>();
auto tmp = *cpy.getSlot();
*this->getSlot() = std::move(tmp);
}
Expand All @@ -98,6 +97,8 @@ Config::ConfFloat::~ConfFloat()
slot->val = 0;
slot->min = 0;
slot->max = 0;

notify_free_slot<Config::ConfFloat>(idx);
}

Config::ConfFloat &Config::ConfFloat::operator=(const ConfFloat &cpy)
Expand Down
Loading

0 comments on commit 2cdba30

Please # to comment.