QP/C++
qf_pspub.cpp
Go to the documentation of this file.
00001 
00002 // Product: QF/C++
00003 // Last Updated for Version: 4.3.00
00004 // Date of the Last Update:  Nov 01, 2011
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2011 Quantum Leaps, LLC. All rights reserved.
00011 //
00012 // This software may be distributed and modified under the terms of the GNU
00013 // General Public License version 2 (GPL) as published by the Free Software
00014 // Foundation and appearing in the file GPL.TXT included in the packaging of
00015 // this file. Please note that GPL Section 2[b] requires that all works based
00016 // on this software must also be made publicly available under the terms of
00017 // the GPL ("Copyleft").
00018 //
00019 // Alternatively, this software may be distributed and modified under the
00020 // terms of Quantum Leaps commercial licenses, which expressly supersede
00021 // the GPL and are specifically designed for licensees interested in
00022 // retaining the proprietary status of their code.
00023 //
00024 // Contact information:
00025 // Quantum Leaps Web site:  http://www.quantum-leaps.com
00026 // e-mail:                  info@quantum-leaps.com
00028 #include "qf_pkg.h"
00029 #include "qassert.h"
00030 
00034 
00035 #ifdef Q_USE_NAMESPACE
00036 namespace QP {
00037 #endif
00038 
00039 Q_DEFINE_THIS_MODULE(qf_pspub)
00040 
00041 //............................................................................
00042 #ifndef Q_SPY
00043 void QF::publish(QEvent const *e) {
00044 #else
00045 void QF::publish(QEvent const *e, void const *sender) {
00046 #endif
00047          // make sure that the published signal is within the configured range
00048     Q_REQUIRE(e->sig < QF_maxSignal_);
00049 
00050     QF_CRIT_STAT_
00051     QF_CRIT_ENTRY_();
00052 
00053     QS_BEGIN_NOCRIT_(QS_QF_PUBLISH, (void *)0, (void *)0)
00054         QS_TIME_();                                           // the timestamp
00055         QS_OBJ_(sender);                                  // the sender object
00056         QS_SIG_(e->sig);                            // the signal of the event
00057         QS_U8_(EVT_POOL_ID(e));                    // the pool Id of the event
00058         QS_U8_(EVT_REF_CTR(e));                  // the ref count of the event
00059     QS_END_NOCRIT_()
00060 
00061     if (EVT_POOL_ID(e) != (uint8_t)0) {              // is it a dynamic event?
00062         EVT_INC_REF_CTR(e);         // increment the reference counter, NOTE01
00063     }
00064     QF_CRIT_EXIT_();
00065 
00066 #if (QF_MAX_ACTIVE <= 8)
00067     uint8_t tmp = QF_subscrList_[e->sig].m_bits[0];
00068     while (tmp != (uint8_t)0) {
00069         uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]);
00070         tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);      // clear the subscriber bit
00071         Q_ASSERT(active_[p] != (QActive *)0);            // must be registered
00072 
00073                            // POST() asserts internally if the queue overflows
00074         active_[p]->POST(e, sender);
00075     }
00076 #else
00077     uint8_t i = Q_DIM(QF_subscrList_[0].m_bits);// number of bytes in the list
00078     do {                       // go through all bytes in the subsciption list
00079         --i;
00080         uint8_t tmp = QF_subscrList_[e->sig].m_bits[i];
00081         while (tmp != (uint8_t)0) {
00082             uint8_t p = Q_ROM_BYTE(QF_log2Lkup[tmp]);
00083             tmp &= Q_ROM_BYTE(QF_invPwr2Lkup[p]);  // clear the subscriber bit
00084             p = (uint8_t)(p + (i << 3));                // adjust the priority
00085             Q_ASSERT(active_[p] != (QActive *)0);        // must be registered
00086 
00087                            // POST() asserts internally if the queue overflows
00088             active_[p]->POST(e, sender);
00089         }
00090     } while (i != (uint8_t)0);
00091 #endif
00092 
00093     gc(e);                            // run the garbage collector, see NOTE01
00094 }
00095 
00096 #ifdef Q_USE_NAMESPACE
00097 }                                                              // namespace QP
00098 #endif
00099 
00101 // NOTE01:
00102 // QF::publish() increments the reference counter to prevent premature
00103 // recycling of the event while the multicasting is still in progress.
00104 // At the end of the function, the garbage collector step decrements the
00105 // reference counter and recycles the event if the counter drops to zero.
00106 // This covers the case when the event was published without any subscribers.
00107 //