Files
PX4-Autopilot/src/lib/parameters/StaticSparseLayer.h
T
Thomas Debrunner bc872822bc params: Overhaul param system to use a layered approach without locking
- Instead we disable interrups on Nuttx where needed
- No lock is held during param export. Params can be changed
  concurrently and we rely on the fact that another export will be
  triggered in that case.
2023-05-31 07:45:20 +02:00

157 lines
3.8 KiB
C++

/****************************************************************************
*
* Copyright (c) 2023 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
#include <stdlib.h>
#include "ParamLayer.h"
template <int N_SLOTS>
class StaticSparseLayer : public ParamLayer
{
public:
StaticSparseLayer(ParamLayer *parent) : ParamLayer(parent)
{
for (int i = 0; i < N_SLOTS; i++) {
_slots[i] = {UINT16_MAX, param_value_u{}};
}
}
virtual ~StaticSparseLayer() = default;
bool store(param_t param, param_value_u value) override
{
const AtomicTransaction transaction;
const int index = _getIndex(param);
if (index < _next_slot) { // already exists
_slots[index].value = value;
} else if (_next_slot < N_SLOTS) {
_slots[_next_slot++] = {param, value};
_sort();
} else {
return false;
}
return true;
}
bool contains(param_t param) const override
{
const AtomicTransaction transaction;
return _getIndex(param) < _next_slot;
}
param_value_u get(param_t param) const override
{
const AtomicTransaction transaction;
const int index = _getIndex(param);
if (index < _next_slot) { // exists in this layer
return _slots[index].value;
}
return _parent->get(param);
}
void reset(param_t param) override
{
const AtomicTransaction transaction;
int index = _getIndex(param);
if (index < _next_slot) {
_slots[index] = {UINT16_MAX, param_value_u{}};
_sort();
_next_slot--;
}
}
void refresh(param_t param) override
{
_parent->refresh(param);
}
int size() const override
{
return _next_slot;
}
int byteSize() const override
{
return N_SLOTS * sizeof(Slot);
}
private:
struct Slot {
param_t param;
param_value_u value;
};
static int _slotCompare(const void *a, const void *b)
{
return ((int)((Slot *)a)->param) - ((int)((Slot *)b)->param);
}
void _sort()
{
qsort(_slots, N_SLOTS, sizeof(Slot), &_slotCompare);
}
int _getIndex(param_t param) const
{
int left = 0;
int right = _next_slot - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (_slots[mid].param == param) {
return mid;
} else if (_slots[mid].param < param) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return _next_slot;
}
Slot _slots[N_SLOTS];
int _next_slot = 0;
};