F´ Flight Software - C/C++ Documentation  devel
A framework for building embedded system applications to NASA flight quality standards.
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 
10 namespace 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 
34 
35  }
36 
38  DEBUG_PRINT("ActiveComponent %s destructor.\n",this->getObjName());
39  }
40 
42  QueuedComponentBase::init(instance);
43  }
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));
78  (void)this->m_queue.send(exitBuff,0,Os::Queue::BlockingType::NONBLOCKING);
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.
102  case Lifecycle::CREATED:
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.
108  case Lifecycle::DISPATCHING:
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
115  case Lifecycle::FINALIZING:
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) {
141  return MsgDispatchStatus::MSG_DISPATCH_EMPTY;
142  }
143  return this->doDispatch();
144  }
145 
147  }
148 
150  }
151 
152 }
#define DEBUG_PRINT(...)
#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.
Os::Task::Status join()
Join the thread.
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
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
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
SerializeStatus
forward declaration for string
@ FW_SERIALIZE_OK
Serialization/Deserialization operation was successful.
@ OP_OK
Operation succeeded.
Definition: Os.hpp:26