Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .github/workflows/format-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ jobs:
env:
CHECKED_DIRS: >-
Drv
Fw/Buffer
Fw/Cmd
Fw/Com
Fw
Os
Svc/Ccsds
Svc/EventManager
Expand Down
201 changes: 95 additions & 106 deletions Fw/Comp/ActiveComponentBase.cpp
Original file line number Diff line number Diff line change
@@ -1,138 +1,127 @@
#include <Fw/FPrimeBasicTypes.hpp>
#include <Fw/Comp/ActiveComponentBase.hpp>
#include <Fw/FPrimeBasicTypes.hpp>
#include <Fw/Types/Assert.hpp>
#include <Os/TaskString.hpp>

namespace Fw {

class ActiveComponentExitSerializableBuffer : public Fw::SerializeBufferBase {

public:
FwSizeType getBuffCapacity() const {
return sizeof(m_buff);
}

U8* getBuffAddr() {
return m_buff;
}
class ActiveComponentExitSerializableBuffer : public Fw::SerializeBufferBase {

Check notice

Code scanning / CodeQL

More than one statement per line Note

This line contains 2 statements; only one is allowed.
public:
FwSizeType getBuffCapacity() const { return sizeof(m_buff); }

Check notice

Code scanning / CodeQL

More than one statement per line Note

This line contains 2 statements; only one is allowed.

const U8* getBuffAddr() const {
return m_buff;
}
U8* getBuffAddr() { return m_buff; }

Check notice

Code scanning / CodeQL

More than one statement per line Note

This line contains 2 statements; only one is allowed.

private:
const U8* getBuffAddr() const { return m_buff; }

Check notice

Code scanning / CodeQL

More than one statement per line Note

This line contains 2 statements; only one is allowed.

U8 m_buff[sizeof(ActiveComponentBase::ACTIVE_COMPONENT_EXIT)];
private:
U8 m_buff[sizeof(ActiveComponentBase::ACTIVE_COMPONENT_EXIT)];
};

};
ActiveComponentBase::ActiveComponentBase(const char* name) : QueuedComponentBase(name) {}

Check notice

Code scanning / CodeQL

Use of basic integral type Note

name uses the basic integral type char rather than a typedef with size and signedness.

Check notice

Code scanning / CodeQL

More than one statement per line Note

This line contains 2 statements; only one is allowed.

Check warning

Code scanning / CppCheck

Member variable 'ActiveComponentBase::m_stage' is not initialized in the constructor. Warning

Member variable 'ActiveComponentBase::m_stage' is not initialized in the constructor.

ActiveComponentBase::ActiveComponentBase(const char* name) : QueuedComponentBase(name) {
ActiveComponentBase::~ActiveComponentBase() {}

Check notice

Code scanning / CodeQL

More than one statement per line Note

This line contains 2 statements; only one is allowed.

}

ActiveComponentBase::~ActiveComponentBase() {
}

void ActiveComponentBase::init(FwEnumStoreType instance) {
QueuedComponentBase::init(instance);
}
void ActiveComponentBase::init(FwEnumStoreType instance) {
QueuedComponentBase::init(instance);

Check warning

Code scanning / CodeQL

Unchecked function argument Warning

This use of parameter instance has not been checked.
}

#if FW_OBJECT_TO_STRING == 1
const char* ActiveComponentBase::getToStringFormatString() {
return "ActComp: %s";
}
const char* ActiveComponentBase::getToStringFormatString() {

Check notice

Code scanning / CodeQL

Use of basic integral type Note

getToStringFormatString uses the basic integral type char rather than a typedef with size and signedness.
return "ActComp: %s";
}
#endif

void ActiveComponentBase::start(FwTaskPriorityType priority, FwSizeType stackSize, FwSizeType cpuAffinity, FwTaskIdType identifier) {
Os::TaskString taskName;
void ActiveComponentBase::start(FwTaskPriorityType priority,

Check notice

Code scanning / CodeQL

Long function without assertion Note

All functions of more than 10 lines should have at least one assertion.
FwSizeType stackSize,
FwSizeType cpuAffinity,
FwTaskIdType identifier) {
Os::TaskString taskName;

#if FW_OBJECT_NAMES == 1
taskName = this->getObjName();
taskName = this->getObjName();

Check warning

Code scanning / CodeQL

Unchecked return value Warning

The return value of non-void function
operator=
is not checked.
#else
(void) taskName.format("ActComp_%" PRI_FwSizeType, Os::Task::getNumTasks());
(void)taskName.format("ActComp_%" PRI_FwSizeType, Os::Task::getNumTasks());
#endif
// Cooperative threads tasks externalize the task loop, and as such use the state machine as their task function
// Standard multithreading tasks use the task loop to respectively call the state machine
Os::Task::taskRoutine routine = (m_task.isCooperative()) ? this->s_taskStateMachine : this->s_taskLoop;
Os::Task::Arguments arguments(taskName, routine, this, priority, stackSize, cpuAffinity, identifier);
Os::Task::Status status = this->m_task.start(arguments);
FW_ASSERT(status == Os::Task::Status::OP_OK,static_cast<FwAssertArgType>(status));
}
// Cooperative threads tasks externalize the task loop, and as such use the state machine as their task function
// Standard multithreading tasks use the task loop to respectively call the state machine
Os::Task::taskRoutine routine = (m_task.isCooperative()) ? this->s_taskStateMachine : this->s_taskLoop;
Os::Task::Arguments arguments(taskName, routine, this, priority, stackSize, cpuAffinity, identifier);

Check warning

Code scanning / CodeQL

Unchecked function argument Warning

This use of parameter priority has not been checked.

Check warning

Code scanning / CodeQL

Unchecked function argument Warning

This use of parameter stackSize has not been checked.

Check warning

Code scanning / CodeQL

Unchecked function argument Warning

This use of parameter cpuAffinity has not been checked.

Check warning

Code scanning / CodeQL

Unchecked function argument Warning

This use of parameter identifier has not been checked.
Os::Task::Status status = this->m_task.start(arguments);
FW_ASSERT(status == Os::Task::Status::OP_OK, static_cast<FwAssertArgType>(status));
}

void ActiveComponentBase::exit() {
ActiveComponentExitSerializableBuffer exitBuff;
SerializeStatus stat = exitBuff.serialize(static_cast<I32>(ACTIVE_COMPONENT_EXIT));
FW_ASSERT(FW_SERIALIZE_OK == stat,static_cast<FwAssertArgType>(stat));
(void)this->m_queue.send(exitBuff,0,Os::Queue::BlockingType::NONBLOCKING);
}
void ActiveComponentBase::exit() {
ActiveComponentExitSerializableBuffer exitBuff;
SerializeStatus stat = exitBuff.serialize(static_cast<I32>(ACTIVE_COMPONENT_EXIT));
FW_ASSERT(FW_SERIALIZE_OK == stat, static_cast<FwAssertArgType>(stat));
(void)this->m_queue.send(exitBuff, 0, Os::Queue::BlockingType::NONBLOCKING);
}

Os::Task::Status ActiveComponentBase::join() {
return this->m_task.join();
}
Os::Task::Status ActiveComponentBase::join() {
return this->m_task.join();
}

Os::Task::Status ActiveComponentBase::join(void** pointer) {
return this->m_task.join();
}
Os::Task::Status ActiveComponentBase::join(void** pointer) {
return this->m_task.join();
}

void ActiveComponentBase::s_taskStateMachine(void* component_pointer) {
FW_ASSERT(component_pointer != nullptr);
// cast void* back to active component
ActiveComponentBase* component = static_cast<ActiveComponentBase*>(component_pointer);

// Each invocation of this function runs a single stage of the thread lifecycle. This has moved the thread
// while loop to the top level such that it can be replaced by something else (e.g. cooperative thread
// dispatcher) and is not intrinsic to this code.
switch (component->m_stage) {
// The first stage the active component triggers the "preamble" call before moving into the dispatching
// stage of the component thread.
case Lifecycle::CREATED:
component->preamble();
component->m_stage = Lifecycle::DISPATCHING;
break;
// The second stage of the active component triggers the dispatching loop dispatching messages until an
// exit message is received.
case Lifecycle::DISPATCHING:
if (component->dispatch() == MsgDispatchStatus::MSG_DISPATCH_EXIT) {
component->m_stage = Lifecycle::FINALIZING;
}
break;
// The second-to-last stage is where the finalizer is called. This will transition to the final stage
// automatically after the finalizer is called
case Lifecycle::FINALIZING:
component->finalizer();
component->m_stage = Lifecycle::DONE;
break;
// The last stage does nothing, cooperative tasks live here forever, threaded tasks exit on this condition
case Lifecycle::DONE:
break;
default:
FW_ASSERT(0);
break;
}
void ActiveComponentBase::s_taskStateMachine(void* component_pointer) {

Check notice

Code scanning / CodeQL

Long function without assertion Note

All functions of more than 10 lines should have at least one assertion.
FW_ASSERT(component_pointer != nullptr);
// cast void* back to active component
ActiveComponentBase* component = static_cast<ActiveComponentBase*>(component_pointer);

// Each invocation of this function runs a single stage of the thread lifecycle. This has moved the thread
// while loop to the top level such that it can be replaced by something else (e.g. cooperative thread
// dispatcher) and is not intrinsic to this code.
switch (component->m_stage) {
// The first stage the active component triggers the "preamble" call before moving into the dispatching
// stage of the component thread.
case Lifecycle::CREATED:
component->preamble();
component->m_stage = Lifecycle::DISPATCHING;
break;
// The second stage of the active component triggers the dispatching loop dispatching messages until an
// exit message is received.
case Lifecycle::DISPATCHING:
if (component->dispatch() == MsgDispatchStatus::MSG_DISPATCH_EXIT) {
component->m_stage = Lifecycle::FINALIZING;
}
break;
// The second-to-last stage is where the finalizer is called. This will transition to the final stage
// automatically after the finalizer is called
case Lifecycle::FINALIZING:
component->finalizer();
component->m_stage = Lifecycle::DONE;
break;
// The last stage does nothing, cooperative tasks live here forever, threaded tasks exit on this condition
case Lifecycle::DONE:
break;
default:
FW_ASSERT(0);
break;
}
}

void ActiveComponentBase::s_taskLoop(void* component_pointer) {
FW_ASSERT(component_pointer != nullptr);
ActiveComponentBase* component = static_cast<ActiveComponentBase*>(component_pointer);
// A non-cooperative task switching implementation is just a while-loop around the active component
// state-machine. Here the while loop is at top-level.
while (component->m_stage != ActiveComponentBase::Lifecycle::DONE) {
ActiveComponentBase::s_taskStateMachine(component);
}
void ActiveComponentBase::s_taskLoop(void* component_pointer) {
FW_ASSERT(component_pointer != nullptr);
ActiveComponentBase* component = static_cast<ActiveComponentBase*>(component_pointer);
// A non-cooperative task switching implementation is just a while-loop around the active component
// state-machine. Here the while loop is at top-level.
while (component->m_stage != ActiveComponentBase::Lifecycle::DONE) {
ActiveComponentBase::s_taskStateMachine(component);
}

Check warning

Code scanning / CodeQL

Unbounded loop Warning

This loop does not have a fixed bound.
}

ActiveComponentBase::MsgDispatchStatus ActiveComponentBase::dispatch() {
// Cooperative tasks should return rather than block when no messages are available
if (this->m_task.isCooperative() and m_queue.getMessagesAvailable() == 0) {
return MsgDispatchStatus::MSG_DISPATCH_EMPTY;
}
return this->doDispatch();
ActiveComponentBase::MsgDispatchStatus ActiveComponentBase::dispatch() {
// Cooperative tasks should return rather than block when no messages are available
if (this->m_task.isCooperative() and m_queue.getMessagesAvailable() == 0) {
return MsgDispatchStatus::MSG_DISPATCH_EMPTY;
}
return this->doDispatch();
}

void ActiveComponentBase::preamble() {
}
void ActiveComponentBase::preamble() {}

Check notice

Code scanning / CodeQL

More than one statement per line Note

This line contains 2 statements; only one is allowed.

void ActiveComponentBase::finalizer() {
}
void ActiveComponentBase::finalizer() {}

Check notice

Code scanning / CodeQL

More than one statement per line Note

This line contains 2 statements; only one is allowed.

}
} // namespace Fw
37 changes: 19 additions & 18 deletions Fw/Comp/ActiveComponentBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
#ifndef FW_ACTIVE_COMPONENT_BASE_HPP
#define FW_ACTIVE_COMPONENT_BASE_HPP

#include <Fw/FPrimeBasicTypes.hpp>
#include <Fw/Comp/QueuedComponentBase.hpp>
#include <Fw/Deprecate.hpp>
#include <Fw/FPrimeBasicTypes.hpp>
#include <Os/Task.hpp>

namespace Fw {
Expand All @@ -22,11 +22,12 @@ class ActiveComponentBase : public QueuedComponentBase {
void start(FwTaskPriorityType priority = Os::Task::TASK_PRIORITY_DEFAULT,
FwSizeType stackSize = Os::Task::TASK_DEFAULT,
FwSizeType cpuAffinity = Os::Task::TASK_DEFAULT,
FwTaskIdType identifier =
static_cast<FwTaskIdType>(Os::Task::TASK_DEFAULT)); //!< called by instantiator when task is to be started
void exit(); //!< exit task in active component
Os::Task::Status join(); //!< Join the thread
DEPRECATED(Os::Task::Status join(void** value_ptr), "Switch to .join()"); //!< Join to thread with discarded value_ptr
FwTaskIdType identifier = static_cast<FwTaskIdType>(
Os::Task::TASK_DEFAULT)); //!< called by instantiator when task is to be started
void exit(); //!< exit task in active component
Os::Task::Status join(); //!< Join the thread
DEPRECATED(Os::Task::Status join(void** value_ptr),
"Switch to .join()"); //!< Join to thread with discarded value_ptr

enum {
ACTIVE_COMPONENT_EXIT //!< message to exit active component task
Expand All @@ -35,27 +36,27 @@ class ActiveComponentBase : public QueuedComponentBase {
protected:
//! Tracks the lifecycle of the component
enum Lifecycle {
CREATED, //!< Initial stage, call preamble
DISPATCHING, //!< Component is dispatching messages
FINALIZING, //!< Penultimate stage, call finalizer
DONE, //!< Done, doing nothing
CREATED, //!< Initial stage, call preamble
DISPATCHING, //!< Component is dispatching messages
FINALIZING, //!< Penultimate stage, call finalizer
DONE, //!< Done, doing nothing
};

explicit ActiveComponentBase(const char* name); //!< Constructor
virtual ~ActiveComponentBase(); //!< Destructor
void init(FwEnumStoreType instance); //!< initialization code
virtual void preamble(); //!< A function that will be called before the event loop is entered
MsgDispatchStatus dispatch(); //!< The function that will dispatching messages
virtual void finalizer(); //!< A function that will be called after exiting the loop
Os::Task m_task; //!< task object for active component
virtual void preamble(); //!< A function that will be called before the event loop is entered
MsgDispatchStatus dispatch(); //!< The function that will dispatching messages
virtual void finalizer(); //!< A function that will be called after exiting the loop
Os::Task m_task; //!< task object for active component

#if FW_OBJECT_TO_STRING == 1
virtual const char* getToStringFormatString(); //!< Format string for toString function
virtual const char* getToStringFormatString(); //!< Format string for toString function
#endif
private:
Lifecycle m_stage; //!< Lifecycle stage of the component
static void s_taskStateMachine(void*); //!< Task lifecycle state machine
static void s_taskLoop(void*); //!< Standard multi-threading task loop
Lifecycle m_stage; //!< Lifecycle stage of the component
static void s_taskStateMachine(void*); //!< Task lifecycle state machine
static void s_taskLoop(void*); //!< Standard multi-threading task loop
};

} // namespace Fw
Expand Down
Loading
Loading