⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qf.cpp

📁 本程序将ucosii移入了QF框架
💻 CPP
字号:
/////////////////////////////////////////////////////////////////////
// Quantum Event Quantum Framewrok implemenatation
// Copyright (c) 2002 Miro Samek, Palo Alto, CA. 
// All Rights Reserved.
/////////////////////////////////////////////////////////////////////
#include "qassert.h"
#include "port.h"

DEFINE_THIS_FILE;

QActive *pkgActive[QF_MAX_ACTIVE];
QEvent const pkgStdEvt[] = {
   { Q_EMPTY_SIG, 0, 0 },
   { Q_INIT_SIG,  0, 0 },
   { Q_ENTRY_SIG, 0, 0 },
   { Q_EXIT_SIG,  0, 0 }
};

static QSubscrList *locSubscrList;
static unsigned locMaxSignal;

enum { MAX_POOL = 3 };
static QF_EPOOL locPool[MAX_POOL];   // allocate MAX_POOL event pools

            // The pool pointers keep track of pools actually used.
            // The first and last poolPtr are not used (must be 0),
            // which is guaranteed by static initialization in C/C++.
static QF_EPOOL *locPoolPtr[1 + MAX_POOL + 1];

//...................................................................
void QF::init(QSubscrList subscr[], unsigned maxSignal) {
   locSubscrList = subscr;
   locMaxSignal = maxSignal;
   osInit();
}
//...................................................................
void QF::cleanup() {
   osCleanup();
}
//...................................................................
void QF::tick() {  
   register QTimer *t, *tp;
   QF_ISR_PROTECT();
   for (t = tp = pkgTimerListHead; t; t = t->myNext) {
      if (--t->myCtr == 0) {
                                             // queue cannot overflow
         ALLEGE(t->myActive->enqueue(&t->myToutEvt));
         if (t->myInterval) {                      // periodic timer?
            t->myCtr = t->myInterval;              // rearm the timer
            tp = t;
         }
         else {   // one-shot timer, disarm by removing from the list
            if (t == pkgTimerListHead) {
               pkgTimerListHead = tp = t->myNext;              
            }
            else {
               tp->myNext = t->myNext;
            }
            t->myActive = 0;            // mark the timer free to use
         }
      }
      else {
         tp = t;
      }
   }            
   QF_ISR_UNPROTECT();
}
//...................................................................
void QF::poolInit(QEvent *poolSto, 
                  unsigned nEvts, unsigned evtSize)
{
   static unsigned poolId = 0;
   REQUIRE(poolId < MAX_POOL);        // cannot exceed the # of pools
      // please initialize event pools in ascending order of evtSize:
   REQUIRE(poolId == 0 || locPoolPtr[poolId]->myEvtSize < evtSize);
   QF_EPOOL_INIT(&locPool[poolId], poolSto, nEvts, evtSize);
   locPoolPtr[poolId + 1] = &locPool[poolId];//add *initialized* pool
   ++poolId;                 // one more pool; (poolId of 0 not used)
}
//...................................................................
QEvent *QF::create(unsigned evtSize, QSignal sig) {
   register unsigned id;
   register QEPool *p;
   for (id = 1, p = locPoolPtr[1]; p; p = locPoolPtr[++id]) {
      if (evtSize <= p->myEvtSize) { //will evtSize fit in this pool?
         QEvent *e;
         QF_EPOOL_GET(p, e);
         ASSERT(e);            // the pool must not run out of events
         e->poolId = id;       // to know where to recycle this event
         e->sig = sig;                   // set signal for this event
         e->useNum = 0;            // this event is new, not used yet
         return e;
      } 
   }
   ASSERT(0);         // event too big to fit in any initialized pool
   return 0;  // should never be reached, just to avoid compiler fuss
}
//...................................................................
void QF::annihilate(QEvent *e) {
   if (e->poolId) {                            // is it a pool event?
      ASSERT(e->poolId <= MAX_POOL && locPoolPtr[e->poolId]);
      QF_EPOOL_PUT(locPoolPtr[e->poolId], e);
   }
   else {                                 // this is not a pool event
      e->useNum = 0;  // recycle event by clearing the number of uses
   }
}
//...................................................................
void QF::add(QActive *a) {
   REQUIRE(a->myPrio < QF_MAX_ACTIVE && pkgActive[a->myPrio] == 0);
   pkgActive[a->myPrio] = a;
}
//...................................................................
void QF::remove(QActive *a) {
   register QSignal sig;
   for (sig = Q_USER_SIG; sig < locMaxSignal; ++sig) {
       QF::unsubscribe(a, sig);
   }
   pkgActive[a->myPrio] = 0;            // free-up the priority level
}
//...................................................................
void QF::subscribe(QActive *a, QSignal sig) {
   register unsigned char p = a->myPrio; // priority of active object
   REQUIRE(Q_USER_SIG <= sig && sig < locMaxSignal &&
           p < QF_MAX_ACTIVE && pkgActive[p] == a);
   QF_PROTECT();
   register QSubscrList sl = *(locSubscrList + sig);
   ASSERT((sl & 0xF0000000) == 0); //must have at least one free slot
   for (register int n = 0; n < 32; n += 4) {   // find priority slot
      if (p > ((sl >> n) & 0xF)) {
          sl =  (sl & ~(~0 << n)) |
                (p << n) |
                ((sl << 4) & (~0 << (n + 4))); 
          *(locSubscrList + sig) = sl;
          break;      // subscriber registered (attached to the list)
      }
   }
   QF_UNPROTECT();
}
//...................................................................
void QF::unsubscribe(QActive *a, QSignal sig) {
   REQUIRE(Q_USER_SIG <= sig && sig < locMaxSignal);
   register unsigned char p = a->myPrio; // priority of active object
   QF_PROTECT();
   register QSubscrList sl = *(locSubscrList + sig);
   for (register int n = 0; n < 32; n += 4) {   // find priority slot
      if (p == ((sl >> n) & 0xF)) {
          sl =  (sl & ~(~0 << n)) | ((sl >> 4) & (~0 << n)); 
          *(locSubscrList + sig) = sl;
          break;     // subscription canceled (removed from the list)
      }
   }
   QF_UNPROTECT();
}
//...................................................................
void QF::publish(QEvent *e) {
   REQUIRE(e->sig < locMaxSignal &&
           e->useNum == 0);           // do not publish event in use!
   register QSubscrList sl = *(locSubscrList + e->sig);
   if (sl) {                                      // any subscribers?
      register unsigned char p = (unsigned char)(sl & 0xF);
      e->useNum = 1;                                 // the first use
      ASSERT(pkgActive[p]);     // active object must have subscribed
      ALLEGE(pkgActive[p]->enqueue(e));      // queue cannot overflow
   }
   else {                                           // no subscribers
      QF::annihilate(e);                     // do not leak the event
   }
}
//...................................................................
void QF::propagate(QEvent *e) {
   if (e->useNum > 0) {            // should QF propagate this event?
      ASSERT(e->sig < locMaxSignal);                   // range check
      register QSubscrList sl = locSubscrList[e->sig];
      sl >>= (e->useNum*4); // shift out already serviced subscribers
      if (sl) {                        // more subscribers available?
         register unsigned char p = (unsigned char)(sl & 0xF);
         ++e->useNum;                                     // next use
         ASSERT(pkgActive[p]);     // active object must have started
         ALLEGE(pkgActive[p]->enqueue(e));   // queue cannot overflow
         return;                                  // event propagated
      }
   }
   QF::annihilate(e);         // event not propagated; don't leak it!
}
/////////////////////////////////////////////////////////////////////
// NOTE01:
// NOTE02:
//

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -