F´ Flight Software - C/C++ Documentation
A framework for building embedded system applications to NASA flight quality standards.
Loading...
Searching...
No Matches
ActiveComponentBase.cpp
Go to the documentation of this file.
1#include <FpConfig.hpp>
3#include <Fw/Types/Assert.hpp>
4#include <Os/TaskString.hpp>
5#include <cstdio>
6
7//#define DEBUG_PRINT(...) printf(##__VA_ARGS__); fflush(stdout)
8#define DEBUG_PRINT(...)
9
10namespace Fw {
11
13
14 public:
16 return sizeof(m_buff);
17 }
18
20 return m_buff;
21 }
22
23 const U8* getBuffAddr() const {
24 return m_buff;
25 }
26
27 private:
28
30
31 };
32
36
38 DEBUG_PRINT("ActiveComponent %s destructor.\n",this->getObjName());
39 }
40
44
45#if FW_OBJECT_TO_STRING == 1 && FW_OBJECT_NAMES == 1
46 void ActiveComponentBase::toString(char* buffer, NATIVE_INT_TYPE size) {
47 FW_ASSERT(size > 0);
48 FW_ASSERT(buffer != nullptr);
49 PlatformIntType status = snprintf(buffer, static_cast<size_t>(size), "ActComp: %s", this->m_objName.toChar());
50 if (status < 0) {
51 buffer[0] = 0;
52 }
53 }
54#endif
55
57 Os::TaskString taskName;
58
59#if FW_OBJECT_NAMES == 1
60 taskName = this->getObjName();
61#else
62 char taskNameChar[FW_TASK_NAME_BUFFER_SIZE];
63 (void)snprintf(taskNameChar,sizeof(taskNameChar),"ActComp_%d",Os::Task::getNumTasks());
64 taskName = taskNameChar;
65#endif
66 // Cooperative threads tasks externalize the task loop, and as such use the state machine as their task function
67 // Standard multithreading tasks use the task loop to respectively call the state machine
68 Os::Task::taskRoutine routine = (m_task.isCooperative()) ? this->s_taskStateMachine : this->s_taskLoop;
69 Os::Task::Arguments arguments(taskName, routine, this, priority, stackSize, cpuAffinity, static_cast<PlatformUIntType>(identifier));
70 Os::Task::Status status = this->m_task.start(arguments);
71 FW_ASSERT(status == Os::Task::Status::OP_OK,static_cast<NATIVE_INT_TYPE>(status));
72 }
73
76 SerializeStatus stat = exitBuff.serialize(static_cast<I32>(ACTIVE_COMPONENT_EXIT));
77 FW_ASSERT(FW_SERIALIZE_OK == stat,static_cast<NATIVE_INT_TYPE>(stat));
79 DEBUG_PRINT("exit %s\n", this->getObjName());
80 }
81
83 DEBUG_PRINT("join %s\n", this->getObjName());
84 return this->m_task.join();
85 }
86
88 return this->m_task.join();
89 }
90
91 void ActiveComponentBase::s_taskStateMachine(void* component_pointer) {
92 FW_ASSERT(component_pointer != nullptr);
93 // cast void* back to active component
94 ActiveComponentBase* component = static_cast<ActiveComponentBase*>(component_pointer);
95
96 // Each invocation of this function runs a single stage of the thread lifecycle. This has moved the thread
97 // while loop to the top level such that it can be replaced by something else (e.g. cooperative thread
98 // dispatcher) and is not intrinsic to this code.
99 switch (component->m_stage) {
100 // The first stage the active component triggers the "preamble" call before moving into the dispatching
101 // stage of the component thread.
103 component->preamble();
104 component->m_stage = Lifecycle::DISPATCHING;
105 break;
106 // The second stage of the active component triggers the dispatching loop dispatching messages until an
107 // exit message is received.
109 if (component->dispatch() == MsgDispatchStatus::MSG_DISPATCH_EXIT) {
110 component->m_stage = Lifecycle::FINALIZING;
111 }
112 break;
113 // The second-to-last stage is where the finalizer is called. This will transition to the final stage
114 // automatically after the finalizer is called
116 component->finalizer();
117 component->m_stage = Lifecycle::DONE;
118 break;
119 // The last stage does nothing, cooperative tasks live here forever, threaded tasks exit on this condition
120 case Lifecycle::DONE:
121 break;
122 default:
123 FW_ASSERT(0);
124 break;
125 }
126 }
127
128 void ActiveComponentBase::s_taskLoop(void* component_pointer) {
129 FW_ASSERT(component_pointer != nullptr);
130 ActiveComponentBase* component = static_cast<ActiveComponentBase*>(component_pointer);
131 // A non-cooperative task switching implementation is just a while-loop around the active component
132 // state-machine. Here the while loop is at top-level.
133 while (component->m_stage != ActiveComponentBase::Lifecycle::DONE) {
134 ActiveComponentBase::s_taskStateMachine(component);
135 }
136 }
137
139 // Cooperative tasks should return rather than block when no messages are available
140 if (this->m_task.isCooperative() and m_queue.getMessagesAvailable() == 0) {
142 }
143 return this->doDispatch();
144 }
145
148
151
152}
#define FW_ASSERT(...)
Definition Assert.hpp:14
PlatformIntType NATIVE_INT_TYPE
Definition BasicTypes.h:55
uint8_t U8
8-bit unsigned integer
Definition BasicTypes.h:30
PlatformUIntType NATIVE_UINT_TYPE
Definition BasicTypes.h:56
unsigned int PlatformUIntType
int PlatformIntType
DefaultTypes.hpp provides fallback defaults for the platform types.
#define FW_TASK_NAME_BUFFER_SIZE
Max size of task name.
Definition FpConfig.h:277
C++-compatible configuration header for fprime configuration.
#define DEBUG_PRINT
Os::Task::Status join()
Join the thread.
@ DISPATCHING
Component is dispatching messages.
@ CREATED
Initial stage, call preamble.
@ FINALIZING
Penultimate stage, call finalizer.
@ DONE
Done, doing nothing.
Os::Task m_task
task object for active component
@ ACTIVE_COMPONENT_EXIT
message to exit active component task
ActiveComponentBase(const char *name)
Constructor.
void start(Os::Task::ParamType priority=Os::Task::TASK_DEFAULT, Os::Task::ParamType stackSize=Os::Task::TASK_DEFAULT, Os::Task::ParamType cpuAffinity=Os::Task::TASK_DEFAULT, Os::Task::ParamType identifier=Os::Task::TASK_DEFAULT)
called by instantiator when task is to be started
void exit()
exit task in active component
virtual ~ActiveComponentBase()
Destructor.
MsgDispatchStatus dispatch()
The function that will dispatching messages.
virtual void finalizer()
A function that will be called after exiting the loop.
virtual void preamble()
A function that will be called before the event loop is entered.
const U8 * getBuffAddr() const
gets buffer address for data reading, const version
NATIVE_UINT_TYPE getBuffCapacity() const
returns capacity, not current size, of buffer
U8 * getBuffAddr()
gets buffer address for data filling
void init()
Object initializer.
Definition ObjBase.cpp:27
virtual MsgDispatchStatus doDispatch()=0
method to dispatch a single message in the queue.
Os::Queue m_queue
queue object for active component
@ MSG_DISPATCH_EMPTY
No more messages in the queue.
@ MSG_DISPATCH_EXIT
A message was sent requesting an exit of the loop.
SerializeStatus serialize(U8 val)
serialize 8-bit unsigned int
Status send(const U8 *buffer, FwSizeType size, FwQueuePriorityType priority, BlockingType blockType) override
send a message into the queue through delegate
FwSizeType getMessagesAvailable() const override
get number of messages available
Definition Queue.cpp:77
@ NONBLOCKING
Message will return with status when space is unavailable.
Definition Queue.hpp:46
static FwSizeType getNumTasks()
get the current number of tasks
Definition Task.cpp:179
bool isCooperative() override
determine if the task is cooperative multitasking (implementation specific)
Definition Task.cpp:164
FwSizeType ParamType
backwards-compatible parameter type
Definition Task.hpp:219
Status start(const Arguments &arguments) override
start the task
Definition Task.cpp:82
Status join() override
block until the task has ended
Definition Task.cpp:134
void(* taskRoutine)(void *ptr)
Prototype for task routine started in task context.
Definition Task.hpp:59
@ OP_OK
message sent/received okay
Definition Task.hpp:30
SerializeStatus
forward declaration for string
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.