C

EventQueue Class

template <typename EventType_, Qul::EventQueueOverrunPolicy overrunPolicy, size_t queueSize> class Qul::EventQueue

Provides 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 Type Documentation

EventQueue::EventType

Type of event used for this EventLoop.

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.