Linux Face / QPFramework
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers qequeue.h Source File

qequeue.h

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////////
00002 // Product: QF/C++, platform-independent event queue interface.
00003 // Last Updated for Version: 4.0.00
00004 // Date of the Last Update:  Apr 06, 2008
00005 //
00006 //                    Q u a n t u m     L e a P s
00007 //                    ---------------------------
00008 //                    innovating embedded systems
00009 //
00010 // Copyright (C) 2002-2008 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
00027 //////////////////////////////////////////////////////////////////////////////
00028 #ifndef qequeue_h
00029 #define qequeue_h
00030 
00031 /// \file
00032 /// \ingroup qep qf qk qs
00033 /// \brief platform-independent event queue interface.
00034 ///
00035 /// This header file must be included in all QF ports that use native QF
00036 /// event queue implementation. Also, this file is needed when the "raw"
00037 /// thread-safe queues are used for communication between active objects
00038 /// and non-framework entities, such as ISRs, device drivers, or legacy
00039 /// code.
00040 
00041 #ifndef QF_EQUEUE_CTR_SIZE
00042 
00043     /// \brief The size (in bytes) of the ring-buffer counters used in the
00044     /// native QF event queue implementation. Valid values: 1, 2, or 4;
00045     /// default 1.
00046     ///
00047     /// This macro can be defined in the QF port file (qf_port.h) to
00048     /// configure the ::QEQueueCtr type. Here the macro is not defined so the
00049     /// default of 1 byte is chosen.
00050     #define QF_EQUEUE_CTR_SIZE 1
00051 #endif
00052 #if (QF_EQUEUE_CTR_SIZE == 1)
00053 
00054     /// \brief The data type to store the ring-buffer counters based on
00055     /// the macro #QF_EQUEUE_CTR_SIZE.
00056     ///
00057     /// The dynamic range of this data type determines the maximum length
00058     /// of the ring buffer managed by the native QF event queue.
00059     typedef uint8_t QEQueueCtr;
00060 #elif (QF_EQUEUE_CTR_SIZE == 2)
00061     typedef uint16_t QEQueueCtr;
00062 #elif (QF_EQUEUE_CTR_SIZE == 4)
00063     typedef uint32_t QEQueueCtr;
00064 #else
00065     #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1, 2, or 4"
00066 #endif
00067 
00068 
00069 //////////////////////////////////////////////////////////////////////////////
00070 /// \brief Native QF Event Queue class
00071 ///
00072 /// This structure describes the native QF event queue, which can be used as
00073 /// the event queue for active objects, or as a simple "raw" event queue for
00074 /// thread-safe event passing among non-framework entities, such as ISRs,
00075 /// device drivers, or other third-party components.
00076 ///
00077 /// The native QF event queue is configured by defining the macro
00078 /// #QF_EQUEUE_TYPE as ::QEQueue in the specific QF port header file.
00079 ///
00080 /// The ::QEQueue structure contains only data members for managing an event
00081 /// queue, but does not contain the storage for the queue buffer, which must
00082 /// be provided externally during the queue initialization.
00083 ///
00084 /// The event queue can store only event pointers, not the whole events. The
00085 /// internal implementation uses the standard ring-buffer plus one external
00086 /// location that optimizes the queue operation for the most frequent case
00087 /// of empty queue.
00088 ///
00089 /// The ::QEQueue structure is used with two sets of functions. One set is for
00090 /// the active object event queue, which needs to block the active object
00091 /// task when the event queue is empty and unblock it when events are posted
00092 /// to the queue. The interface for the native active object event queue
00093 /// consists of the following functions: QActive::postFIFO_(),
00094 /// QActive::postLIFO_(), and QActive::get_(). Additionally the function
00095 /// QEQueue_init() is used to initialize the queue.
00096 ///
00097 /// The other set of functions, uses this structure as a simple "raw" event
00098 /// queue to pass events between entities other than active objects, such as
00099 /// ISRs. The "raw" event queue is not capable of blocking on the get()
00100 /// operation, but is still thread-safe because it uses QF critical section
00101 /// to protect its integrity. The interface for the "raw" thread-safe queue
00102 /// consists of the following functions: QEQueue::postFIFO(),
00103 /// QEQueue::postLIFO(), and QEQueue::get(). Additionally the function
00104 /// QEQueue::init() is used to initialize the queue.
00105 ///
00106 /// \note Most event queue operations (both the active object queues and
00107 /// the "raw" queues) internally use  the QF critical section. You should be
00108 /// careful not to invoke those operations from other critical sections when
00109 /// nesting of critical sections is not supported.
00110 class QEQueue {
00111 private:
00112 
00113     /// \brief pointer to event at the front of the queue
00114     ///
00115     /// All incoming and outgoing events pass through the m_frontEvt location.
00116     /// When the queue is empty (which is most of the time), the extra
00117     /// m_frontEvt location allows to bypass the ring buffer altogether,
00118     /// greatly optimizing the performance of the queue. Only bursts of events
00119     /// engage the ring buffer.
00120     ///
00121     /// The additional role of this attribute is to indicate the empty status
00122     /// of the queue. The queue is empty if the m_frontEvt location is NULL.
00123     QEvent const *m_frontEvt;
00124 
00125     /// \brief pointer to the start of the ring buffer
00126     QEvent const **m_ring;
00127 
00128     /// \brief offset of the end of the ring buffer from the start of the
00129     /// buffer m_ring
00130     QEQueueCtr m_end;
00131 
00132     /// \brief offset to where next event will be inserted into the buffer
00133     QEQueueCtr m_head;
00134 
00135     /// \brief offset of where next event will be extracted from the buffer
00136     QEQueueCtr m_tail;
00137 
00138     /// \brief number of free events in the ring buffer
00139     QEQueueCtr m_nFree;
00140 
00141     /// \brief minimum number of free events ever in the ring buffer.
00142     ///
00143     /// \note this attribute remembers the low-watermark of the ring buffer,
00144     /// which provides a valuable information for sizing event queues.
00145     /// \sa QF::getQueueMargin().
00146     QEQueueCtr m_nMin;
00147 
00148 public:
00149 
00150     /// \brief Initializes the native QF event queue
00151     ///
00152     /// The parameters are as follows: \a qSto[] is the ring buffer storage,
00153     /// \a qLen is the length of the ring buffer in the units of event-
00154     /// pointers.
00155     ///
00156     /// \note The actual capacity of the queue is qLen + 1, because of the
00157     /// extra location fornEvt_.
00158     void init(QEvent const *qSto[], QEQueueCtr qLen);
00159 
00160     /// \brief "raw" thread-safe QF event queue implementation for the
00161     /// First-In-First-Out (FIFO) event posting. You can call this function
00162     /// from any task context or ISR context. Please note that this function
00163     /// uses internally a critical section.
00164     ///
00165     /// \note The function raises an assertion if the native QF queue becomes
00166     /// full and cannot accept the event.
00167     ///
00168     /// \sa QEQueue::postLIFO(), QEQueue::get()
00169     void postFIFO(QEvent const *e);
00170 
00171     /// \brief "raw" thread-safe QF event queue implementation for the
00172     /// First-In-First-Out (FIFO) event posting. You can call this function
00173     /// from any task context or ISR context. Please note that this function
00174     ///  uses internally a critical section.
00175     ///
00176     /// \note The function raises an assertion if the native QF queue becomes
00177     /// full and cannot accept the event.
00178     ///
00179     /// \sa QEQueue::postLIFO(), QEQueue::get()
00180     void postLIFO(QEvent const *e);
00181 
00182     /// \brief "raw" thread-safe QF event queue implementation for the
00183     /// Last-In-First-Out (LIFO) event posting.
00184     ///
00185     /// \note The LIFO policy should be used only with great caution because
00186     /// it alters order of events in the queue.
00187     /// \note The function raises an assertion if the native QF queue becomes
00188     /// full and cannot accept the event. You can call this function from
00189     /// any task context or ISR context. Please note that this function uses
00190     /// internally a critical section.
00191     ///
00192     /// \sa QEQueue::postFIFO(), QEQueue::get()
00193     QEvent const *get(void);
00194 
00195     /// \brief "raw" thread-safe QF event queue operation for
00196     /// obtaining the number of free entries still available in the queue.
00197     ///
00198     /// \note This operation needs to be used with caution because the
00199     /// number of free entries can change unexpectedly. The main intent for
00200     /// using this operation is in conjunction with event deferral. In this
00201     /// case the queue is accessed only from a single thread (by a single AO),
00202     /// so the number of free entries cannot change unexpectedly.
00203     ///
00204     /// \sa QActive::defer(), QActive::recall()
00205     QEQueueCtr getNFree(void) const {
00206         return m_nFree;
00207     }
00208 
00209 private:
00210     friend class QF;
00211     friend class QActive;
00212 };
00213 
00214 #endif                                                            // qequeue_h
00215