C
事件队列类
template <typename EventType_, Qul::EventQueueOverrunPolicy overrunPolicy, size_t queueSize> class Qul::EventQueue提供了一种方便的方式在不同应用程序部分之间发送和接收事件。 更多...
头文件 | #include <qul/eventqueue.h> |
自 | Qt Quick Ultralite 1.0 |
公共类型
公共函数
事件队列() | |
~事件队列() | |
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) |
详细描述
这是一个模板类,需要事件的类型、EventQueueOverrunPolicy 和队列的最大 size
。默认值是 EventQueueOverrunPolicy_Discard 和队列大小为 5
。有关详细信息,请参阅 调整队列大小。
通常,可以使用 postEvent 函数将事件发布到队列(在没有中断上下文的情况下),或从中断处理程序使用 postEventFromInterrupt 函数。覆盖 onEvent 来处理事件,通常在下一帧期间。
DoubleQueue
是裸金属平台上的默认队列后端。只要有一个写入器,它就是中断安全的,因为写入和读取都是指向不同的列表。可以在队列有单个写入器的情况下从中断调用 postEventFromInterrupt()。如果有多个写入器,必须确保 postEvent() 或 postEventFromInterrupt() 不会被同一队列的另一个 postEvent() 或 postEventFromInterrupt() 中断。process() 可以被 postEvent() 或 postEventFromInterrupt() 中断。
对于基于实时操作系统(RTOS)的平台,队列后端实现依托于RTOS特定的队列,这使得在多线程环境下 Qul::EventQueue
具有线程安全性。
Qt Quick Ultralite 提供的默认后端使用 memcpy()
或等价操作来复制数据到队列。这意味着在 EventQueue 中使用的数据类型必须是/包含原始数据(POD),或者 纯旧数据。如果不能这样做,则必须使用指针。然而,Qt Quick Ultralite 提供的后端在事件是指针时不会管理内存。您可以选择使用 EventQueueOverrunPolicy_Discard 和 onEventDiscarded,或者提供自定义后端来处理被覆盖的事件的内存。有关更多信息,请参阅 实现自定义队列。
当队列接收到的的事件超过其容量时,将根据 EventQueueOverrunPolicy 进行处理。此外,只要状态未被调用 clearOverrun 重置,就会在处理任何事件之前调用 onQueueOverrun。
如果使用了 EventQueueOverrunPolicy_Discard 并且需要处理被丢弃的事件,则可以重写 onEventDiscarded 函数。
示例
从 EventQueue 派生,以创建特定事件类型的队列,并覆盖 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 } };
接下来,创建队列的实例。通常,公开数据或信号到 QML 的队列除了从 EventQueue 继承外,还从 Singleton 继承,这使得此步骤变得不必要。
IntegerEventQueue integerEventQueue;
现在,可以在中断上下文之外发布事件
integerEventQueue.postEvent(42);
或者从中断处理程序中
integerEventQueue.postEventFromInterrupt(42);
调整队列大小
默认情况下,队列的大小设置为 5
。大小决定在随后的分派操作之间可以存储多少事件。分派尽可能快速进行,通常在下一次应用程序帧中。使用 EventQueueOverrunPolicy 来控制队列满时队列的行为。
// 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>
通过覆盖 onQueueOverrun 方法来接收越界通知。
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(); } };
事件顺序
每个队列中事件的顺序被保留,但不同队列之间没有保证顺序。
当事件顺序很重要时,如输入事件,这可能会成为问题
keyboardInput.postEvent(KeyEvents(...)); touchInput.postEvent(TouchEvent(...)); // Unknown whether the KeyEvent or TouchEvent is processed first!
在这些情况下,可以使用单队列,而不是单独的队列,使用联合或 std::variant 事件类型。
另请参阅 将数据从中断处理程序转移到 QML。
成员函数文档
EventQueue::EventQueue()
构造队列并注册到应用程序以处理事件。
EventQueue::~EventQueue()
销毁队列并注销它。
[自 Qt Quick Ultralite 2.3]
void EventQueue::clearOverrun()
清除实现的越界标志。
这个函数是在 Qt Quick Ultralite 2.3 中引入的。
另请参阅 Qul::Platform::MessageQueueInterface::clearOverrun() 和 isOverrun()。
[自 Qt Quick Ultralite 2.3]
bool EventQueue::isOverrun() const
如果实现的队列被丢弃或覆盖的事件超载,则返回 true
。
这个函数是在 Qt Quick Ultralite 2.3 中引入的。
另请参阅 Qul::Platform::MessageQueueInterface::isOverrun() 和 clearOverrun。
[纯虚函数]
void EventQueue::onEvent(const Qul::EventQueue::EventType &event)
派生类必须重写此方法来处理 事件。
每个队列中事件按照从旧到新的顺序处理。
[虚函数]
void EventQueue::onEventDiscarded(const Qul::EventQueue::EventType &event)
派生类可以重写此方法来处理丢弃的 事件。如果 EventType_
参数是一个指针,需要适当的销毁例程,这非常有用。
此函数仅在 Qul::EventQueueOverrunPolicy_Discard 被使用时调用。
[虚函数]
void EventQueue::onQueueOverrun()
派生类可以重写此方法来处理队列超载。
如果向此队列发送的事件多于分配的存储空间,则调用此函数。它不是在 postEvent 或 postEventFromInterrupt 调用期间立即调用,而是在下一次 onEvent 调用之前直接调用。
void EventQueue::postEvent(const Qul::EventQueue::EventType &event)
将 事件 的副本追加到队列中,以便在下一次调度操作(通常是下一次帧)期间进行处理。
如果队列已满,EventQueueOverrunPolicy 确定是丢弃事件还是覆盖旧事件。在这两种情况下,都会安排调用 onQueueOverrun。
注意:在中断上下文中,请使用 postEventFromInterrupt 替代。
void EventQueue::postEventFromInterrupt(const Qul::EventQueue::EventType &event)
将 事件 的副本追加到队列中,以便在下一次调度操作(通常是下一次帧)期间进行处理。
如果队列已满,EventQueueOverrunPolicy 确定是丢弃事件还是覆盖旧事件。在这两种情况下,都会安排调用 onQueueOverrun。
当从中断上下文写入事件时应使用此函数。
在特定的 Qt 许可证下提供。
了解更多信息。