예제 #1
0
파일: qa_defer.c 프로젝트: voileravi/zen
/*..........................................................................*/
uint8_t QActive_recall(QActive *me, QEQueue *eq) {
    QEvent const *e = QEQueue_get(eq);  /* get an event from deferred queue */
    uint8_t recalled;
    if (e != (QEvent const *)0) {                       /* event available? */
        QF_CRIT_STAT_

        QActive_postLIFO(me, e);  /* post it to the front of the AO's queue */

        QF_CRIT_ENTRY_();

        if (QF_EVT_POOL_ID_(e) != (uint8_t)0) {   /* is it a dynamic event? */

            /* after posting to the AO's queue the event must be referenced
            * at least twice: once in the deferred event queue (eq->get()
            * did NOT decrement the reference counter) and once in the
            * AO's event queue.
            */
            Q_ASSERT(QF_EVT_REF_CTR_(e) > (uint8_t)1);

            /* we need to decrement the reference counter once, to account
            * for removing the event from the deferred event queue.
            */
            QF_EVT_REF_CTR_DEC_(e);      /* decrement the reference counter */
        }

        QF_CRIT_EXIT_();
        recalled = (uint8_t)1;
    }
    else {
        recalled = (uint8_t)0;
    }
    return recalled;
}
예제 #2
0
파일: qf_dyn.cpp 프로젝트: dongkc/purifier
//****************************************************************************
/// @description
/// This function implements a simple garbage collector for dynamic events.
/// Only dynamic events are candidates for recycling. (A dynamic event is one
/// that is allocated from an event pool, which is determined as non-zero
/// e->poolId_ attribute.) Next, the function decrements the reference counter
/// of the event (e->refCtr_), and recycles the event only if the counter
/// drops to zero (meaning that no more references are outstanding for this
/// event). The dynamic event is recycled by returning it to the pool from
/// which it was originally allocated.
///
/// @param[in]  e  pointer to the event to recycle
///
/// @note
/// QF invokes the garbage collector at all appropriate contexts, when
/// an event can become garbage (automatic garbage collection), so the
/// application code should have no need to call QP::QF::gc() directly.
/// The QP::QF::gc() function is exposed only for special cases when your
/// application sends dynamic events to the "raw" thread-safe queues
/// (see QP::QEQueue). Such queues are processed outside of QF and the
/// automatic garbage collection is **NOT** performed for these events.
/// In this case you need to call QP::QF::gc() explicitly.
///
void QF::gc(QEvt const * const e) {
    // is it a dynamic event?
    if (QF_EVT_POOL_ID_(e) != static_cast<uint8_t>(0)) {
        QF_CRIT_STAT_
        QF_CRIT_ENTRY_();

        // isn't this the last reference?
        if (e->refCtr_ > static_cast<uint8_t>(1)) {
            QF_EVT_REF_CTR_DEC_(e); // decrement the ref counter

            QS_BEGIN_NOCRIT_(QS_QF_GC_ATTEMPT,
                static_cast<void *>(0), static_cast<void *>(0))
                QS_TIME_();        // timestamp
                QS_SIG_(e->sig);   // the signal of the event
                QS_2U8_(e->poolId_, e->refCtr_);// pool Id & refCtr of the evt
            QS_END_NOCRIT_()

            QF_CRIT_EXIT_();
        }
        // this is the last reference to this event, recycle it
        else {
            uint_fast8_t idx = static_cast<uint_fast8_t>(e->poolId_)
                               - static_cast<uint_fast8_t>(1);

            QS_BEGIN_NOCRIT_(QS_QF_GC,
                static_cast<void *>(0), static_cast<void *>(0))
                QS_TIME_();        // timestamp
                QS_SIG_(e->sig);   // the signal of the event
                QS_2U8_(e->poolId_, e->refCtr_);// pool Id & refCtr of the evt
            QS_END_NOCRIT_()

            QF_CRIT_EXIT_();

            // pool ID must be in range
            Q_ASSERT_ID(410, idx < QF_maxPool_);

#ifdef Q_EVT_VIRTUAL
            // explicitly exectute the destructor'
            // NOTE: casting 'const' away is legitimate,
            // because it's a pool event
            QF_EVT_CONST_CAST_(e)->~QEvt(); // xtor,
#endif
            // cast 'const' away, which is OK, because it's a pool event
            QF_EPOOL_PUT_(QF_pool_[idx], QF_EVT_CONST_CAST_(e));
        }
    }
}
예제 #3
0
파일: qf_gc.cpp 프로젝트: dongkc/rtu_drv
//............................................................................
void QF::gc(QEvt const * const e) {
    if (QF_EVT_POOL_ID_(e) != u8_0) {                // is it a dynamic event?
        QF_CRIT_STAT_
        QF_CRIT_ENTRY_();

        if (QF_EVT_REF_CTR_(e) > u8_1) {     // isn't this the last reference?
            QF_EVT_REF_CTR_DEC_(e);               // decrement the ref counter

            QS_BEGIN_NOCRIT_(QS_QF_GC_ATTEMPT, null_void, null_void)
                QS_TIME_();                                       // timestamp
                QS_SIG_(e->sig);                    // the signal of the event
                QS_U8_(QF_EVT_POOL_ID_(e));        // the pool Id of the event
                QS_U8_(QF_EVT_REF_CTR_(e));      // the ref count of the event
            QS_END_NOCRIT_()

            QF_CRIT_EXIT_();
        }
        else {         // this is the last reference to this event, recycle it
            uint8_t idx = static_cast<uint8_t>(QF_EVT_POOL_ID_(e) - u8_1);

            QS_BEGIN_NOCRIT_(QS_QF_GC, null_void, null_void)
                QS_TIME_();                                       // timestamp
                QS_SIG_(e->sig);                    // the signal of the event
                QS_U8_(QF_EVT_POOL_ID_(e));        // the pool Id of the event
                QS_U8_(QF_EVT_REF_CTR_(e));      // the ref count of the event
            QS_END_NOCRIT_()

            QF_CRIT_EXIT_();

            Q_ASSERT(idx < QF_maxPool_);

#ifdef Q_EVT_VIRTUAL
            QF_EVT_CONST_CAST_(e)->~QEvt();        // xtor, cast 'const' away,
                             // which is legitimate, because it's a pool event
#endif
                  // cast 'const' away, which is OK, because it's a pool event
            QF_EPOOL_PUT_(QF_pool_[idx], QF_EVT_CONST_CAST_(e));
        }
    }
}
void QF_tick(void const * const sender)
#endif
{
    QTimeEvt *t;
    QTimeEvt *prev = (QTimeEvt *)0;
    QF_CRIT_STAT_

    QF_CRIT_ENTRY_();

    QS_BEGIN_NOCRIT_(QS_QF_TICK, (void *)0, (void *)0)
        QS_TEC_((QTimeEvtCtr)(++QS_tickCtr_));          /* the tick counter */
    QS_END_NOCRIT_()

    for (t = QF_timeEvtListHead_; t != (QTimeEvt *)0; t = t->next) {
        if (t->ctr == (QTimeEvtCtr)0) { /* time evt. scheduled for removal? */
            if (t == QF_timeEvtListHead_) {
                QF_timeEvtListHead_ = t->next;
            }
            else {
                Q_ASSERT(prev != (QTimeEvt *)0);
                prev->next = t->next;
            }
            QF_EVT_REF_CTR_DEC_(&t->super);           /* mark as not linked */
        }
        else {
            --t->ctr;
            if (t->ctr == (QTimeEvtCtr)0) { /* is time evt about to expire? */
                if (t->interval != (QTimeEvtCtr)0) {  /* periodic time evt? */
                    t->ctr = t->interval;           /* rearm the time event */
                }
                else {
                    QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_AUTO_DISARM, QS_teObj_, t)
                        QS_OBJ_(t);               /* this time event object */
                        QS_OBJ_(t->act);               /* the active object */
                    QS_END_NOCRIT_()
                }

                QS_BEGIN_NOCRIT_(QS_QF_TIMEEVT_POST, QS_teObj_, t)
                    QS_TIME_();                                /* timestamp */
                    QS_OBJ_(t);                    /* the time event object */
                    QS_SIG_(t->super.sig);     /* signal of this time event */
                    QS_OBJ_(t->act);                   /* the active object */
                QS_END_NOCRIT_()

                QF_CRIT_EXIT_();       /* exit crit. section before posting */
                /* QACTIVE_POST() asserts internally if the queue overflows */
                QACTIVE_POST(t->act, &t->super, sender);
                QF_CRIT_ENTRY_();     /* re-enter crit. section to continue */

                if (t->ctr == (QTimeEvtCtr)0) {  /* still marked to expire? */
                    if (t == QF_timeEvtListHead_) {
                        QF_timeEvtListHead_ = t->next;
                    }
                    else {
                        Q_ASSERT(prev != (QTimeEvt *)0);
                        prev->next = t->next;
                    }
                    QF_EVT_REF_CTR_DEC_(&t->super);      /* mark as removed */
                }
                else {
                    prev = t;
                }
            }
            else {
                prev = t;
            }
        }
    }