Menu

defer/recall without assert with full queue

2015-06-25
2015-06-26
  • Rémi Desgrange

    Rémi Desgrange - 2015-06-25

    Hi,

    I'm using defer/recall concept, and it's really not critical if recall cannot be done because queue of the machine is full. Here is the code I use.

    Busy state of a potential sm

    QP::QState MySm::Busy(MySm * const me, QP::QEvt const * const e) {
        QP::QState status_;
        switch (e->sig) {
            // ${AO::MySm::SM::Busy::TIMEOUT}
            case TIMEOUT_SIG: {
                // ${AO::MySm::SM::Busy::TIMEOUT::[me->m_counter==~}
                if (me->m_counter == 10) {
                    static struct {
                        QP::QMState const *target;
                        QP::QActionHandler act[3];
                    } const tatbl_ = { // transition-action table
                        &Execute_s,
                        {
                            Q_ACTION_CAST(&Busy_x), // exit
                            Q_ACTION_CAST(&Execute_e), // entry
                            Q_ACTION_CAST(0)  // zero terminator
                        }
                    };
                    me->m_counter = 0;
                    me->m_timeEvt.disarm();
                    status_ = QM_TRAN(&tatbl_);
                }
                // ${AO::MySm::SM::Busy::TIMEOUT::[else]}
                else {
                    if(me->m_deferedEvt.getNFree() > 0)
                    {
                        me->defer(&me->m_deferedEvt, e);
                    } else {
                        cout << "cannot defer" << endl;
                    }
                    me->m_counter++;
                    status_ = QM_HANDLED();
                }
                break;
            }
            default: {
                status_ = QM_SUPER();
                break;
            }
        }
        return status_;
    }
    

    And the state that recall event, maybe the while is not the best way..

    // ${AO::MySm::SM::Execute}
    QP::QState MySm::Execute_e(MySm* const me) {
        cout << "Entry " << __FUNCTION__ << endl;
    
        while(me->recall(&me->m_deferedEvt))
        {
            cout << "Evt to recall" << endl;
            cout << "getNFree : "  << me->m_deferedEvt.getNFree() << endl;
        }
        return QM_ENTRY(&Execute_s);
    }
    

    I repeat that my interest here is to not assert when the queue storage of the machine (not the qequeue) is full.

     

    Last edit: Rémi Desgrange 2015-06-25
  • Quantum Leaps

    Quantum Leaps - 2015-06-25

    In the newer QP/C++, the QMActive::defer() operation does not assert. Instead it returns a bool (true if the event could be deferred and false otherwise). Please see the doxygen documentation at:

    http://www.state-machine.com/qpcpp/class_q_p_1_1_q_m_active.html#a46fbfef403b1ee47ae4b30c709fb4021

    So, you no longer need to test the deferred-queue.

    As to the while loop while recalling events in the entry action, I don't get it and it makes little sense to me. It seems to me that you just flood your primary queue with all the recalled events, which you then defer again.

    --MMS

     
  • Rémi Desgrange

    Rémi Desgrange - 2015-06-26

    The problem is not the size of the deferred queue, it's the size of the SM queue storage.

    the SM schema is attached

    I'll give you a quick example:
    let's imagine a machine that send SMS.
    This machine will have 3 states :
    -Wait
    -SmsRx
    -SmsTx
    And 2 signal :
    -SMS_SEND_SIG : ask the machine to send a sms, the text, phone number are passed in the events
    -SMS_RECEIVE_SIG : tell the machine that a sms has been received.

    The initial state is, obviously the "Wait" state. On SMS_RECEIVE_SIG, the machine will transit to "SmsRx" where it will parse and treat the SMS. If, in this state I receive a "SMS_SEND_SIG", I don't want to loose the sms, so I defer the event and I will recall it in "Wait" state. The solution that you give the Psicc for this pattern works if I receive 1 "SMS_SEND_SIG" in the "SmsRx" state. It doesn"t work if I receive multiple signal.

    But maybe I misunderstood the concept of defer/recall ?

     

    Last edit: Rémi Desgrange 2015-06-26
  • Quantum Leaps

    Quantum Leaps - 2015-06-26

    The queue size of the active object (AO) is an issue only if you flood it with events. That's why I questioned your recalling all events at once in a tight while loop. This is a departure from the "Deferred Event" pattern, because events should be recalled one at a time.

    I still don't understand your case for recalling all events at once. Perhaps you could elaborate why it is necessary and what it is that you are trying to achieve here.

    --MMS

     

    Last edit: Quantum Leaps 2015-06-26
  • Rémi Desgrange

    Rémi Desgrange - 2015-06-26

    I did see your post, I edit my response

    Here is the schema

     

Log in to post a comment.