/*$file${include::qequeue.h} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /* * Model: qpc.qm * File: ${include::qequeue.h} * * This code has been generated by QM 5.2.4 . * DO NOT EDIT THIS FILE MANUALLY. All your changes will be lost. * * This code is covered by the following QP license: * License # : LicenseRef-QL-dual * Issued to : Any user of the QP/C real-time embedded framework * Framework(s) : qpc * Support ends : 2023-12-31 * License scope: * * Copyright (C) 2005 Quantum Leaps, LLC . * * SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-QL-commercial * * This software is dual-licensed under the terms of the open source GNU * General Public License version 3 (or any later version), or alternatively, * under the terms of one of the closed source Quantum Leaps commercial * licenses. * * The terms of the open source GNU General Public License version 3 * can be found at: * * The terms of the closed source Quantum Leaps commercial licenses * can be found at: * * Redistributions in source code must retain this top-level comment block. * Plagiarizing this software to sidestep the license obligations is illegal. * * Contact information: * * */ /*$endhead${include::qequeue.h} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ /*! @file * @brief QP natvie, platform-independent, thread-safe event queue interface * @details * This header file must be included in all QF ports that use native QF * event queue for active objects. Also, this file needs to be included * in the QP/C library when the application uses QActive_defer()/ * QActive_recall(). Finally, this file is also needed when the "raw" * thread-safe queues are used for communication between active objects * and non-framework entities, such as ISRs, device drivers, or legacy * code. */ #ifndef QP_INC_QEQUEUE_H_ #define QP_INC_QEQUEUE_H_ #ifndef QF_EQUEUE_CTR_SIZE /*! The size [bytes] of the ring-buffer counters used in the * native QF event queue implementation. Valid values: 1U, 2U, or 4U; * default 1U. * @details * This macro can be defined in the QF port file (qf_port.h) to * configure the ::QEQueueCtr type. Here the macro is not defined so the * default of 1 byte is chosen. */ #define QF_EQUEUE_CTR_SIZE 1U #endif #if (QF_EQUEUE_CTR_SIZE == 1U) /*! The data type to store the ring-buffer counters based on * the macro #QF_EQUEUE_CTR_SIZE. * @details * The dynamic range of this data type determines the maximum length * of the ring buffer managed by the native QF event queue. */ typedef uint8_t QEQueueCtr; #elif (QF_EQUEUE_CTR_SIZE == 2U) typedef uint16_t QEQueueCtr; #elif (QF_EQUEUE_CTR_SIZE == 4U) typedef uint32_t QEQueueCtr; #else #error "QF_EQUEUE_CTR_SIZE defined incorrectly, expected 1U, 2U, or 4U" #endif /*==========================================================================*/ /*$declare${QF::QEQueue} vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/ /*${QF::QEQueue} ...........................................................*/ /*! @brief Native QF Event Queue * @class QEQueue * * @details * 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.
* * The native QF event queue is configured by defining the macro * #QF_EQUEUE_TYPE as ::QEQueue in the specific QF port header file.
*
* 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.
*
* 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.
*
* 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.
*
* 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. * *
ote 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 { /* private: */ /*! pointer to event at the front of the queue. * @private @memberof QEQueue * * @details * 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. * *
ote 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 * @private @memberof QEQueue */ QEvt const ** ring; /*! offset of the end of the ring buffer from the start of the buffer * @private @memberof QEQueue */ QEQueueCtr end; /*! offset to where next event will be inserted into the buffer * @private @memberof QEQueue */ QEQueueCtr volatile head; /*! offset of where next event will be extracted from the buffer * @private @memberof QEQueue */ QEQueueCtr volatile tail; /*! number of free events in the ring buffer * @private @memberof QEQueue */ QEQueueCtr volatile nFree; /*! Minimum number of free events ever in the ring buffer. * @private @memberof QEQueue * * @details * 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; /* public: */ /*! Initialize the native QF event queue. * @public @memberof QEQueue * * @details * Initialize the event queue by giving it the storage for the ring buffer. * * @param[in,out] me current instance pointer (see @ref oop) * @param[in] qSto an array of pointers to ::QEvt to sereve as the * ring buffer for the event queue * @param[in] qLen the length of the `qSto` buffer (in ::QEvt pointers) * * @note The actual capacity of the queue is qLen + 1, because of the extra * location forntEvt. * * @note * This function is also used to initialize the event queues of active * objects in the built-int QV and QK kernels, as well as other * QP ports to OSes/RTOSes that do provide a suitable message queue. */ void QEQueue_init(QEQueue * const me, QEvt const ** const qSto, uint_fast16_t const qLen); /*! Post an event to the "raw" thread-safe event queue (FIFO). * @public @memberof QEQueue * * @details * Post an event to the "raw" thread-safe event queue using the * First-In-First-Out (FIFO) order. * * @param[in,out] me current instance pointer (see @ref oop) * @param[in] e pointer to the event to be posted to the queue * @param[in] margin number of required free slots in the queue after * posting the event. The special value #QF_NO_MARGIN * means that this function will assert if posting * @note * The #QF_NO_MARGIN value of the `margin` parameter is special and * denotes situation when the post() operation is assumed to succeed (event * delivery guarantee). An assertion fires, when the event cannot be * delivered in this case. * * @returns 'true' (success) when the posting succeeded with the provided * margin and 'false' (failure) when the posting fails. * * @note This function can be called from any task context or ISR context. * * @sa QEQueue_postLIFO(), QEQueue_get() */ bool QEQueue_post(QEQueue * const me, QEvt const * const e, uint_fast16_t const margin, uint_fast8_t const qs_id); /*! Post an event to the "raw" thread-safe event queue (LIFO). * @public @memberof QEQueue * * @details * Post an event to the "raw" thread-safe event queue using the * Last-In-First-Out (LIFO) order. * * @param[in,out] me current instance pointer (see @ref oop) * @param[in] e pointer to the event to be posted to the queue * * @attention * The LIFO policy should be used only with great __caution__, because * it alters the order of events in the queue. * * @note * This function can be called from any task context or ISR context. * * @note * this function is used for the "raw" thread-safe queues and __not__ * for the queues of active objects. * * @sa * QEQueue_post(), QEQueue_get(), QActive_defer() */ void QEQueue_postLIFO(QEQueue * const me, QEvt const * const e, uint_fast8_t const qs_id); /*! Obtain an event from the "raw" thread-safe queue. * @public @memberof QEQueue * * @details * Retrieves an event from the front of the "raw" thread-safe queue and * returns a pointer to this event to the caller. * * @param[in,out] me current instance pointer (see @ref oop) * * @returns * pointer to event at the front of the queue, if the queue is * not empty and NULL if the queue is empty. * * @note * this function is used for the "raw" thread-safe queues and __not__ * for the queues of active objects. * * @sa * QEQueue_post(), QEQueue_postLIFO(), QActive_recall() */ QEvt const * QEQueue_get(QEQueue * const me, uint_fast8_t const qs_id); /*! "raw" thread-safe QF event queue operation for obtaining the number * of free entries still available in the queue. * @public @memberof QEQueue * * @details * This operation needs to be used with caution because the number of free * entries can change unexpectedly. The main intent for using this operation * is in conjunction with event deferral. In this case the queue is accessed * only from a single thread (by a single AO), so the number of free * entries cannot change unexpectedly. * * @param[in] me current instance pointer (see @ref oop) * * @returns the current number of free slots in the queue. */ static inline QEQueueCtr QEQueue_getNFree(QEQueue const * const me) { return me->nFree; } /*! "raw" thread-safe QF event queue operation for obtaining the minimum * number of free entries ever in the queue (a.k.a. "low-watermark"). * @public @memberof QEQueue * * @details * This operation needs to be used with caution because the "low-watermark" * can change unexpectedly. The main intent for using this operation is to * get an idea of queue usage to size the queue adequately. * * @param[in] me current instance pointer (see @ref oop) * * @returns the minimum number of free entries ever in the queue since init. */ static inline QEQueueCtr QEQueue_getNMin(QEQueue const * const me) { return me->nMin; } /*! "raw" thread-safe QF event queue operation to find out if the queue * is empty. * @public @memberof QEQueue * * @details * This operation needs to be used with caution because the queue status * can change unexpectedly. The main intent for using this operation is in * conjunction with event deferral. In this case the queue is accessed only * from a single thread (by a single AO), so no other entity can post * events to the queue. * * @param[in] me_ current instance pointer (see @ref oop) * * @returns 'true' if the queue is current empty and 'false' otherwise. */ static inline bool QEQueue_isEmpty(QEQueue const * const me) { return me->frontEvt == (QEvt *)0; } /*$enddecl${QF::QEQueue} ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/ #endif /* QP_INC_QEQUEUE_H_ */