/****************************************************************************/
/*! Active Object (based on ::QHsm implementation) */
/**
* @description
* Active objects in QP are encapsulated state machines (each embedding an
* event queue and a thread) that communicate with one another asynchronously
* by sending and receiving events. Within an active object, events are
* processed sequentially in a run-to-completion (RTC) fashion, while QF
* encapsulates all the details of thread-safe event exchange and queuing.
* @n@n
* ::QActive represents an active object that uses the QHsm-style
* implementation strategy for state machines. This strategy is tailored
* to manual coding, but it is also supported by the QM modeling tool.
* The resulting code is slower than in the ::QMsm style implementation
* strategy.
*
* @usage
* The following example illustrates how to derive an active object from
* ::QActive. Please note that the ::QActive member @c super is defined as the
* __first__ member of the derived struct (see @ref oop).
* @include qf_qactive.c
*/
typedef struct QActive {
QHsm super; /*!< inherits ::QHsm */
#ifdef QF_EQUEUE_TYPE
/*! OS-dependent event-queue type. */
/**
* @description
* The type of the queue depends on the underlying operating system or
* a kernel. Many kernels support "message queues" that can be adapted
* to deliver QF events to the active object. Alternatively, QF provides
* a native event queue implementation that can be used as well.
*
* @note
* The native QF event queue is configured by defining the macro
* #QF_EQUEUE_TYPE as ::QEQueue.
*/
QF_EQUEUE_TYPE eQueue;
#endif
#ifdef QF_OS_OBJECT_TYPE
/*! OS-dependent per-thread object. */
/**
* @description
* This data might be used in various ways, depending on the QF port.
* In some ports osObject is used to block the calling thread when
* the native QF queue is empty. In other QF ports the OS-dependent
* object might be used differently.
*/
QF_OS_OBJECT_TYPE osObject;
#endif
#ifdef QF_THREAD_TYPE
/*! OS-dependent representation of the thread of the active object. */
/**
* @description
* This data might be used in various ways, depending on the QF port.
* In some ports thread is used to store the thread handle. In other
* ports thread can be the pointer to the Thread-Local-Storage (TLS).
*/
QF_THREAD_TYPE thread;
#endif
/*! QF priority (1..#QF_MAX_ACTIVE) of this active object. */
uint_fast8_t prio;
#ifdef qxk_h /* QXK kernel used? */
/*! QF start priority (1..#QF_MAX_ACTIVE) of this active object. */
uint_fast8_t startPrio;
#endif
} QActive;
里面有一个事件队列EQUEUE
/****************************************************************************/
/*! Native QF Event Queue */
/**
* @description
* This class describes the native QF event queue, which can be used as
* the event queue for active objects, or as a simple "raw" event queue for
* thread-safe event passing among non-framework entities, such as ISRs,
* device drivers, or other third-party components.@n
* @n
* The native QF event queue is configured by defining the macro
* #QF_EQUEUE_TYPE as ::QEQueue in the specific QF port header file.@n
* @n
* The ::QEQueue structure contains only data members for managing an event
* queue, but does not contain the storage for the queue buffer, which must
* be provided externally during the queue initialization.@n
* @n
* The event queue can store only event pointers, not the whole events. The
* internal implementation uses the standard ring-buffer plus one external
* location that optimizes the queue operation for the most frequent case
* of empty queue.@n
* @n
* The ::QEQueue structure is used with two sets of functions. One set is for
* the active object event queue, which might need to block the active object
* task when the event queue is empty and might need to unblock it when
* events are posted to the queue. The interface for the native active object
* event queue consists of the following functions: QActive_post(),
* QActive_postLIFO(), and QActive_get_(). Additionally the function
* QEQueue_init() is used to initialize the queue.@n
* @n
* The other set of functions, uses ::QEQueue as a simple "raw" event
* queue to pass events between entities other than active objects, such as
* ISRs. The "raw" event queue is not capable of blocking on the get()
* operation, but is still thread-safe because it uses QF critical section
* to protect its integrity. The interface for the "raw" thread-safe queue
* consists of the following functions: QEQueue_post(),
* QEQueue_postLIFO(), and QEQueue_get(). Additionally the function
* QEQueue_init() is used to initialize the queue.
*
* @note Most event queue operations (both the active object queues and
* the "raw" queues) internally use the QF critical section. You should be
* careful not to invoke those operations from other critical sections when
* nesting of critical sections is not supported.
*
* @sa ::QEQueue for the description of the data members
*/
typedef struct QEQueue {
/*! pointer to event at the front of the queue. */
/**
* @description
* All incoming and outgoing events pass through the frontEvt location.
* When the queue is empty (which is most of the time), the extra
* frontEvt location allows to bypass the ring buffer altogether,
* greatly optimizing the performance of the queue. Only bursts of events
* engage the ring buffer.
*
* @note The additional role of this attribute is to indicate the empty
* status of the queue. The queue is empty when frontEvt is NULL.
*/
QEvt const * volatile frontEvt;
/*! pointer to the start of the ring buffer. */
QEvt const **ring;
/*! offset of the end of the ring buffer from the start of the buffer. */
QEQueueCtr end;
/*! offset to where next event will be inserted into the buffer. */
QEQueueCtr volatile head;
/*! offset of where next event will be extracted from the buffer. */
QEQueueCtr volatile tail;
/*! number of free events in the ring buffer. */
QEQueueCtr volatile nFree;
/*! minimum number of free events ever in the ring buffer. */
/**
* @description
* this attribute remembers the low-watermark of the ring buffer,
* which provides a valuable information for sizing event queues.
* @sa QF_getQueueMargin().
*/
QEQueueCtr nMin;
} QEQueue;
QEQueue