Simple "Blinky" example for the QP active object framework
Fork of qp_dpp by
Diff: philo.cpp
- Revision:
- 4:6189d844a1a2
- Parent:
- 3:81ceb3127876
diff -r 81ceb3127876 -r 6189d844a1a2 philo.cpp --- a/philo.cpp Mon Sep 26 02:21:01 2011 +0000 +++ b/philo.cpp Tue Sep 04 22:41:20 2012 +0000 @@ -1,65 +1,62 @@ ////////////////////////////////////////////////////////////////////////////// -// Product: DPP example -// Last Updated for Version: 4.2.00 -// Date of the Last Update: Jul 15, 2011 -// -// Q u a n t u m L e a P s -// --------------------------- -// innovating embedded systems -// -// Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved. +// Model: dpp.qm +// File: ././philo.cpp // -// This software may be distributed and modified under the terms of the GNU -// General Public License version 2 (GPL) as published by the Free Software -// Foundation and appearing in the file GPL.TXT included in the packaging of -// this file. Please note that GPL Section 2[b] requires that all works based -// on this software must also be made publicly available under the terms of -// the GPL ("Copyleft"). +// This file has been generated automatically by QP Modeler (QM). +// DO NOT EDIT THIS FILE MANUALLY. // -// Alternatively, this software may be distributed and modified under the -// terms of Quantum Leaps commercial licenses, which expressly supersede -// the GPL and are specifically designed for licensees interested in -// retaining the proprietary status of their code. -// -// Contact information: -// Quantum Leaps Web site: http://www.quantum-leaps.com -// e-mail: info@quantum-leaps.com +// Please visit www.state-machine.com/qm for more information. ////////////////////////////////////////////////////////////////////////////// #include "qp_port.h" #include "dpp.h" #include "bsp.h" +namespace DPP { + Q_DEFINE_THIS_FILE // Active object class ------------------------------------------------------- -class Philo : public QActive { +// @(/2/0) ................................................................... +class Philo : public QP::QActive { private: - QTimeEvt m_timeEvt; // to timeout thinking or eating + QP::QTimeEvt m_timeEvt; public: Philo(); -private: - static QState initial (Philo *me, QEvent const *e); - static QState thinking(Philo *me, QEvent const *e); - static QState hungry (Philo *me, QEvent const *e); - static QState eating (Philo *me, QEvent const *e); +protected: + static QP::QState initial(Philo * const me, QP::QEvt const * const e); + static QP::QState thinking(Philo * const me, QP::QEvt const * const e); + static QP::QState hungry(Philo * const me, QP::QEvt const * const e); + static QP::QState eating(Philo * const me, QP::QEvt const * const e); }; // Local objects ------------------------------------------------------------- -static Philo l_philo[N_PHILO]; // storage for all Philos +static Philo l_philo[N_PHILO]; // storage for all Philos -#define THINK_TIME (BSP_TICKS_PER_SEC/2) -#define EAT_TIME (BSP_TICKS_PER_SEC/5) +// helper function to provide a randomized think time for Philos +inline QP::QTimeEvtCtr think_time() { + return static_cast<QP::QTimeEvtCtr>((BSP_random() % BSP_TICKS_PER_SEC) + + (BSP_TICKS_PER_SEC/2U)); +} - // helper macro to provide the ID of Philo "me_" -#define PHILO_ID(me_) ((uint8_t)((me_) - l_philo)) +// helper function to provide a randomized eat time for Philos +inline QP::QTimeEvtCtr eat_time() { + return static_cast<QP::QTimeEvtCtr>((BSP_random() % BSP_TICKS_PER_SEC) + + BSP_TICKS_PER_SEC); +} -enum InternalSignals { // internal signals +// helper function to provide the ID of Philo "me" +inline uint8_t PHILO_ID(Philo const * const me) { + return static_cast<uint8_t>(me - l_philo); +} + +enum InternalSignals { // internal signals TIMEOUT_SIG = MAX_SIG }; + // Global objects ------------------------------------------------------------ -QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AOs +QP::QActive * const AO_Philo[N_PHILO] = { // "opaque" pointers to Philo AO &l_philo[0], &l_philo[1], &l_philo[2], @@ -67,15 +64,23 @@ &l_philo[4] }; -//............................................................................ -Philo::Philo() - : QActive((QStateHandler)&Philo::initial), - m_timeEvt(TIMEOUT_SIG) -{} -//............................................................................ -QState Philo::initial(Philo *me, QEvent const *) { - static uint8_t registered; // starts off with 0, per C-standard +// Philo definition ---------------------------------------------------------- +// @(/2/0) ................................................................... +// @(/2/0/1) ................................................................. +Philo::Philo() + : QActive(Q_STATE_CAST(&Philo::initial)), + m_timeEvt(TIMEOUT_SIG) +{ +} + +// @(/2/0/2) ................................................................. +// @(/2/0/2/0) +QP::QState Philo::initial(Philo * const me, QP::QEvt const * const e) { + static bool registered = false; // starts off with 0, per C-standard + (void)e; // suppress the compiler warning about unused parameter if (!registered) { + registered = true; + QS_OBJ_DICTIONARY(&l_philo[0]); QS_OBJ_DICTIONARY(&l_philo[0].m_timeEvt); QS_OBJ_DICTIONARY(&l_philo[1]); @@ -91,80 +96,125 @@ QS_FUN_DICTIONARY(&Philo::thinking); QS_FUN_DICTIONARY(&Philo::hungry); QS_FUN_DICTIONARY(&Philo::eating); - - registered = (uint8_t)1; } - QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal for each Philos - QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal for each Philos + QS_SIG_DICTIONARY(HUNGRY_SIG, me); // signal for each Philos + QS_SIG_DICTIONARY(TIMEOUT_SIG, me); // signal for each Philos me->subscribe(EAT_SIG); - return Q_TRAN(&Philo::thinking); } -//............................................................................ -QState Philo::thinking(Philo *me, QEvent const *e) { +// @(/2/0/2/1) ............................................................... +QP::QState Philo::thinking(Philo * const me, QP::QEvt const * const e) { + QP::QState status; switch (e->sig) { + // @(/2/0/2/1) case Q_ENTRY_SIG: { - me->m_timeEvt.postIn(me, THINK_TIME); - return Q_HANDLED(); + me->m_timeEvt.postIn(me, think_time()); + status = Q_HANDLED(); + break; } + // @(/2/0/2/1) + case Q_EXIT_SIG: { + (void)me->m_timeEvt.disarm(); + status = Q_HANDLED(); + break; + } + // @(/2/0/2/1/0) case TIMEOUT_SIG: { - return Q_TRAN(&Philo::hungry); + status = Q_TRAN(&Philo::hungry); + break; } - case EAT_SIG: // intentionally fall-through + // @(/2/0/2/1/1) + case EAT_SIG: // intentionally fall through case DONE_SIG: { - // EAT or DONE must be for other Philos than this one - Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me)); - return Q_HANDLED(); + /* EAT or DONE must be for other Philos than this one */ + Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); + status = Q_HANDLED(); + break; + } + default: { + status = Q_SUPER(&QHsm::top); + break; } } - return Q_SUPER(&QHsm::top); + return status; } -//............................................................................ -QState Philo::hungry(Philo *me, QEvent const *e) { +// @(/2/0/2/2) ............................................................... +QP::QState Philo::hungry(Philo * const me, QP::QEvt const * const e) { + QP::QState status; switch (e->sig) { + // @(/2/0/2/2) case Q_ENTRY_SIG: { TableEvt *pe = Q_NEW(TableEvt, HUNGRY_SIG); pe->philoNum = PHILO_ID(me); AO_Table->POST(pe, me); - return Q_HANDLED(); + status = Q_HANDLED(); + break; } + // @(/2/0/2/2/0) case EAT_SIG: { - if (((TableEvt *)e)->philoNum == PHILO_ID(me)) { - return Q_TRAN(&Philo::eating); + // @(/2/0/2/2/0/0) + if (Q_EVT_CAST(TableEvt)->philoNum == PHILO_ID(me)) { + status = Q_TRAN(&Philo::eating); + } + else { + status = Q_UNHANDLED(); } break; } + // @(/2/0/2/2/1) case DONE_SIG: { - // DONE must be for other Philos than this one - Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me)); - return Q_HANDLED(); + /* DONE must be for other Philos than this one */ + Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); + status = Q_HANDLED(); + break; + } + default: { + status = Q_SUPER(&QHsm::top); + break; } } - return Q_SUPER(&QHsm::top); + return status; } -//............................................................................ -QState Philo::eating(Philo *me, QEvent const *e) { +// @(/2/0/2/3) ............................................................... +QP::QState Philo::eating(Philo * const me, QP::QEvt const * const e) { + QP::QState status; switch (e->sig) { + // @(/2/0/2/3) case Q_ENTRY_SIG: { - me->m_timeEvt.postIn(me, EAT_TIME); - return Q_HANDLED(); + me->m_timeEvt.postIn(me, eat_time()); + status = Q_HANDLED(); + break; } + // @(/2/0/2/3) case Q_EXIT_SIG: { TableEvt *pe = Q_NEW(TableEvt, DONE_SIG); pe->philoNum = PHILO_ID(me); - QF::PUBLISH(pe, me); - return Q_HANDLED(); + QP::QF::PUBLISH(pe, me); + (void)me->m_timeEvt.disarm(); + status = Q_HANDLED(); + break; } + // @(/2/0/2/3/0) case TIMEOUT_SIG: { - return Q_TRAN(&Philo::thinking); + status = Q_TRAN(&Philo::thinking); + break; } - case EAT_SIG: // intentionally fall-through + // @(/2/0/2/3/1) + case EAT_SIG: // intentionally fall through case DONE_SIG: { - // EAT or DONE must be for other Philos than this one - Q_ASSERT(((TableEvt const *)e)->philoNum != PHILO_ID(me)); - return Q_HANDLED(); + /* EAT or DONE must be for other Philos than this one */ + Q_ASSERT(Q_EVT_CAST(TableEvt)->philoNum != PHILO_ID(me)); + status = Q_HANDLED(); + break; + } + default: { + status = Q_SUPER(&QHsm::top); + break; } } - return Q_SUPER(&QHsm::top); + return status; } + + +} // namespace DPP