mirror of
https://github.com/nasa/fprime.git
synced 2025-12-10 00:44:37 -06:00
Make Os::Queues use Fw::MemAllocator pattern for memory (#4451)
* Queues use MemAllocator pattern * Derive queue allocation from MallocRegistry * Formatting * Fix UTs * Fix CI * Fix alignment in UT * Formatting and sp * Formatting, bad header * More formatting * Add queue teardown * Deinit components * Fix priority queue test * Fix bug in priority queue allocation * Correct comments * Fix FppTest and Ref UTs * Fix max heap teardown * Fix review comment on max heap * Fix null -> nullptr
This commit is contained in:
parent
89a9e3247b
commit
cddf38bb6f
@ -27,7 +27,9 @@ ActiveTestTester ::ActiveTestTester()
|
||||
this->component.registerExternalParameters(&this->paramTesterDelegate);
|
||||
}
|
||||
|
||||
ActiveTestTester ::~ActiveTestTester() {}
|
||||
ActiveTestTester ::~ActiveTestTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
void ActiveTestTester ::initComponents() {
|
||||
this->init();
|
||||
|
||||
@ -27,7 +27,9 @@ QueuedTestTester ::QueuedTestTester()
|
||||
this->component.registerExternalParameters(&this->paramTesterDelegate);
|
||||
}
|
||||
|
||||
QueuedTestTester ::~QueuedTestTester() {}
|
||||
QueuedTestTester ::~QueuedTestTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
void QueuedTestTester ::initComponents() {
|
||||
this->init();
|
||||
|
||||
@ -56,7 +56,9 @@ DpTestTester::DpTestTester()
|
||||
generateRandomString(this->stringRecordData);
|
||||
}
|
||||
|
||||
DpTestTester::~DpTestTester() {}
|
||||
DpTestTester::~DpTestTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -22,7 +22,9 @@ SmTestTester::SmTestTester() : SmTestGTestBase("SmTestTester", SmTestTester::MAX
|
||||
this->component.setIdBase(ID_BASE);
|
||||
}
|
||||
|
||||
SmTestTester::~SmTestTester() {}
|
||||
SmTestTester::~SmTestTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -26,7 +26,9 @@ BasicTester::BasicTester(const char* const compName)
|
||||
m_smChoiceBasic_action_b_history(),
|
||||
m_smChoiceBasic_guard_g() {}
|
||||
|
||||
BasicTester::~BasicTester() {}
|
||||
BasicTester::~BasicTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Handler implementations for typed input ports
|
||||
|
||||
@ -23,7 +23,9 @@ BasicU32Tester ::BasicU32Tester(const char* const compName)
|
||||
m_smChoiceBasicU32_action_b_history(),
|
||||
m_smChoiceBasicU32_guard_g() {}
|
||||
|
||||
BasicU32Tester ::~BasicU32Tester() {}
|
||||
BasicU32Tester ::~BasicU32Tester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -23,7 +23,9 @@ ChoiceToChoiceTester ::ChoiceToChoiceTester(const char* const compName)
|
||||
m_smChoiceChoiceToChoice_guard_g1(),
|
||||
m_smChoiceChoiceToChoice_guard_g2() {}
|
||||
|
||||
ChoiceToChoiceTester ::~ChoiceToChoiceTester() {}
|
||||
ChoiceToChoiceTester ::~ChoiceToChoiceTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -22,7 +22,9 @@ ChoiceToStateTester::ChoiceToStateTester(const char* const compName)
|
||||
m_smChoiceChoiceToState_actionHistory(),
|
||||
m_smChoiceChoiceToState_guard_g() {}
|
||||
|
||||
ChoiceToStateTester::~ChoiceToStateTester() {}
|
||||
ChoiceToStateTester::~ChoiceToStateTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -22,7 +22,9 @@ InputPairU16U32Tester ::InputPairU16U32Tester(const char* const compName)
|
||||
m_smChoiceInputPairU16U32_action_a_history(),
|
||||
m_smChoiceInputPairU16U32_guard_g() {}
|
||||
|
||||
InputPairU16U32Tester ::~InputPairU16U32Tester() {}
|
||||
InputPairU16U32Tester ::~InputPairU16U32Tester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -24,7 +24,9 @@ SequenceTester ::SequenceTester(const char* const compName)
|
||||
m_smChoiceSequence_guard_g1(),
|
||||
m_smChoiceSequence_guard_g2() {}
|
||||
|
||||
SequenceTester ::~SequenceTester() {}
|
||||
SequenceTester ::~SequenceTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -24,7 +24,9 @@ SequenceU32Tester::SequenceU32Tester(const char* const compName)
|
||||
m_smChoiceSequenceU32_guard_g1(),
|
||||
m_smChoiceSequenceU32_guard_g2() {}
|
||||
|
||||
SequenceU32Tester::~SequenceU32Tester() {}
|
||||
SequenceU32Tester::~SequenceU32Tester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -19,7 +19,9 @@ namespace SmInstanceInitial {
|
||||
BasicTester::BasicTester(const char* const compName)
|
||||
: BasicComponentBase(compName), m_basic1_action_a_history(), m_smInitialBasic1_action_a_history() {}
|
||||
|
||||
BasicTester::~BasicTester() {}
|
||||
BasicTester::~BasicTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Handler implementations for typed input ports
|
||||
|
||||
@ -24,7 +24,9 @@ ChoiceTester::ChoiceTester(const char* const compName)
|
||||
m_choice_guard_g(),
|
||||
m_smInitialChoice_guard_g() {}
|
||||
|
||||
ChoiceTester::~ChoiceTester() {}
|
||||
ChoiceTester::~ChoiceTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -19,7 +19,9 @@ namespace SmInstanceInitial {
|
||||
NestedTester::NestedTester(const char* const compName)
|
||||
: NestedComponentBase(compName), m_nested_action_a_history(), m_smInitialNested_action_a_history() {}
|
||||
|
||||
NestedTester::~NestedTester() {}
|
||||
NestedTester::~NestedTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -23,7 +23,9 @@ BasicGuardStringTester ::BasicGuardStringTester(const char* const compName)
|
||||
m_smStateBasicGuardString_action_a_history(),
|
||||
m_smStateBasicGuardString_guard_g() {}
|
||||
|
||||
BasicGuardStringTester ::~BasicGuardStringTester() {}
|
||||
BasicGuardStringTester ::~BasicGuardStringTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -23,7 +23,9 @@ BasicGuardTestAbsTypeTester::BasicGuardTestAbsTypeTester(const char* const compN
|
||||
m_smStateBasicGuardTestAbsType_action_a_history(),
|
||||
m_smStateBasicGuardTestAbsType_guard_g() {}
|
||||
|
||||
BasicGuardTestAbsTypeTester::~BasicGuardTestAbsTypeTester() {}
|
||||
BasicGuardTestAbsTypeTester::~BasicGuardTestAbsTypeTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -22,7 +22,9 @@ BasicGuardTestArrayTester::BasicGuardTestArrayTester(const char* const compName)
|
||||
m_smStateBasicGuardTestArray_action_a_history(),
|
||||
m_smStateBasicGuardTestArray_guard_g() {}
|
||||
|
||||
BasicGuardTestArrayTester::~BasicGuardTestArrayTester() {}
|
||||
BasicGuardTestArrayTester::~BasicGuardTestArrayTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -22,7 +22,9 @@ BasicGuardTestEnumTester::BasicGuardTestEnumTester(const char* const compName)
|
||||
m_smStateBasicGuardTestEnum_action_a_history(),
|
||||
m_smStateBasicGuardTestEnum_guard_g() {}
|
||||
|
||||
BasicGuardTestEnumTester::~BasicGuardTestEnumTester() {}
|
||||
BasicGuardTestEnumTester::~BasicGuardTestEnumTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -22,7 +22,9 @@ BasicGuardTestStructTester::BasicGuardTestStructTester(const char* const compNam
|
||||
m_smStateBasicGuardTestStruct_action_a_history(),
|
||||
m_smStateBasicGuardTestStruct_guard_g() {}
|
||||
|
||||
BasicGuardTestStructTester::~BasicGuardTestStructTester() {}
|
||||
BasicGuardTestStructTester::~BasicGuardTestStructTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -20,7 +20,9 @@ namespace SmInstanceState {
|
||||
BasicGuardTester ::BasicGuardTester(const char* const compName)
|
||||
: BasicGuardComponentBase(compName), m_smStateBasicGuard_action_a_history(), m_smStateBasicGuard_guard_g() {}
|
||||
|
||||
BasicGuardTester ::~BasicGuardTester() {}
|
||||
BasicGuardTester ::~BasicGuardTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -22,7 +22,9 @@ BasicGuardU32Tester::BasicGuardU32Tester(const char* const compName)
|
||||
m_smStateBasicGuardU32_action_a_history(),
|
||||
m_smStateBasicGuardU32_guard_g() {}
|
||||
|
||||
BasicGuardU32Tester::~BasicGuardU32Tester() {}
|
||||
BasicGuardU32Tester::~BasicGuardU32Tester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -19,7 +19,9 @@ namespace SmInstanceState {
|
||||
BasicInternalTester::BasicInternalTester(const char* const compName)
|
||||
: BasicInternalComponentBase(compName), m_smStateBasicInternal_action_a_history() {}
|
||||
|
||||
BasicInternalTester::~BasicInternalTester() {}
|
||||
BasicInternalTester::~BasicInternalTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -19,7 +19,9 @@ namespace SmInstanceState {
|
||||
BasicSelfTester::BasicSelfTester(const char* const compName)
|
||||
: BasicSelfComponentBase(compName), m_smStateBasicSelf_action_a_history() {}
|
||||
|
||||
BasicSelfTester::~BasicSelfTester() {}
|
||||
BasicSelfTester::~BasicSelfTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -22,7 +22,9 @@ BasicStringTester ::BasicStringTester(const char* const compName)
|
||||
m_smStateBasicString_action_a_history(),
|
||||
m_smStateBasicString_action_b_history() {}
|
||||
|
||||
BasicStringTester ::~BasicStringTester() {}
|
||||
BasicStringTester ::~BasicStringTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -21,7 +21,9 @@ BasicTestAbsTypeTester ::BasicTestAbsTypeTester(const char* const compName)
|
||||
m_smStateBasicTestAbsType_action_a_history(),
|
||||
m_smStateBasicTestAbsType_action_b_history() {}
|
||||
|
||||
BasicTestAbsTypeTester ::~BasicTestAbsTypeTester() {}
|
||||
BasicTestAbsTypeTester ::~BasicTestAbsTypeTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -21,7 +21,9 @@ BasicTestArrayTester::BasicTestArrayTester(const char* const compName)
|
||||
m_smStateBasicTestArray_action_a_history(),
|
||||
m_smStateBasicTestArray_action_b_history() {}
|
||||
|
||||
BasicTestArrayTester::~BasicTestArrayTester() {}
|
||||
BasicTestArrayTester::~BasicTestArrayTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -21,7 +21,9 @@ BasicTestEnumTester::BasicTestEnumTester(const char* const compName)
|
||||
m_smStateBasicTestEnum_action_a_history(),
|
||||
m_smStateBasicTestEnum_action_b_history() {}
|
||||
|
||||
BasicTestEnumTester::~BasicTestEnumTester() {}
|
||||
BasicTestEnumTester::~BasicTestEnumTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -21,7 +21,9 @@ BasicTestStructTester::BasicTestStructTester(const char* const compName)
|
||||
m_smStateBasicTestStruct_action_a_history(),
|
||||
m_smStateBasicTestStruct_action_b_history() {}
|
||||
|
||||
BasicTestStructTester::~BasicTestStructTester() {}
|
||||
BasicTestStructTester::~BasicTestStructTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -19,7 +19,9 @@ namespace SmInstanceState {
|
||||
BasicTester ::BasicTester(const char* const compName)
|
||||
: BasicComponentBase(compName), m_basic1_action_a_history(), m_smStateBasic1_action_a_history() {}
|
||||
|
||||
BasicTester ::~BasicTester() {}
|
||||
BasicTester ::~BasicTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Handler implementations for typed input ports
|
||||
|
||||
@ -19,7 +19,9 @@ namespace SmInstanceState {
|
||||
BasicU32Tester::BasicU32Tester(const char* const compName)
|
||||
: BasicU32ComponentBase(compName), m_smStateBasicU32_action_a_history(), m_smStateBasicU32_action_b_history() {}
|
||||
|
||||
BasicU32Tester::~BasicU32Tester() {}
|
||||
BasicU32Tester::~BasicU32Tester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -19,7 +19,9 @@ namespace SmInstanceState {
|
||||
InternalTester::InternalTester(const char* const compName)
|
||||
: InternalComponentBase(compName), m_smStateInternal_action_a_history() {}
|
||||
|
||||
InternalTester::~InternalTester() {}
|
||||
InternalTester::~InternalTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -18,7 +18,9 @@ namespace SmInstanceState {
|
||||
|
||||
PolymorphismTester::PolymorphismTester(const char* const compName) : PolymorphismComponentBase(compName) {}
|
||||
|
||||
PolymorphismTester::~PolymorphismTester() {}
|
||||
PolymorphismTester::~PolymorphismTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -19,7 +19,9 @@ namespace SmInstanceState {
|
||||
StateToChildTester::StateToChildTester(const char* const compName)
|
||||
: StateToChildComponentBase(compName), m_smStateStateToChild_actionHistory() {}
|
||||
|
||||
StateToChildTester::~StateToChildTester() {}
|
||||
StateToChildTester::~StateToChildTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -20,7 +20,9 @@ namespace SmInstanceState {
|
||||
StateToChoiceTester::StateToChoiceTester(const char* const compName)
|
||||
: StateToChoiceComponentBase(compName), m_smStateStateToChoice_actionHistory(), m_smStateStateToChoice_guard_g() {}
|
||||
|
||||
StateToChoiceTester::~StateToChoiceTester() {}
|
||||
StateToChoiceTester::~StateToChoiceTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -19,7 +19,9 @@ namespace SmInstanceState {
|
||||
StateToSelfTester::StateToSelfTester(const char* const compName)
|
||||
: StateToSelfComponentBase(compName), m_smStateStateToSelf_actionHistory() {}
|
||||
|
||||
StateToSelfTester::~StateToSelfTester() {}
|
||||
StateToSelfTester::~StateToSelfTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -19,7 +19,9 @@ namespace SmInstanceState {
|
||||
StateToStateTester::StateToStateTester(const char* const compName)
|
||||
: StateToStateComponentBase(compName), m_smStateStateToState_actionHistory() {}
|
||||
|
||||
StateToStateTester::~StateToStateTester() {}
|
||||
StateToStateTester::~StateToStateTester() {
|
||||
this->deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Implementations for internal state machine actions
|
||||
|
||||
@ -15,6 +15,10 @@ void QueuedComponentBase::init(FwEnumStoreType instance) {
|
||||
PassiveComponentBase::init(instance);
|
||||
}
|
||||
|
||||
void QueuedComponentBase::deinit() {
|
||||
this->m_queue.teardown();
|
||||
}
|
||||
|
||||
#if FW_OBJECT_TO_STRING == 1
|
||||
const char* QueuedComponentBase::getToStringFormatString() {
|
||||
return "QueueComp: %s";
|
||||
@ -28,7 +32,7 @@ Os::Queue::Queue::Status QueuedComponentBase::createQueue(FwSizeType depth, FwSi
|
||||
#else
|
||||
queueName.format("CompQ_%" PRI_FwSizeType, Os::Queue::getNumQueues());
|
||||
#endif
|
||||
return this->m_queue.create(queueName, depth, msgSize);
|
||||
return this->m_queue.create(this->getInstance(), queueName, depth, msgSize);
|
||||
}
|
||||
|
||||
FwSizeType QueuedComponentBase::getNumMsgsDropped() {
|
||||
|
||||
@ -31,6 +31,7 @@ class QueuedComponentBase : public PassiveComponentBase {
|
||||
QueuedComponentBase(const char* name); //!< Constructor
|
||||
virtual ~QueuedComponentBase(); //!< Destructor
|
||||
void init(FwEnumStoreType instance); //!< initialization function
|
||||
void deinit(); //!< Allows de-initialization on teardown
|
||||
Os::Queue m_queue; //!< queue object for active component
|
||||
Os::Queue::Status createQueue(FwSizeType depth, FwSizeType msgSize);
|
||||
virtual MsgDispatchStatus doDispatch() = 0; //!< method to dispatch a single message in the queue.
|
||||
|
||||
70
Fw/LanguageHelpers.hpp
Normal file
70
Fw/LanguageHelpers.hpp
Normal file
@ -0,0 +1,70 @@
|
||||
// ======================================================================
|
||||
// \title LanguageHelpers.hpp
|
||||
// \author lestarch
|
||||
// \brief hpp file for C++ language helper functions
|
||||
//
|
||||
// \copyright
|
||||
// Copyright (C) 2025 California Institute of Technology.
|
||||
// ALL RIGHTS RESERVED. United States Government Sponsorship
|
||||
// acknowledged.
|
||||
// ======================================================================
|
||||
#ifndef FW_TYPES_LANGUAGE_HELPERS_HPP_
|
||||
#define FW_TYPES_LANGUAGE_HELPERS_HPP_
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
#include "Fw/Types/Assert.hpp"
|
||||
#include "Fw/Types/ByteArray.hpp"
|
||||
namespace Fw {
|
||||
//! \brief placement new for arrays
|
||||
//!
|
||||
//! C++ as a language does not guaranteed that placement new for a C++ array of length N will fit within a memory
|
||||
//! region of size N *sizeof(T). Moreover, there are some compilers whose implementation of placement new for arrays
|
||||
//! do not guarantee this property.
|
||||
//!
|
||||
//! This function provides a helper for placement new for arrays that guarantees that the array will fit within the
|
||||
//! provided memory region. It checks that the provided memory region is large enough to hold the array (N * sizeof(T)
|
||||
//! and that the alignment of the provided memory region is sufficient for the type T. It also checks that the provided
|
||||
//! memory region is non-null.
|
||||
//!
|
||||
//! \warning this function cannot be used for arrays of arrays (i.e. T cannot be an array type).
|
||||
//!
|
||||
//! \tparam T the type of the array elements
|
||||
//! \param array the byte array to use for placement new (pair of bytes pointer and size)
|
||||
//! \param arraySize the number of elements in the array
|
||||
//! \return a pointer to the array of type T
|
||||
template <typename T>
|
||||
T* arrayPlacementNew(Fw::ByteArray array, FwSizeType arraySize) {
|
||||
static_assert(!std::is_array<T>::value, "Cannot use arrayPlacementNew new for arrays of arrays");
|
||||
static_assert(std::is_constructible<T>::value,
|
||||
"Cannot use arrayPlacementNew on types without a default zero-argument constructor");
|
||||
void* base_pointer = reinterpret_cast<void*>(array.bytes);
|
||||
FW_ASSERT(base_pointer != nullptr);
|
||||
FW_ASSERT((reinterpret_cast<PlatformPointerCastType>(base_pointer) % alignof(T)) == 0);
|
||||
FW_ASSERT(array.size >= (sizeof(T) * arraySize));
|
||||
T* type_pointer = static_cast<T*>(base_pointer);
|
||||
for (FwSizeType index = 0; index < arraySize; index++) {
|
||||
new (&type_pointer[index]) T();
|
||||
}
|
||||
return type_pointer;
|
||||
}
|
||||
|
||||
//! \brief placement delete for arrays
|
||||
//!
|
||||
//! This is the partner of tha above function that performs the destructor operation on every element of type T in the
|
||||
//! array. This assumes that all elements have been constructed.
|
||||
//!
|
||||
//! \warning this function cannot be used for arrays of arrays (i.e. T cannot be an array type).
|
||||
//!
|
||||
//! \tparam T the type of the array elements
|
||||
//! \param arrayPointer pointer to an array of type T
|
||||
//! \param arraySize the number of elements in the array
|
||||
template <typename T>
|
||||
void arrayPlacementDestruct(T* arrayPointer, FwSizeType arraySize) {
|
||||
static_assert(!std::is_array<T>::value, "Cannot use arrayPlacementDestruct new for arrays of arrays");
|
||||
FW_ASSERT(arrayPointer != nullptr);
|
||||
for (FwSizeType index = 0; index < arraySize; index++) {
|
||||
arrayPointer[index].~T();
|
||||
}
|
||||
}
|
||||
} // namespace Fw
|
||||
#endif // FW_TYPES_LANGUAGE_HELPERS_HPP_
|
||||
@ -33,7 +33,7 @@ class MallocAllocator : public MemAllocator {
|
||||
//! Allocate memory using malloc(). The identifier is unused and memory is never recoverable.
|
||||
//! malloc() guarantees alignment for any type and so does this allocator. It will not respect smaller alignments.
|
||||
//!
|
||||
//! \param identifier the memory segment identifier (not used)
|
||||
//! \param identifier the allocating entity identifier (not used)
|
||||
//! \param size the requested size (not changed)
|
||||
//! \param recoverable - flag to indicate the memory could be recoverable (always set to false)
|
||||
//! \param alignment - alignment requirement for the allocation. Default: maximum alignment defined by C++.
|
||||
|
||||
@ -6,11 +6,10 @@
|
||||
*/
|
||||
#include <Fw/Types/Assert.hpp>
|
||||
#include <Fw/Types/MemAllocator.hpp>
|
||||
|
||||
#include <config/MemoryAllocation.hpp>
|
||||
#include <type_traits>
|
||||
namespace Fw {
|
||||
|
||||
MemAllocatorRegistry* MemAllocatorRegistry::s_registry = nullptr; //!< singleton registry
|
||||
|
||||
MemAllocator::MemAllocator() {}
|
||||
|
||||
MemAllocator::~MemAllocator() {}
|
||||
@ -36,9 +35,8 @@ void* MemAllocator ::checkedAllocate(const FwEnumStoreType identifier, FwSizeTyp
|
||||
return this->checkedAllocate(identifier, size, unused, alignment);
|
||||
}
|
||||
|
||||
MemAllocatorRegistry::MemAllocatorRegistry() {
|
||||
// Register self as the singleton
|
||||
MemAllocatorRegistry::s_registry = this;
|
||||
MemAllocatorRegistry::MemAllocatorRegistry() : m_defaultAllocator(MemAllocatorRegistry::getDefaultAllocator()) {
|
||||
this->registerAllocator(MemoryAllocation::MemoryAllocatorType::SYSTEM, m_defaultAllocator);
|
||||
}
|
||||
|
||||
void MemAllocatorRegistry::registerAllocator(const MemoryAllocation::MemoryAllocatorType type,
|
||||
@ -47,8 +45,8 @@ void MemAllocatorRegistry::registerAllocator(const MemoryAllocation::MemoryAlloc
|
||||
}
|
||||
|
||||
MemAllocatorRegistry& MemAllocatorRegistry::getInstance() {
|
||||
FW_ASSERT(s_registry != nullptr);
|
||||
return *s_registry;
|
||||
static MemAllocatorRegistry registry;
|
||||
return registry;
|
||||
}
|
||||
|
||||
MemAllocator& MemAllocatorRegistry::getAllocator(const MemoryAllocation::MemoryAllocatorType type) {
|
||||
@ -63,4 +61,12 @@ MemAllocator& MemAllocatorRegistry::getAnAllocator(const MemoryAllocation::Memor
|
||||
}
|
||||
return *this->m_allocators[type];
|
||||
}
|
||||
|
||||
MemAllocator& MemAllocatorRegistry::getDefaultAllocator() {
|
||||
static_assert(std::is_constructible<MemoryAllocation::DefaultMemoryAllocatorType>::value,
|
||||
"DefaultMemoryAllocatorType must be constructible without arguments");
|
||||
static MemoryAllocation::DefaultMemoryAllocatorType defaultAllocator;
|
||||
return defaultAllocator;
|
||||
}
|
||||
|
||||
} /* namespace Fw */
|
||||
|
||||
@ -55,7 +55,7 @@ class MemAllocator {
|
||||
//! identifier is a unique identifier for the allocating entity. This entity (e.g. a component) may call allocate
|
||||
//! multiple times with the same id, but no other entity in the system shall call allocate with that id.
|
||||
//!
|
||||
//! \param identifier the memory segment identifier, each identifier is to be used in once single allocation
|
||||
//! \param identifier - a unique identifier for the allocating entity
|
||||
//! \param size the requested size - changed to actual if different
|
||||
//! \param recoverable - flag to indicate the memory could be recoverable
|
||||
//! \param alignment - alignment requirement for the allocation. Default: maximum alignment defined by C++.
|
||||
@ -70,7 +70,7 @@ class MemAllocator {
|
||||
//! Deallocate memory previously allocated by allocate(). The pointer must be one returned by allocate() and the
|
||||
//! identifier must match the one used in the original allocate() call.
|
||||
//!
|
||||
//! \param identifier the memory segment identifier, each identifier is to be used in once single allocation
|
||||
//! \param identifier - a unique identifier for the allocating entity, must match the call to allocate()
|
||||
//! \param ptr the pointer to memory returned by allocate()
|
||||
virtual void deallocate(const FwEnumStoreType identifier, void* ptr) = 0;
|
||||
|
||||
@ -80,7 +80,7 @@ class MemAllocator {
|
||||
//! by the underlying allocator but is not returned to the caller. This is for cases when the caller does not care
|
||||
//! about recoverability of memory.
|
||||
//!
|
||||
//! \param identifier the memory segment identifier, each identifier is to be used in once single allocation
|
||||
//! \param identifier - a unique identifier for the allocating entity
|
||||
//! \param size the requested size - changed to actual if different
|
||||
//! \param alignment - alignment requirement for the allocation. Default: maximum alignment defined by C++.
|
||||
//! \return the pointer to memory. Zero if unable to allocate
|
||||
@ -95,7 +95,7 @@ class MemAllocator {
|
||||
//!
|
||||
//! Allocations are checked using FW_ASSERT implying that an allocation failure results in a tripped assertion.
|
||||
//!
|
||||
//! \param identifier the memory segment identifier, each identifier is to be used in once single allocation
|
||||
//! \param identifier - a unique identifier for the allocating entity
|
||||
//! \param size the requested size, actual allocation will be at least this size
|
||||
//! \param recoverable - flag to indicate the memory could be recoverable
|
||||
//! \param alignment - alignment requirement for the allocation. Default: maximum alignment defined by C++.
|
||||
@ -114,7 +114,7 @@ class MemAllocator {
|
||||
//!
|
||||
//! Allocations are checked using FW_ASSERT implying that an allocation failure results in a tripped assertion.
|
||||
//!
|
||||
//! \param identifier the memory segment identifier, each identifier is to be used in once single allocation
|
||||
//! \param identifier - a unique identifier for the allocating entity
|
||||
//! \param size the requested size, actual allocation will be at least this size
|
||||
//! \param alignment - alignment requirement for the allocation. Default: maximum alignment defined by C++.
|
||||
//! \return the pointer to memory. Zero if unable to allocate
|
||||
@ -132,11 +132,12 @@ class MemAllocator {
|
||||
};
|
||||
|
||||
class MemAllocatorRegistry {
|
||||
public:
|
||||
private:
|
||||
// Constructor which will register itself as the singleton
|
||||
MemAllocatorRegistry();
|
||||
~MemAllocatorRegistry() = default;
|
||||
|
||||
public:
|
||||
//! \brief get the singleton registry
|
||||
//!
|
||||
//! \return the singleton registry
|
||||
@ -169,11 +170,17 @@ class MemAllocatorRegistry {
|
||||
MemAllocator& getAnAllocator(const MemoryAllocation::MemoryAllocatorType type);
|
||||
|
||||
private:
|
||||
//! \brief get the default allocator
|
||||
//!
|
||||
//! Creates a single instance of the default allocator and returns a reference to it. This is done to ensure that
|
||||
//! the default allocator is only created once and is available when ill-ordered static initialization occurs.
|
||||
//!
|
||||
//! \return the default allocator
|
||||
static MemAllocator& getDefaultAllocator();
|
||||
|
||||
//! Array of allocators for each type defaulted to nullptr
|
||||
MemAllocator* m_allocators[MemoryAllocation::MemoryAllocatorType::NUM_CONSTANTS] = {nullptr};
|
||||
|
||||
//! The singleton registry pointer
|
||||
static MemAllocatorRegistry* s_registry; //!< singleton registry
|
||||
MemAllocator& m_defaultAllocator; //!< default allocator
|
||||
};
|
||||
} /* namespace Fw */
|
||||
|
||||
|
||||
@ -2,11 +2,12 @@
|
||||
// \title Os/Generic/PriorityQueue.cpp
|
||||
// \brief priority queue implementation for Os::Queue
|
||||
// ======================================================================
|
||||
|
||||
#include "PriorityQueue.hpp"
|
||||
#include <Fw/Types/Assert.hpp>
|
||||
#include "Os/Generic/PriorityQueue.hpp"
|
||||
#include <cstring>
|
||||
#include <new>
|
||||
#include "Fw/LanguageHelpers.hpp"
|
||||
#include "Fw/Types/Assert.hpp"
|
||||
#include "Fw/Types/MemAllocator.hpp"
|
||||
#include "config/MemoryAllocatorTypeEnumAc.hpp"
|
||||
|
||||
namespace Os {
|
||||
namespace Generic {
|
||||
@ -38,62 +39,137 @@ void PriorityQueueHandle ::load_data(FwSizeType index, U8* destination, FwSizeTy
|
||||
(void)::memcpy(destination, this->m_data + offset, static_cast<size_t>(size));
|
||||
}
|
||||
|
||||
PriorityQueue::~PriorityQueue() {
|
||||
delete[] this->m_handle.m_data;
|
||||
delete[] this->m_handle.m_indices;
|
||||
delete[] this->m_handle.m_sizes;
|
||||
}
|
||||
PriorityQueue::~PriorityQueue() {}
|
||||
|
||||
QueueInterface::Status PriorityQueue::create(const Fw::ConstStringBase& name,
|
||||
QueueInterface::Status PriorityQueue::create(FwEnumStoreType id,
|
||||
const Fw::ConstStringBase& name,
|
||||
FwSizeType depth,
|
||||
FwSizeType messageSize) {
|
||||
const FwEnumStoreType identifier = id;
|
||||
QueueInterface::Status status = Os::QueueInterface::Status::OP_OK;
|
||||
// Ensure we are created exactly once
|
||||
FW_ASSERT(this->m_handle.m_indices == nullptr);
|
||||
FW_ASSERT(this->m_handle.m_sizes == nullptr);
|
||||
FW_ASSERT(this->m_handle.m_data == nullptr);
|
||||
|
||||
// Allocate indices list
|
||||
FwSizeType* indices = new (std::nothrow) FwSizeType[depth];
|
||||
if (indices == nullptr) {
|
||||
return QueueInterface::Status::ALLOCATION_FAILED;
|
||||
}
|
||||
// Allocate sizes list or clean-up
|
||||
FwSizeType* sizes = new (std::nothrow) FwSizeType[depth];
|
||||
if (sizes == nullptr) {
|
||||
delete[] indices;
|
||||
return QueueInterface::Status::ALLOCATION_FAILED;
|
||||
}
|
||||
// Allocate sizes list or clean-up
|
||||
U8* data = new (std::nothrow) U8[depth * messageSize];
|
||||
if (data == nullptr) {
|
||||
delete[] indices;
|
||||
delete[] sizes;
|
||||
return QueueInterface::Status::ALLOCATION_FAILED;
|
||||
}
|
||||
// Allocate max heap or clean-up
|
||||
bool created = this->m_handle.m_heap.create(depth);
|
||||
if (not created) {
|
||||
delete[] indices;
|
||||
delete[] sizes;
|
||||
delete[] data;
|
||||
return QueueInterface::Status::ALLOCATION_FAILED;
|
||||
}
|
||||
// Assign initial indices and sizes
|
||||
for (FwSizeType i = 0; i < depth; i++) {
|
||||
indices[i] = i;
|
||||
sizes[i] = 0;
|
||||
}
|
||||
// Set local tracking variables
|
||||
this->m_handle.m_maxSize = messageSize;
|
||||
this->m_handle.m_indices = indices;
|
||||
this->m_handle.m_data = data;
|
||||
this->m_handle.m_sizes = sizes;
|
||||
this->m_handle.m_startIndex = 0;
|
||||
this->m_handle.m_stopIndex = 0;
|
||||
this->m_handle.m_depth = depth;
|
||||
this->m_handle.m_highMark = 0;
|
||||
// Get the memory allocator configured for priority queues
|
||||
Fw::MemAllocator& allocator = Fw::MemAllocatorRegistry::getInstance().getAnAllocator(
|
||||
Fw::MemoryAllocation::MemoryAllocatorType::OS_GENERIC_PRIORITY_QUEUE);
|
||||
|
||||
return QueueInterface::Status::OP_OK;
|
||||
// Allocate indices list
|
||||
void* allocation = nullptr;
|
||||
FwSizeType size = 0;
|
||||
FwSizeType* indices = nullptr;
|
||||
FwSizeType* sizes = nullptr;
|
||||
U8* data = nullptr;
|
||||
U8* heap_pointer = nullptr;
|
||||
|
||||
// Allocate indices list and construct it when valid
|
||||
size = depth * sizeof(FwSizeType);
|
||||
allocation = allocator.allocate(identifier, size, alignof(FwSizeType));
|
||||
if (allocation == nullptr) {
|
||||
status = QueueInterface::Status::ALLOCATION_FAILED;
|
||||
} else if (size < (depth * sizeof(FwSizeType))) {
|
||||
allocator.deallocate(identifier, allocation);
|
||||
status = QueueInterface::Status::ALLOCATION_FAILED;
|
||||
} else {
|
||||
indices = Fw::arrayPlacementNew<FwSizeType>(Fw::ByteArray(static_cast<U8*>(allocation), size), depth);
|
||||
}
|
||||
|
||||
// Allocate sizes list and construct it when valid
|
||||
if (status == QueueInterface::Status::OP_OK) {
|
||||
size = depth * sizeof(FwSizeType);
|
||||
allocation = allocator.allocate(identifier, size, alignof(FwSizeType));
|
||||
if (allocation == nullptr) {
|
||||
allocator.deallocate(identifier, indices);
|
||||
status = QueueInterface::Status::ALLOCATION_FAILED;
|
||||
} else if (size < (depth * sizeof(FwSizeType))) {
|
||||
allocator.deallocate(identifier, indices);
|
||||
allocator.deallocate(identifier, allocation);
|
||||
status = QueueInterface::Status::ALLOCATION_FAILED;
|
||||
} else {
|
||||
sizes = Fw::arrayPlacementNew<FwSizeType>(Fw::ByteArray(static_cast<U8*>(allocation), size), depth);
|
||||
}
|
||||
}
|
||||
// Allocate data
|
||||
if (status == QueueInterface::Status::OP_OK) {
|
||||
size = depth * messageSize;
|
||||
allocation = allocator.allocate(identifier, size, alignof(U8));
|
||||
if (allocation == nullptr) {
|
||||
allocator.deallocate(identifier, indices);
|
||||
allocator.deallocate(identifier, sizes);
|
||||
status = QueueInterface::Status::ALLOCATION_FAILED;
|
||||
} else if (size < (depth * messageSize)) {
|
||||
allocator.deallocate(identifier, indices);
|
||||
allocator.deallocate(identifier, sizes);
|
||||
allocator.deallocate(identifier, allocation);
|
||||
status = QueueInterface::Status::ALLOCATION_FAILED;
|
||||
} else {
|
||||
data = static_cast<U8*>(allocation);
|
||||
}
|
||||
}
|
||||
// Allocate data for max heap
|
||||
if (status == QueueInterface::Status::OP_OK) {
|
||||
size = Types::MaxHeap::ELEMENT_SIZE * depth;
|
||||
allocation = allocator.allocate(identifier, size, Types::MaxHeap::ALIGNMENT);
|
||||
if (allocation == nullptr) {
|
||||
allocator.deallocate(identifier, indices);
|
||||
allocator.deallocate(identifier, sizes);
|
||||
allocator.deallocate(identifier, data);
|
||||
status = QueueInterface::Status::ALLOCATION_FAILED;
|
||||
} else if (size < (Types::MaxHeap::ELEMENT_SIZE * depth)) {
|
||||
allocator.deallocate(identifier, indices);
|
||||
allocator.deallocate(identifier, sizes);
|
||||
allocator.deallocate(identifier, data);
|
||||
allocator.deallocate(identifier, allocation);
|
||||
status = QueueInterface::Status::ALLOCATION_FAILED;
|
||||
} else {
|
||||
heap_pointer = static_cast<U8*>(allocation);
|
||||
this->m_handle.m_heap.create(depth, Fw::ByteArray(static_cast<U8*>(allocation), size));
|
||||
}
|
||||
}
|
||||
// Set up structures when all allocations succeeded
|
||||
if (status == QueueInterface::Status::OP_OK) {
|
||||
// Assign initial indices and sizes
|
||||
for (FwSizeType i = 0; i < depth; i++) {
|
||||
indices[i] = i;
|
||||
sizes[i] = 0;
|
||||
}
|
||||
// Set local tracking variables
|
||||
this->m_handle.m_id = id;
|
||||
this->m_handle.m_maxSize = messageSize;
|
||||
this->m_handle.m_indices = indices;
|
||||
this->m_handle.m_data = data;
|
||||
this->m_handle.m_sizes = sizes;
|
||||
this->m_handle.m_heap_pointer = heap_pointer;
|
||||
this->m_handle.m_startIndex = 0;
|
||||
this->m_handle.m_stopIndex = 0;
|
||||
this->m_handle.m_depth = depth;
|
||||
this->m_handle.m_highMark = 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
void PriorityQueue::teardown() {
|
||||
this->teardownInternal();
|
||||
}
|
||||
|
||||
void PriorityQueue::teardownInternal() {
|
||||
if (this->m_handle.m_data != nullptr) {
|
||||
const FwEnumStoreType identifier = this->m_handle.m_id;
|
||||
Fw::MemAllocator& allocator = Fw::MemAllocatorRegistry::getInstance().getAnAllocator(
|
||||
Fw::MemoryAllocation::MemoryAllocatorType::OS_GENERIC_PRIORITY_QUEUE);
|
||||
allocator.deallocate(identifier, this->m_handle.m_data);
|
||||
allocator.deallocate(identifier, this->m_handle.m_indices);
|
||||
allocator.deallocate(identifier, this->m_handle.m_sizes);
|
||||
this->m_handle.m_heap.teardown();
|
||||
allocator.deallocate(identifier, this->m_handle.m_heap_pointer);
|
||||
|
||||
// Set these pointers to nullptr
|
||||
this->m_handle.m_data = nullptr;
|
||||
this->m_handle.m_indices = nullptr;
|
||||
this->m_handle.m_sizes = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QueueInterface::Status PriorityQueue::send(const U8* buffer,
|
||||
|
||||
@ -20,6 +20,7 @@ namespace Generic {
|
||||
//! the data region and index list have queue depth number of entries.
|
||||
struct PriorityQueueHandle : public QueueHandle {
|
||||
Types::MaxHeap m_heap; //!< MaxHeap data store for tracking priority
|
||||
U8* m_heap_pointer; //!< Pointer to the MaxHeap data store
|
||||
U8* m_data = nullptr; //!< Pointer to data allocation
|
||||
FwSizeType* m_indices = nullptr; //!< List of indices into data
|
||||
FwSizeType* m_sizes = nullptr; //!< Size store for each method
|
||||
@ -31,6 +32,7 @@ struct PriorityQueueHandle : public QueueHandle {
|
||||
Os::Mutex m_data_lock; //!< Lock against data manipulation
|
||||
Os::ConditionVariable m_full; //!< Queue full condition variable to support blocking
|
||||
Os::ConditionVariable m_empty; //!< Queue empty condition variable to support blocking
|
||||
FwEnumStoreType m_id; //!< Identifier for the queue, used for memory allocation
|
||||
|
||||
//!\brief find an available index to store data from the list
|
||||
FwSizeType find_index();
|
||||
@ -74,13 +76,31 @@ class PriorityQueue : public Os::QueueInterface {
|
||||
//!
|
||||
//! Creates a queue ensuring sufficient storage to hold `depth` messages of `messageSize` size each.
|
||||
//!
|
||||
//! \warning allocates memory on the heap
|
||||
//! \warning allocates memory through the memory allocator registry
|
||||
//!
|
||||
//! \param id: identifier for the queue, used for memory allocation
|
||||
//! \param name: name of queue
|
||||
//! \param depth: depth of queue in number of messages
|
||||
//! \param messageSize: size of an individual message
|
||||
//! \return: status of the creation
|
||||
Status create(const Fw::ConstStringBase& name, FwSizeType depth, FwSizeType messageSize) override;
|
||||
Status create(FwEnumStoreType id,
|
||||
const Fw::ConstStringBase& name,
|
||||
FwSizeType depth,
|
||||
FwSizeType messageSize) override;
|
||||
|
||||
//! \brief teardown the queue
|
||||
//!
|
||||
//! Allow for queues to deallocate resources as part of system shutdown. This delegates to the underlying queue
|
||||
//! implementation.
|
||||
void teardown() override;
|
||||
|
||||
//! \brief teardown the queue
|
||||
//!
|
||||
//! Allow for queues to deallocate resources as part of system shutdown. This delegates to the underlying queue
|
||||
//! implementation.
|
||||
//!
|
||||
//! Note: this is a helper to allow this to be called from the destructor.
|
||||
void teardownInternal();
|
||||
|
||||
//! \brief send a message into the queue
|
||||
//!
|
||||
|
||||
@ -17,10 +17,9 @@
|
||||
#include "Os/Generic/Types/MaxHeap.hpp"
|
||||
#include <Fw/FPrimeBasicTypes.hpp>
|
||||
#include <Fw/Logger/Logger.hpp>
|
||||
#include "Fw/Types/Assert.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <new>
|
||||
#include "Fw/LanguageHelpers.hpp"
|
||||
#include "Fw/Types/Assert.hpp"
|
||||
|
||||
// Macros for traversing the heap:
|
||||
#define LCHILD(x) (2 * x + 1)
|
||||
@ -30,7 +29,6 @@
|
||||
namespace Types {
|
||||
|
||||
MaxHeap::MaxHeap() {
|
||||
// Initialize the heap:
|
||||
this->m_capacity = 0;
|
||||
this->m_heap = nullptr;
|
||||
this->m_size = 0;
|
||||
@ -38,20 +36,30 @@ MaxHeap::MaxHeap() {
|
||||
}
|
||||
|
||||
MaxHeap::~MaxHeap() {
|
||||
delete[] this->m_heap;
|
||||
this->m_heap = nullptr;
|
||||
}
|
||||
|
||||
bool MaxHeap::create(FwSizeType capacity) {
|
||||
void MaxHeap::create(FwSizeType capacity, Fw::ByteArray heap_allocation) {
|
||||
FW_ASSERT(this->m_heap == nullptr);
|
||||
FW_ASSERT(heap_allocation.size >= (capacity * sizeof(Node)), static_cast<FwAssertArgType>(capacity),
|
||||
static_cast<FwAssertArgType>(heap_allocation.size));
|
||||
FW_ASSERT(heap_allocation.bytes != nullptr);
|
||||
// Loop bounds will overflow if capacity set to the max allowable value
|
||||
FW_ASSERT(capacity < std::numeric_limits<FwSizeType>::max());
|
||||
this->m_heap = new (std::nothrow) Node[capacity];
|
||||
if (nullptr == this->m_heap) {
|
||||
return false;
|
||||
}
|
||||
this->m_heap = Fw::arrayPlacementNew<Node>(heap_allocation, capacity);
|
||||
this->m_capacity = capacity;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MaxHeap::teardown() {
|
||||
// Only destroy the heap if it is still allocated
|
||||
if (this->m_heap != nullptr) {
|
||||
Fw::arrayPlacementDestruct<Node>(this->m_heap, this->m_capacity);
|
||||
}
|
||||
// Reset the capacity and heap so that the provider of memory
|
||||
this->m_capacity = 0;
|
||||
this->m_heap = nullptr;
|
||||
this->m_size = 0;
|
||||
this->m_order = 0;
|
||||
}
|
||||
|
||||
bool MaxHeap::push(FwQueuePriorityType value, FwSizeType id) {
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#define UTILS_TYPES_MAX_HEAP_HPP
|
||||
|
||||
#include <Fw/FPrimeBasicTypes.hpp>
|
||||
#include <Fw/Types/ByteArray.hpp>
|
||||
|
||||
namespace Types {
|
||||
|
||||
@ -39,12 +40,13 @@ class MaxHeap {
|
||||
~MaxHeap();
|
||||
//! \brief MaxHeap creation
|
||||
//!
|
||||
//! Create the max heap with a given maximum size
|
||||
//! \warning allocates memory on the heap
|
||||
//!
|
||||
//! Create the max heap with a given capacity. Constructs heap elements in the provided memory.
|
||||
//! \param capacity the maximum number of elements to store in the heap
|
||||
//! \param heap_allocation the memory to use for the heap
|
||||
//!
|
||||
bool create(FwSizeType capacity);
|
||||
void create(FwSizeType capacity, Fw::ByteArray heap_allocation);
|
||||
//! \brief MaxHeap teardown
|
||||
void teardown();
|
||||
//! \brief Push an item onto the heap.
|
||||
//!
|
||||
//! The item will be put into the heap according to its value. The
|
||||
@ -105,6 +107,11 @@ class MaxHeap {
|
||||
FwSizeType m_size; // the current size of the heap
|
||||
FwSizeType m_order; // the current count of heap pushes
|
||||
FwSizeType m_capacity; // the maximum capacity of the heap
|
||||
public:
|
||||
//! Exposes the ELEMENT_SIZE for pre-allocation
|
||||
static constexpr FwSizeType ELEMENT_SIZE = sizeof(Node);
|
||||
//! Exposes the ALIGNMENT for pre-allocation
|
||||
static constexpr FwSizeType ALIGNMENT = alignof(Node);
|
||||
};
|
||||
|
||||
} // namespace Types
|
||||
|
||||
@ -5,41 +5,37 @@
|
||||
|
||||
#define DEPTH 5
|
||||
#define DATA_SIZE 3
|
||||
#define BIG 100000
|
||||
|
||||
TEST(Nominal, Creation) {
|
||||
bool ret;
|
||||
alignas(Types::MaxHeap::ALIGNMENT) U8 heap_allocation[Types::MaxHeap::ELEMENT_SIZE * BIG];
|
||||
{
|
||||
Types::MaxHeap heap;
|
||||
ret = heap.create(0);
|
||||
ASSERT_TRUE(ret);
|
||||
heap.create(0, Fw::ByteArray(heap_allocation, sizeof(heap_allocation)));
|
||||
}
|
||||
{
|
||||
Types::MaxHeap heap;
|
||||
ret = heap.create(1000000);
|
||||
ASSERT_TRUE(ret);
|
||||
heap.create(BIG, Fw::ByteArray(heap_allocation, sizeof(heap_allocation)));
|
||||
}
|
||||
{
|
||||
Types::MaxHeap heap;
|
||||
ret = heap.create(1);
|
||||
ASSERT_TRUE(ret);
|
||||
heap.create(1, Fw::ByteArray(heap_allocation, sizeof(heap_allocation)));
|
||||
}
|
||||
{
|
||||
Types::MaxHeap heap;
|
||||
ret = heap.create(DEPTH);
|
||||
ASSERT_TRUE(ret);
|
||||
heap.create(DEPTH, Fw::ByteArray(heap_allocation, sizeof(heap_allocation)));
|
||||
}
|
||||
{
|
||||
Types::MaxHeap heap;
|
||||
ret = heap.create(DEPTH);
|
||||
ASSERT_TRUE(ret);
|
||||
heap.create(DEPTH, Fw::ByteArray(heap_allocation, sizeof(heap_allocation)));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Nominal, Empty) {
|
||||
bool ret;
|
||||
alignas(Types::MaxHeap::ALIGNMENT) U8 heap_allocation[Types::MaxHeap::ELEMENT_SIZE * DEPTH];
|
||||
Types::MaxHeap heap;
|
||||
ret = heap.create(DEPTH);
|
||||
ASSERT_TRUE(ret);
|
||||
heap.create(DEPTH, Fw::ByteArray(heap_allocation, sizeof(heap_allocation)));
|
||||
|
||||
FwQueuePriorityType value;
|
||||
FwSizeType id = 0;
|
||||
@ -59,9 +55,9 @@ TEST(Nominal, Empty) {
|
||||
TEST(Nominal, PushPop) {
|
||||
printf("Creating heap.\n");
|
||||
bool ret;
|
||||
alignas(Types::MaxHeap::ALIGNMENT) U8 heap_allocation[Types::MaxHeap::ELEMENT_SIZE * DEPTH];
|
||||
Types::MaxHeap heap;
|
||||
ret = heap.create(DEPTH);
|
||||
ASSERT_TRUE(ret);
|
||||
heap.create(DEPTH, Fw::ByteArray(heap_allocation, sizeof(heap_allocation)));
|
||||
|
||||
FwQueuePriorityType value;
|
||||
FwSizeType size;
|
||||
|
||||
12
Os/Queue.cpp
12
Os/Queue.cpp
@ -19,7 +19,10 @@ Queue::~Queue() {
|
||||
m_delegate.~QueueInterface();
|
||||
}
|
||||
|
||||
QueueInterface::Status Queue ::create(const Fw::ConstStringBase& name, FwSizeType depth, FwSizeType messageSize) {
|
||||
QueueInterface::Status Queue ::create(FwEnumStoreType id,
|
||||
const Fw::ConstStringBase& name,
|
||||
FwSizeType depth,
|
||||
FwSizeType messageSize) {
|
||||
FW_ASSERT(&this->m_delegate == reinterpret_cast<QueueInterface*>(&this->m_handle_storage[0]));
|
||||
FW_ASSERT(depth > 0);
|
||||
FW_ASSERT(messageSize > 0);
|
||||
@ -27,7 +30,7 @@ QueueInterface::Status Queue ::create(const Fw::ConstStringBase& name, FwSizeTyp
|
||||
if (this->m_depth > 0 || this->m_size > 0) {
|
||||
return QueueInterface::Status::ALREADY_CREATED;
|
||||
}
|
||||
QueueInterface::Status status = this->m_delegate.create(name, depth, messageSize);
|
||||
QueueInterface::Status status = this->m_delegate.create(id, name, depth, messageSize);
|
||||
if (status == QueueInterface::Status::OP_OK) {
|
||||
this->m_name = name;
|
||||
this->m_depth = depth;
|
||||
@ -43,6 +46,11 @@ QueueInterface::Status Queue ::create(const Fw::ConstStringBase& name, FwSizeTyp
|
||||
return status;
|
||||
}
|
||||
|
||||
void Queue::teardown() {
|
||||
FW_ASSERT(&this->m_delegate == reinterpret_cast<QueueInterface*>(&this->m_handle_storage[0]));
|
||||
return this->m_delegate.teardown();
|
||||
}
|
||||
|
||||
QueueInterface::Status Queue::send(const U8* buffer,
|
||||
FwSizeType size,
|
||||
FwQueuePriorityType priority,
|
||||
|
||||
26
Os/Queue.hpp
26
Os/Queue.hpp
@ -69,11 +69,23 @@ class QueueInterface {
|
||||
//! allocation is dependent on the underlying implementation and users should assume that resource allocation is
|
||||
//! possible.
|
||||
//!
|
||||
//! \param id: identifier for the queue, used for memory allocation
|
||||
//! \param name: name of queue
|
||||
//! \param depth: depth of queue in number of messages
|
||||
//! \param messageSize: size of an individual message
|
||||
//! \return: status of the creation
|
||||
virtual Status create(const Fw::ConstStringBase& name, FwSizeType depth, FwSizeType messageSize) = 0;
|
||||
virtual Status create(FwEnumStoreType id,
|
||||
const Fw::ConstStringBase& name,
|
||||
FwSizeType depth,
|
||||
FwSizeType messageSize) = 0;
|
||||
|
||||
//! \brief teardown the queue
|
||||
//!
|
||||
//! Allow for queues to deallocate resources as part of system shutdown. This delegates to the underlying queue
|
||||
//! implementation.
|
||||
//!
|
||||
//! Note: the default implementation does nothing.
|
||||
virtual void teardown() {}
|
||||
|
||||
//! \brief send a message into the queue
|
||||
//!
|
||||
@ -179,7 +191,17 @@ class Queue final : public QueueInterface {
|
||||
//! \param depth: depth of queue in number of messages
|
||||
//! \param messageSize: size of an individual message
|
||||
//! \return: status of the creation
|
||||
Status create(const Fw::ConstStringBase& name, FwSizeType depth, FwSizeType messageSize) override;
|
||||
Status create(FwEnumStoreType id,
|
||||
const Fw::ConstStringBase& name,
|
||||
FwSizeType depth,
|
||||
FwSizeType messageSize) override;
|
||||
|
||||
//! \brief teardown the queue
|
||||
//!
|
||||
//! Allow for queues to deallocate resources as part of system shutdown. This delegates to the underlying queue
|
||||
//! implementation.
|
||||
//! implementation.
|
||||
void teardown() override;
|
||||
|
||||
//! \brief send a message into the queue through delegate
|
||||
//!
|
||||
|
||||
@ -8,7 +8,10 @@ namespace Os {
|
||||
namespace Stub {
|
||||
namespace Queue {
|
||||
|
||||
QueueInterface::Status StubQueue::create(const Fw::ConstStringBase& name, FwSizeType depth, FwSizeType messageSize) {
|
||||
QueueInterface::Status StubQueue::create(FwEnumStoreType id,
|
||||
const Fw::ConstStringBase& name,
|
||||
FwSizeType depth,
|
||||
FwSizeType messageSize) {
|
||||
return QueueInterface::Status::UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@ -33,11 +33,15 @@ class StubQueue : public QueueInterface {
|
||||
//! \brief create queue storage
|
||||
//!
|
||||
//! Creates a queue ensuring sufficient storage to hold `depth` messages of `messageSize` size each.
|
||||
//! \param id: identifier of queue
|
||||
//! \param name: name of queue
|
||||
//! \param depth: depth of queue in number of messages
|
||||
//! \param messageSize: size of an individual message
|
||||
//! \return: status of the creation
|
||||
Status create(const Fw::ConstStringBase& name, FwSizeType depth, FwSizeType messageSize) override;
|
||||
Status create(FwEnumStoreType id,
|
||||
const Fw::ConstStringBase& name,
|
||||
FwSizeType depth,
|
||||
FwSizeType messageSize) override;
|
||||
|
||||
//! \brief send a message into the queue
|
||||
//!
|
||||
|
||||
@ -32,7 +32,8 @@ InjectableStlQueue::~InjectableStlQueue() {
|
||||
StaticData::data.lastCalled = StaticData::LastFn::DESTRUCT_FN;
|
||||
}
|
||||
|
||||
QueueInterface::Status InjectableStlQueue::create(const Fw::ConstStringBase& name,
|
||||
QueueInterface::Status InjectableStlQueue::create(FwEnumStoreType id,
|
||||
const Fw::ConstStringBase& name,
|
||||
FwSizeType depth,
|
||||
FwSizeType messageSize) {
|
||||
StaticData::data.lastCalled = StaticData::LastFn::CREATE_FN;
|
||||
|
||||
@ -107,11 +107,15 @@ class InjectableStlQueue : public QueueInterface {
|
||||
//! \brief create queue storage
|
||||
//!
|
||||
//! Creates a queue ensuring sufficient storage to hold `depth` messages of `messageSize` size each.
|
||||
//! \param id: identifier of queue
|
||||
//! \param name: name of queue
|
||||
//! \param depth: depth of queue in number of messages
|
||||
//! \param messageSize: size of an individual message
|
||||
//! \return: status of the creation
|
||||
Status create(const Fw::ConstStringBase& name, FwSizeType depth, FwSizeType messageSize) override;
|
||||
Status create(FwEnumStoreType id,
|
||||
const Fw::ConstStringBase& name,
|
||||
FwSizeType depth,
|
||||
FwSizeType messageSize) override;
|
||||
|
||||
//! \brief send a message into the queue
|
||||
//!
|
||||
|
||||
@ -42,7 +42,7 @@ TEST(Interface, Create) {
|
||||
STest::Random::lowerUpper(std::numeric_limits<FwSizeType>::min(),
|
||||
FW_MIN(std::numeric_limits<FwSizeType>::max(), std::numeric_limits<U32>::max()));
|
||||
Os::Stub::Queue::Test::StaticData::data.createStatus = Os::QueueInterface::Status::INVALID_PRIORITY;
|
||||
Os::QueueInterface::Status status = queue.create(name, depth, messageSize);
|
||||
Os::QueueInterface::Status status = queue.create(0, name, depth, messageSize);
|
||||
ASSERT_EQ(Os::Stub::Queue::Test::StaticData::data.lastCalled, Os::Stub::Queue::Test::StaticData::CREATE_FN);
|
||||
ASSERT_EQ(Os::QueueInterface::Status::INVALID_PRIORITY, status);
|
||||
ASSERT_STREQ(name.toChar(), Os::Stub::Queue::Test::StaticData::data.name.toChar());
|
||||
@ -62,7 +62,7 @@ TEST(Interface, SendPointer) {
|
||||
const FwQueuePriorityType priority = STest::Random::lowerUpper(
|
||||
0, FW_MIN(std::numeric_limits<FwQueuePriorityType>::max(), std::numeric_limits<U32>::max()));
|
||||
U8 buffer[messageSize];
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(name, depth, messageSize));
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(0, name, depth, messageSize));
|
||||
ASSERT_STREQ(name.toChar(), queue.getName().toChar());
|
||||
Os::Stub::Queue::Test::StaticData::data.sendStatus = Os::QueueInterface::Status::EMPTY;
|
||||
Os::QueueInterface::Status status =
|
||||
@ -93,7 +93,7 @@ TEST(Interface, SendBuffer) {
|
||||
Fw::String message = "hello";
|
||||
buffer.serializeFrom(message);
|
||||
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(name, depth, messageSize));
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(0, name, depth, messageSize));
|
||||
Os::Stub::Queue::Test::StaticData::data.sendStatus = Os::QueueInterface::Status::UNKNOWN_ERROR;
|
||||
Os::QueueInterface::Status status = queue.send(buffer, priority, Os::QueueInterface::BlockingType::NONBLOCKING);
|
||||
ASSERT_EQ(Os::Stub::Queue::Test::StaticData::data.lastCalled, Os::Stub::Queue::Test::StaticData::SEND_FN);
|
||||
@ -123,7 +123,7 @@ TEST(Interface, ReceivePointer) {
|
||||
FwQueuePriorityType priority;
|
||||
U8 storage[size];
|
||||
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(name, depth, size));
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(0, name, depth, size));
|
||||
Os::Stub::Queue::Test::StaticData::data.receiveStatus = Os::QueueInterface::Status::FULL;
|
||||
Os::Stub::Queue::Test::StaticData::data.size = sizeOut;
|
||||
Os::Stub::Queue::Test::StaticData::data.priority = priorityOut;
|
||||
@ -159,7 +159,7 @@ TEST(Interface, ReceiveBuffer) {
|
||||
U8 storage[size];
|
||||
Fw::ExternalSerializeBuffer buffer(storage, sizeof storage);
|
||||
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(name, depth, size));
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(0, name, depth, size));
|
||||
Os::Stub::Queue::Test::StaticData::data.receiveStatus = Os::QueueInterface::Status::FULL;
|
||||
Os::Stub::Queue::Test::StaticData::data.size = sizeOut;
|
||||
Os::Stub::Queue::Test::StaticData::data.priority = priorityOut;
|
||||
@ -186,7 +186,7 @@ TEST(Interface, MessageCount) {
|
||||
const FwSizeType messages =
|
||||
STest::Random::lowerUpper(std::numeric_limits<FwSizeType>::min(),
|
||||
FW_MIN(std::numeric_limits<FwSizeType>::max(), std::numeric_limits<U32>::max()));
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(name, depth, messageSize));
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(0, name, depth, messageSize));
|
||||
Os::Stub::Queue::Test::StaticData::data.messages = messages;
|
||||
ASSERT_EQ(queue.getMessagesAvailable(), messages);
|
||||
|
||||
@ -201,7 +201,7 @@ TEST(Interface, MessageHighWaterMarkCount) {
|
||||
const FwSizeType highWater =
|
||||
STest::Random::lowerUpper(std::numeric_limits<FwSizeType>::min(),
|
||||
FW_MIN(std::numeric_limits<FwSizeType>::max(), std::numeric_limits<U32>::max()));
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(name, depth, messageSize));
|
||||
ASSERT_EQ(Os::QueueInterface::Status::OP_OK, queue.create(0, name, depth, messageSize));
|
||||
Os::Stub::Queue::Test::StaticData::data.highWaterMark = highWater;
|
||||
ASSERT_EQ(queue.getMessageHighWaterMark(), highWater);
|
||||
|
||||
|
||||
@ -136,6 +136,7 @@ TEST(InterfaceUninitialized, SendBuffer) {
|
||||
|
||||
Os::QueueInterface::Status status = queue.send(buffer, priority, Os::QueueInterface::BlockingType::BLOCKING);
|
||||
ASSERT_EQ(Os::QueueInterface::Status::UNINITIALIZED, status);
|
||||
queue.teardown();
|
||||
}
|
||||
|
||||
TEST(InterfaceUninitialized, ReceivePointer) {
|
||||
@ -148,6 +149,7 @@ TEST(InterfaceUninitialized, ReceivePointer) {
|
||||
Os::QueueInterface::Status status =
|
||||
queue.receive(storage, sizeof storage, Os::QueueInterface::BlockingType::NONBLOCKING, size, priority);
|
||||
ASSERT_EQ(Os::QueueInterface::Status::UNINITIALIZED, status);
|
||||
queue.teardown();
|
||||
}
|
||||
|
||||
TEST(InterfaceUninitialized, ReceiveBuffer) {
|
||||
@ -160,18 +162,21 @@ TEST(InterfaceUninitialized, ReceiveBuffer) {
|
||||
|
||||
Os::QueueInterface::Status status = queue.receive(buffer, Os::QueueInterface::BlockingType::NONBLOCKING, priority);
|
||||
ASSERT_EQ(Os::QueueInterface::Status::UNINITIALIZED, status);
|
||||
queue.teardown();
|
||||
}
|
||||
|
||||
TEST(InterfaceInvalid, CreateInvalidDepth) {
|
||||
Os::Queue queue;
|
||||
Fw::String name = "My queue";
|
||||
ASSERT_DEATH_IF_SUPPORTED(queue.create(name, 0, 10), "Assert:.*Queue\\.cpp");
|
||||
ASSERT_DEATH_IF_SUPPORTED(queue.create(0, name, 0, 10), "Assert:.*Queue\\.cpp");
|
||||
queue.teardown();
|
||||
}
|
||||
|
||||
TEST(InterfaceInvalid, CreateInvalidSize) {
|
||||
Os::Queue queue;
|
||||
Fw::String name = "My queue";
|
||||
ASSERT_DEATH_IF_SUPPORTED(queue.create(name, 10, 0), "Assert:.*Queue\\.cpp");
|
||||
ASSERT_DEATH_IF_SUPPORTED(queue.create(0, name, 10, 0), "Assert:.*Queue\\.cpp");
|
||||
queue.teardown();
|
||||
}
|
||||
|
||||
TEST(InterfaceInvalid, SendPointerNull) {
|
||||
@ -181,6 +186,7 @@ TEST(InterfaceInvalid, SendPointerNull) {
|
||||
const FwQueuePriorityType priority = 127;
|
||||
ASSERT_DEATH_IF_SUPPORTED(queue.send(nullptr, messageSize, priority, Os::QueueInterface::BlockingType::BLOCKING),
|
||||
"Assert:.*Queue\\.cpp");
|
||||
queue.teardown();
|
||||
}
|
||||
|
||||
TEST(InterfaceInvalid, SendInvalidEnum) {
|
||||
@ -191,6 +197,7 @@ TEST(InterfaceInvalid, SendInvalidEnum) {
|
||||
Os::QueueInterface::BlockingType blockingType =
|
||||
static_cast<Os::QueueInterface::BlockingType>(Os::QueueInterface::BlockingType::BLOCKING + 1);
|
||||
ASSERT_DEATH_IF_SUPPORTED(queue.send(nullptr, messageSize, priority, blockingType), "Assert:.*Queue\\.cpp");
|
||||
queue.teardown();
|
||||
}
|
||||
|
||||
TEST(InterfaceInvalid, ReceivePointerNull) {
|
||||
@ -201,6 +208,7 @@ TEST(InterfaceInvalid, ReceivePointerNull) {
|
||||
ASSERT_DEATH_IF_SUPPORTED(
|
||||
queue.receive(nullptr, size, Os::QueueInterface::BlockingType::NONBLOCKING, size, priority),
|
||||
"Assert:.*Queue\\.cpp");
|
||||
queue.teardown();
|
||||
}
|
||||
|
||||
TEST(InterfaceInvalid, ReceiveInvalidEnum) {
|
||||
@ -211,6 +219,7 @@ TEST(InterfaceInvalid, ReceiveInvalidEnum) {
|
||||
Os::QueueInterface::BlockingType blockingType =
|
||||
static_cast<Os::QueueInterface::BlockingType>(Os::QueueInterface::BlockingType::BLOCKING + 1);
|
||||
ASSERT_DEATH_IF_SUPPORTED(queue.receive(nullptr, size, blockingType, size, priority), "Assert:.*Queue\\.cpp");
|
||||
queue.teardown();
|
||||
}
|
||||
|
||||
TEST(BasicRules, Create) {
|
||||
|
||||
@ -61,7 +61,7 @@ void Os::Test::Queue::Tester::Create::action(Os::Test::Queue::Tester& state //!
|
||||
FwSizeType depth = STest::Random::lowerUpper(1, QUEUE_DEPTH_UPPER_BOUND);
|
||||
FwSizeType messageSize = STest::Random::lowerUpper(1, QUEUE_MESSAGE_SIZE_UPPER_BOUND);
|
||||
QueueInterface::Status status = state.shadow_create(depth, messageSize);
|
||||
QueueInterface::Status test_status = state.queue.create(name, depth, messageSize);
|
||||
QueueInterface::Status test_status = state.queue.create(0, name, depth, messageSize);
|
||||
ASSERT_EQ(status, created ? QueueInterface::Status::ALREADY_CREATED : QueueInterface::Status::OP_OK);
|
||||
ASSERT_EQ(status, test_status);
|
||||
ASSERT_EQ(name, state.queue.getName());
|
||||
|
||||
@ -27,7 +27,7 @@ struct Tester {
|
||||
public:
|
||||
//! Constructor
|
||||
Tester() = default;
|
||||
virtual ~Tester() = default;
|
||||
virtual ~Tester() { queue.teardown(); };
|
||||
|
||||
struct QueueMessage {
|
||||
U8 data[QUEUE_MESSAGE_SIZE_UPPER_BOUND];
|
||||
|
||||
@ -18,7 +18,9 @@ BlockDriverTester ::BlockDriverTester()
|
||||
this->connectPorts();
|
||||
}
|
||||
|
||||
BlockDriverTester ::~BlockDriverTester() {}
|
||||
BlockDriverTester ::~BlockDriverTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -24,7 +24,9 @@ SignalGenTester ::SignalGenTester() : SignalGenGTestBase("Tester", MAX_HISTORY_S
|
||||
this->m_reqDpBuff.set(this->m_dpBuff, sizeof(this->m_dpBuff));
|
||||
}
|
||||
|
||||
SignalGenTester ::~SignalGenTester() {}
|
||||
SignalGenTester ::~SignalGenTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -79,7 +79,9 @@ ActivePhaserTester ::ActivePhaserTester()
|
||||
this->connectPorts();
|
||||
}
|
||||
|
||||
ActivePhaserTester ::~ActivePhaserTester() {}
|
||||
ActivePhaserTester ::~ActivePhaserTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test helpers
|
||||
|
||||
@ -32,7 +32,9 @@ void ActiveRateGroupTester::clearPortCalls() {
|
||||
this->m_callOrder = 0;
|
||||
}
|
||||
|
||||
ActiveRateGroupTester::~ActiveRateGroupTester() {}
|
||||
ActiveRateGroupTester::~ActiveRateGroupTester() {
|
||||
this->m_impl.deinit();
|
||||
}
|
||||
|
||||
void ActiveRateGroupTester::from_RateGroupMemberOut_handler(FwIndexType portNum, U32 context) {
|
||||
ASSERT_TRUE(portNum < static_cast<FwIndexType>(FW_NUM_ARRAY_ELEMENTS(m_impl.m_RateGroupMemberOut_OutputPort)));
|
||||
|
||||
@ -23,7 +23,9 @@ ActiveTextLoggerTester ::ActiveTextLoggerTester()
|
||||
this->connectPorts();
|
||||
}
|
||||
|
||||
ActiveTextLoggerTester ::~ActiveTextLoggerTester() {}
|
||||
ActiveTextLoggerTester ::~ActiveTextLoggerTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -55,6 +55,7 @@ BufferAccumulatorTester ::~BufferAccumulatorTester() {
|
||||
Fw::MallocAllocator buffAccumMallocator;
|
||||
this->component.deallocateQueue(buffAccumMallocator);
|
||||
}
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@ -43,7 +43,9 @@ BufferLoggerTester ::BufferLoggerTester(bool doInitLog)
|
||||
}
|
||||
}
|
||||
|
||||
BufferLoggerTester ::~BufferLoggerTester() {}
|
||||
BufferLoggerTester ::~BufferLoggerTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -22,7 +22,9 @@ namespace Svc {
|
||||
CommandDispatcherTester::CommandDispatcherTester(Svc::CommandDispatcherImpl& inst)
|
||||
: CommandDispatcherGTestBase("testerbase", 100), m_impl(inst) {}
|
||||
|
||||
CommandDispatcherTester::~CommandDispatcherTester() {}
|
||||
CommandDispatcherTester::~CommandDispatcherTester() {
|
||||
this->m_impl.deinit();
|
||||
}
|
||||
|
||||
void CommandDispatcherTester::from_compCmdSend_handler(FwIndexType portNum,
|
||||
FwOpcodeType opCode,
|
||||
|
||||
@ -38,6 +38,7 @@ CmdSequencerTester ::CmdSequencerTester(const SequenceFiles::File::Format::t a_f
|
||||
|
||||
CmdSequencerTester ::~CmdSequencerTester() {
|
||||
this->component.deallocateBuffer(this->mallocator);
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@ -21,7 +21,9 @@ ComAggregatorTester ::ComAggregatorTester()
|
||||
this->connectPorts();
|
||||
}
|
||||
|
||||
ComAggregatorTester ::~ComAggregatorTester() {}
|
||||
ComAggregatorTester ::~ComAggregatorTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -28,7 +28,9 @@ ComLoggerTester ::ComLoggerTester(const char* const compName, bool standardCLIni
|
||||
(void)standardCLInit;
|
||||
}
|
||||
|
||||
ComLoggerTester ::~ComLoggerTester() {}
|
||||
ComLoggerTester ::~ComLoggerTester() {
|
||||
this->comLogger.deinit();
|
||||
}
|
||||
|
||||
void ComLoggerTester ::connectPorts() {
|
||||
comLogger.set_cmdRegOut_OutputPort(0, this->get_from_cmdRegOut(0));
|
||||
|
||||
@ -24,7 +24,9 @@ ComQueueTester ::ComQueueTester() : ComQueueGTestBase("Tester", MAX_HISTORY_SIZE
|
||||
this->connectPorts();
|
||||
}
|
||||
|
||||
ComQueueTester ::~ComQueueTester() {}
|
||||
ComQueueTester ::~ComQueueTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
void ComQueueTester ::dispatchAll() {
|
||||
while (this->component.m_queue.getMessagesAvailable() > 0) {
|
||||
|
||||
@ -26,7 +26,9 @@ DpCatalogTester ::DpCatalogTester()
|
||||
this->connectPorts();
|
||||
}
|
||||
|
||||
DpCatalogTester ::~DpCatalogTester() {}
|
||||
DpCatalogTester ::~DpCatalogTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -18,7 +18,9 @@ DpManagerTester ::DpManagerTester()
|
||||
this->connectPorts();
|
||||
}
|
||||
|
||||
DpManagerTester ::~DpManagerTester() {}
|
||||
DpManagerTester ::~DpManagerTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Handlers for typed from ports
|
||||
|
||||
@ -23,7 +23,9 @@ DpWriterTester ::DpWriterTester()
|
||||
Os::Stub::File::Test::StaticData::data.pointer = 0;
|
||||
}
|
||||
|
||||
DpWriterTester ::~DpWriterTester() {}
|
||||
DpWriterTester ::~DpWriterTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Handlers for typed from ports
|
||||
|
||||
@ -25,7 +25,9 @@ EventManagerTester::EventManagerTester(Svc::EventManager& inst)
|
||||
m_receivedPacket(false),
|
||||
m_receivedFatalEvent(false) {}
|
||||
|
||||
EventManagerTester::~EventManagerTester() {}
|
||||
EventManagerTester::~EventManagerTester() {
|
||||
this->m_impl.deinit();
|
||||
}
|
||||
|
||||
void EventManagerTester::from_PktSend_handler(const FwIndexType portNum, //!< The port number
|
||||
Fw::ComBuffer& data, //!< Buffer containing packet data
|
||||
|
||||
@ -46,11 +46,16 @@ void FileDownlink ::configure(U32 timeout, U32 cooldown, U32 cycleTime, U32 file
|
||||
this->m_configured = true;
|
||||
|
||||
Os::Queue::Status stat =
|
||||
m_fileQueue.create(Os::QueueString("fileDownlinkQueue"), static_cast<FwSizeType>(fileQueueDepth),
|
||||
static_cast<FwSizeType>(sizeof(struct FileEntry)));
|
||||
m_fileQueue.create(this->getInstance(), Os::QueueString("fileDownlinkQueue"),
|
||||
static_cast<FwSizeType>(fileQueueDepth), static_cast<FwSizeType>(sizeof(struct FileEntry)));
|
||||
FW_ASSERT(stat == Os::Queue::OP_OK, static_cast<FwAssertArgType>(stat));
|
||||
}
|
||||
|
||||
void FileDownlink ::deinit() {
|
||||
this->m_fileQueue.teardown();
|
||||
FileDownlinkComponentBase::deinit();
|
||||
}
|
||||
|
||||
void FileDownlink ::preamble() {
|
||||
FW_ASSERT(this->m_configured == true);
|
||||
}
|
||||
|
||||
@ -229,6 +229,9 @@ class FileDownlink final : public FileDownlinkComponentBase {
|
||||
U32 fileQueueDepth //!< Max number of items in file downlink queue
|
||||
);
|
||||
|
||||
//! Cleans up file queue before dispatching to underlying component
|
||||
void deinit();
|
||||
|
||||
//! Start FileDownlink component
|
||||
//! The component must be configured with configure() before starting.
|
||||
//!
|
||||
|
||||
@ -39,6 +39,7 @@ FileDownlinkTester ::~FileDownlinkTester() {
|
||||
for (U32 i = 0; i < buffers_index; i++) {
|
||||
delete[] buffers[i];
|
||||
}
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@ -31,7 +31,9 @@ FileManagerTester ::FileManagerTester() : FileManagerGTestBase("Tester", MAX_HIS
|
||||
this->initComponents();
|
||||
}
|
||||
|
||||
FileManagerTester ::~FileManagerTester() {}
|
||||
FileManagerTester ::~FileManagerTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -37,6 +37,7 @@ FileUplinkTester ::FileUplinkTester()
|
||||
|
||||
FileUplinkTester ::~FileUplinkTester() {
|
||||
this->component.m_file.osFile.close();
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@ -23,7 +23,9 @@ FpySequencerTester ::FpySequencerTester()
|
||||
clearSeq();
|
||||
}
|
||||
|
||||
FpySequencerTester ::~FpySequencerTester() {}
|
||||
FpySequencerTester ::~FpySequencerTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// dispatches events from the queue until the cmp reaches the given state
|
||||
void FpySequencerTester::dispatchUntilState(State state, U32 bound) {
|
||||
|
||||
@ -33,7 +33,9 @@ HealthTester ::HealthTester() : HealthGTestBase("Tester", MAX_HISTORY_SIZE), com
|
||||
this->initComponents();
|
||||
}
|
||||
|
||||
HealthTester ::~HealthTester() {}
|
||||
HealthTester ::~HealthTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Handlers for typed from ports
|
||||
|
||||
@ -1341,7 +1341,9 @@ PrmDbTester::PrmDbTester(Svc::PrmDbImpl& inst) : PrmDbGTestBase("testerbase", 10
|
||||
PrmDbTester::PrmDbTestFile::setTester(this);
|
||||
}
|
||||
|
||||
PrmDbTester::~PrmDbTester() {}
|
||||
PrmDbTester::~PrmDbTester() {
|
||||
this->m_impl.deinit();
|
||||
}
|
||||
|
||||
void PrmDbTester ::from_pingOut_handler(const FwIndexType portNum, U32 key) {
|
||||
this->pushFromPortEntry_pingOut(key);
|
||||
|
||||
@ -18,7 +18,9 @@ SeqDispatcherTester ::SeqDispatcherTester()
|
||||
this->initComponents();
|
||||
}
|
||||
|
||||
SeqDispatcherTester ::~SeqDispatcherTester() {}
|
||||
SeqDispatcherTester ::~SeqDispatcherTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -30,7 +30,9 @@ TlmChanTester ::TlmChanTester()
|
||||
this->connectPorts();
|
||||
}
|
||||
|
||||
TlmChanTester ::~TlmChanTester() {}
|
||||
TlmChanTester ::~TlmChanTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -28,7 +28,9 @@ TlmPacketizerTester ::TlmPacketizerTester()
|
||||
this->connectPorts();
|
||||
}
|
||||
|
||||
TlmPacketizerTester ::~TlmPacketizerTester() {}
|
||||
TlmPacketizerTester ::~TlmPacketizerTester() {
|
||||
this->component.deinit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Tests
|
||||
|
||||
@ -12,6 +12,7 @@ register_fprime_config(
|
||||
"${CMAKE_CURRENT_LIST_DIR}/FpConstants.fpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/FpySequencerCfg.fpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/MemoryAllocation.fpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/MemoryAllocation.hpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/PlatformCfg.fpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/PolyDbCfg.fpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/VersionCfg.fpp"
|
||||
|
||||
20
default/config/MemoryAllocation.hpp
Normal file
20
default/config/MemoryAllocation.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
// ======================================================================
|
||||
// \title config/MemoryAllocation.hpp
|
||||
// \author lestarch
|
||||
// \brief hpp file for memory allocation configuration
|
||||
//
|
||||
// \copyright
|
||||
// Copyright 2024, by the California Institute of Technology.
|
||||
// ALL RIGHTS RESERVED. United States Government Sponsorship
|
||||
// acknowledged.
|
||||
// ======================================================================
|
||||
#ifndef CONFIG_MEMORY_ALLOCATION_HPP
|
||||
#define CONFIG_MEMORY_ALLOCATION_HPP
|
||||
#include <Fw/Types/MallocAllocator.hpp>
|
||||
namespace Fw {
|
||||
namespace MemoryAllocation {
|
||||
using DefaultMemoryAllocatorType = Fw::MallocAllocator;
|
||||
} // namespace MemoryAllocation
|
||||
} // namespace Fw
|
||||
|
||||
#endif // CONFIG_MEMORY_ALLOCATION_HPP
|
||||
@ -15,7 +15,7 @@ constant FW_FILE_HANDLE_MAX_SIZE = 16
|
||||
constant FW_MUTEX_HANDLE_MAX_SIZE = 72
|
||||
|
||||
@ Maximum size of a handle for Os::Queue
|
||||
constant FW_QUEUE_HANDLE_MAX_SIZE = 352
|
||||
constant FW_QUEUE_HANDLE_MAX_SIZE = 368
|
||||
|
||||
@ Maximum size of a handle for Os::Directory
|
||||
constant FW_DIRECTORY_HANDLE_MAX_SIZE = 16
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user