C
EventQueue Class
template <typename EventType_, Qul::EventQueueOverrunPolicy overrunPolicy, size_t queueSize> class Qul::EventQueueProvides a convenient way to send and receive events across different parts of the application. More...
Header: | #include <qul/eventqueue.h> |
Since: | Qt Quick Ultralite 1.0 |
Public Types
Public Functions
EventQueue() | |
~EventQueue() | |
void | clearOverrun() |
bool | isOverrun() const |
virtual void | onEvent(const Qul::EventQueue::EventType &event) = 0 |
virtual void | onEventDiscarded(const Qul::EventQueue::EventType &event) |
virtual void | onQueueOverrun() |
void | postEvent(const Qul::EventQueue::EventType &event) |
void | postEventFromInterrupt(const Qul::EventQueue::EventType &event) |
Detailed Description
This is a template class that requires type of the event
, EventQueueOverrunPolicy, and maximum size
of the queue. The defaults are EventQueueOverrunPolicy_Discard and a queue size of 5
. See Adjusting the Queue Size for details.
In general, events can be posted to the queue using the postEvent function when not in interrupt context, or using the postEventFromInterrupt function from an interrupt handler. Override onEvent to process the events, typically during the next frame.
DoubleQueue
is the default queue backend on baremetal platforms. It is interrupt-safe as long as there is a single writer, because writes and reads are directed to different lists. postEventFromInterrupt() can be called from an interrupt when there is a single writer to a queue. If there are multiple writers, you must ensure that postEvent() or postEventFromInterrupt() are not interrupted by another postEvent() or postEventFromInterrupt() to the same queue. process() is safe to be interrupted by postEvent() or postEventFromInterrupt().
On embedded platforms that have support for std::thread and std::mutex, the queue is thread-safe by using mutexes.
For RTOS-based platforms, the implementation of queue backend is based on RTOS-specific queues, which makes the Qul::EventQueue
thread-safe in a multi-threaded environment.
The default backends provided by Qt Quick Ultralite use memcpy()
or equivalent to copy the data to the queue. This means that the datatypes used in the EventQueue must be/contain POD, or plain old data. If this cannot be done, pointers must be used instead. However, backends provided by Qt Quick Ultralite do not manage memory when the events are pointers. You must either use EventQueueOverrunPolicy_Discard and onEventDiscarded, or provide a custom backend to handle memory for events that are overwritten. See Implementing custom queues for more information.
When a queue receives more events than it can hold, they are handled according to the EventQueueOverrunPolicy. Additionally, onQueueOverrun is called before processing any event as long as the state is not reset by calling clearOverrun.
If EventQueueOverrunPolicy_Discard is used and discarded events need additional handling, onEventDiscarded function can be overridden.
Example
Derive from EventQueue to create a queue for a particular event type and override onEvent:
#include <qul/eventqueue.h> typedef int IntegerEvent; class IntegerEventQueue : public Qul::EventQueue<IntegerEvent> { void onEvent(const IntegerEvent &event) override { // do some stuff with your event here } };
Next, create an instance of the queue. Queues that expose data or signals to QML are often derived from Singleton in addition to EventQueue, making this step unnecessary.
IntegerEventQueue integerEventQueue;
Now, events can be posted from outside of interrupt context:
integerEventQueue.postEvent(42);
Or from interrupt handlers:
integerEventQueue.postEventFromInterrupt(42);
Adjusting the Queue Size
By default, size of the queue is set to 5
. The size determines how many events can be stored between subsequent dispatch operations. Dispatching is performed as soon as possible, typically in the next application frame. Use the EventQueueOverrunPolicy to control how the queue behaves when it is full.
// A queue where only the most recent event is interesting Qul::EventQueue<IntegerEvent, Qul::EventQueueOverrunPolicy_OverwriteOldest, 1> // A queue that can store many events Qul::EventQueue<IntegerEvent, Qul::EventQueueOverrunPolicy_Discard, 1000>
Override the onQueueOverrun method to get notified of overruns.
class AudioQueue : public Qul::EventQueue<float, Qul::EventQueueOverrunPolicy_Discard, 1000> { void onQueueOverrun() override { // Avoid the problem by reducing the frequency of event generation. setSampleRate(8000); clearOverrun(); } };
Event Ordering
The order of events in each queue is preserved but no order is guaranteed between different queues.
This can be a problem when the order of events matters, such as for input events:
keyboardInput.postEvent(KeyEvents(...)); touchInput.postEvent(TouchEvent(...)); // Unknown whether the KeyEvent or TouchEvent is processed first!
In these cases, use a single queue with a union or std::variant event type instead of separate queues.
See also Transferring data from Interrupt Handlers to QML.
Member Function Documentation
EventQueue::EventQueue()
Constructs the queue and registers it with the application for event processing.
EventQueue::~EventQueue()
Destructs the queue and unregisters it.
[since Qt Quick Ultralite 2.3]
void EventQueue::clearOverrun()
Clears implementation's overrun flag.
This function was introduced in Qt Quick Ultralite 2.3.
See also Qul::Platform::MessageQueueInterface::clearOverrun() and isOverrun().
[since Qt Quick Ultralite 2.3]
bool EventQueue::isOverrun() const
Returns true
if the implementation's queue is overrun by events that are either discarded or overwritten.
This function was introduced in Qt Quick Ultralite 2.3.
See also Qul::Platform::MessageQueueInterface::isOverrun() and clearOverrun().
[pure virtual]
void EventQueue::onEvent(const Qul::EventQueue::EventType &event)
A derived class must override this method to process event.
Events are processed from oldest to newest in each queue.
[virtual]
void EventQueue::onEventDiscarded(const Qul::EventQueue::EventType &event)
A derived class may override this method to handle a discarded event. This is useful if the EventType_
argument is a pointer, which needs a proper destruction routine.
This function is called only if Qul::EventQueueOverrunPolicy_Discard is used.
[virtual]
void EventQueue::onQueueOverrun()
A derived class may override this method to handle queue overrun.
This function is called if more events were posted to this queue than fit the allocated storage. It is not called immediately during the postEvent or postEventFromInterrupt call, but rather directly before the next batch of onEvent calls.
void EventQueue::postEvent(const Qul::EventQueue::EventType &event)
Appends a copy of event to the queue to schedule it for processing during the next dispatch operation (typically the next frame).
If the queue is full, the EventQueueOverrunPolicy determines whether the event is discarded or overwrites an old event. In both cases, a call of onQueueOverrun is scheduled.
Note: From interrupt context, use postEventFromInterrupt instead
void EventQueue::postEventFromInterrupt(const Qul::EventQueue::EventType &event)
Appends a copy of event to the queue to schedule it for processing during the next dispatch operation (typically the next frame).
If the queue is full, the EventQueueOverrunPolicy determines whether the event is discarded or overwrites an old event. In both cases, a call of onQueueOverrun is scheduled.
This function should be used when posting events from interrupt context.
Available under certain Qt licenses.
Find out more.