| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include <Fw/Comp/ActiveComponentBase.hpp> | ||
| 2 | #include <Fw/FPrimeBasicTypes.hpp> | ||
| 3 | #include <Fw/Types/Assert.hpp> | ||
| 4 | #include <Os/TaskString.hpp> | ||
| 5 | |||
| 6 | namespace Fw { | ||
| 7 | |||
| 8 | class ActiveComponentExitSerializableBuffer : public Fw::LinearBufferBase { | ||
| 9 | public: | ||
| 10 | ✗ | ActiveComponentExitSerializableBuffer() : Fw::LinearBufferBase(m_buff, sizeof(m_buff)) {} | |
| 11 | |||
| 12 | private: | ||
| 13 | U8 m_buff[sizeof(ActiveComponentBase::ACTIVE_COMPONENT_EXIT)]; | ||
| 14 | }; | ||
| 15 | |||
| 16 |
1/1✓ Branch 11 taken 1291 times.
|
1291 | ActiveComponentBase::ActiveComponentBase(const char* name) : QueuedComponentBase(name), m_stage(Lifecycle::CREATED) {} |
| 17 | |||
| 18 | 2582 | ActiveComponentBase::~ActiveComponentBase() {} | |
| 19 | |||
| 20 | 1290 | void ActiveComponentBase::init(FwEnumStoreType instance) { | |
| 21 | 1290 | QueuedComponentBase::init(instance); | |
| 22 | 1290 | } | |
| 23 | |||
| 24 | #if FW_OBJECT_TO_STRING == 1 | ||
| 25 | ✗ | const char* ActiveComponentBase::getToStringFormatString() { | |
| 26 | ✗ | return "ActComp: %s"; | |
| 27 | } | ||
| 28 | #endif | ||
| 29 | |||
| 30 | ✗ | void ActiveComponentBase::start(FwTaskPriorityType priority, | |
| 31 | FwSizeType stackSize, | ||
| 32 | FwSizeType cpuAffinity, | ||
| 33 | FwTaskIdType identifier) { | ||
| 34 | ✗ | Os::TaskString taskName; | |
| 35 | |||
| 36 | #if FW_OBJECT_NAMES == 1 | ||
| 37 | ✗ | taskName = this->getObjName(); | |
| 38 | #else | ||
| 39 | (void)taskName.format("ActComp_%" PRI_FwSizeType, Os::Task::getNumTasks()); | ||
| 40 | #endif | ||
| 41 | // Cooperative threads tasks externalize the task loop, and as such use the state machine as their task function | ||
| 42 | // Standard multithreading tasks use the task loop to respectively call the state machine | ||
| 43 | ✗ | Os::Task::taskRoutine routine = (m_task.isCooperative()) ? this->s_taskStateMachine : this->s_taskLoop; | |
| 44 | ✗ | Os::Task::Arguments arguments(taskName, routine, this, priority, stackSize, cpuAffinity, identifier); | |
| 45 | ✗ | Os::Task::Status status = this->m_task.start(arguments); | |
| 46 | ✗ | FW_ASSERT(status == Os::Task::Status::OP_OK, static_cast<FwAssertArgType>(status)); | |
| 47 | ✗ | } | |
| 48 | |||
| 49 | ✗ | void ActiveComponentBase::exit() { | |
| 50 | ✗ | ActiveComponentExitSerializableBuffer exitBuff; | |
| 51 | ✗ | SerializeStatus stat = exitBuff.serializeFrom(static_cast<I32>(ACTIVE_COMPONENT_EXIT)); | |
| 52 | ✗ | FW_ASSERT(FW_SERIALIZE_OK == stat, static_cast<FwAssertArgType>(stat)); | |
| 53 | ✗ | (void)this->m_queue.send(exitBuff, 0, Os::Queue::BlockingType::NONBLOCKING); | |
| 54 | ✗ | } | |
| 55 | |||
| 56 | ✗ | Os::Task::Status ActiveComponentBase::join() { | |
| 57 | ✗ | return this->m_task.join(); | |
| 58 | } | ||
| 59 | |||
| 60 | ✗ | Os::Task::Status ActiveComponentBase::join(void** pointer) { | |
| 61 | ✗ | return this->m_task.join(); | |
| 62 | } | ||
| 63 | |||
| 64 | ✗ | void ActiveComponentBase::s_taskStateMachine(void* component_pointer) { | |
| 65 | ✗ | FW_ASSERT(component_pointer != nullptr); | |
| 66 | // cast void* back to active component | ||
| 67 | ✗ | ActiveComponentBase* component = static_cast<ActiveComponentBase*>(component_pointer); | |
| 68 | |||
| 69 | // Each invocation of this function runs a single stage of the thread lifecycle. This has moved the thread | ||
| 70 | // while loop to the top level such that it can be replaced by something else (e.g. cooperative thread | ||
| 71 | // dispatcher) and is not intrinsic to this code. | ||
| 72 | ✗ | switch (component->m_stage) { | |
| 73 | // The first stage the active component triggers the "preamble" call before moving into the dispatching | ||
| 74 | // stage of the component thread. | ||
| 75 | ✗ | case Lifecycle::CREATED: | |
| 76 | ✗ | component->preamble(); | |
| 77 | ✗ | component->m_stage = Lifecycle::DISPATCHING; | |
| 78 | ✗ | break; | |
| 79 | // The second stage of the active component triggers the dispatching loop dispatching messages until an | ||
| 80 | // exit message is received. | ||
| 81 | ✗ | case Lifecycle::DISPATCHING: | |
| 82 | ✗ | if (component->dispatch() == MsgDispatchStatus::MSG_DISPATCH_EXIT) { | |
| 83 | ✗ | component->m_stage = Lifecycle::FINALIZING; | |
| 84 | } | ||
| 85 | ✗ | break; | |
| 86 | // The second-to-last stage is where the finalizer is called. This will transition to the final stage | ||
| 87 | // automatically after the finalizer is called | ||
| 88 | ✗ | case Lifecycle::FINALIZING: | |
| 89 | ✗ | component->finalizer(); | |
| 90 | ✗ | component->m_stage = Lifecycle::DONE; | |
| 91 | ✗ | break; | |
| 92 | // The last stage does nothing, cooperative tasks live here forever, threaded tasks exit on this condition | ||
| 93 | ✗ | case Lifecycle::DONE: | |
| 94 | ✗ | break; | |
| 95 | ✗ | default: | |
| 96 | ✗ | FW_ASSERT(false); | |
| 97 | ✗ | break; | |
| 98 | } | ||
| 99 | ✗ | } | |
| 100 | |||
| 101 | ✗ | void ActiveComponentBase::s_taskLoop(void* component_pointer) { | |
| 102 | ✗ | FW_ASSERT(component_pointer != nullptr); | |
| 103 | ✗ | ActiveComponentBase* component = static_cast<ActiveComponentBase*>(component_pointer); | |
| 104 | // A non-cooperative task switching implementation is just a while-loop around the active component | ||
| 105 | // state-machine. Here the while loop is at top-level. | ||
| 106 | // @non-terminating@: component lifecycle loop runs until DONE | ||
| 107 | ✗ | while (component->m_stage != ActiveComponentBase::Lifecycle::DONE) { | |
| 108 | ✗ | ActiveComponentBase::s_taskStateMachine(component); | |
| 109 | } | ||
| 110 | ✗ | } | |
| 111 | |||
| 112 | ✗ | ActiveComponentBase::MsgDispatchStatus ActiveComponentBase::dispatch() { | |
| 113 | // Cooperative tasks should return rather than block when no messages are available | ||
| 114 | ✗ | if (this->m_task.isCooperative() and m_queue.getMessagesAvailable() == 0) { | |
| 115 | ✗ | return MsgDispatchStatus::MSG_DISPATCH_EMPTY; | |
| 116 | } | ||
| 117 | ✗ | return this->doDispatch(); | |
| 118 | } | ||
| 119 | |||
| 120 | 74 | void ActiveComponentBase::preamble() {} | |
| 121 | |||
| 122 | ✗ | void ActiveComponentBase::finalizer() {} | |
| 123 | |||
| 124 | } // namespace Fw | ||
| 125 |