在Qt信号/槽的上下文中使用观察者模式
Using observer pattern in the context of Qt signals/slots
我正试图为我正在研究的算法做出一些设计决策。我想我想使用信号和插槽来实现观察者模式,但我不确定一些事情。
这是我正在研究的算法:
1.) Load tiles of an image from a large file
1a.) Copy the entire file to a new location
2.) Process the tiles as they are loaded
3.) If the copy has been created, copy the resulting data into the new file
所以我设想有一个类的函数,比如loadAllTiles(),它会发出信号告诉processTile(),另一个tile已经准备好被处理,同时继续加载下一个tile。
processTile()将执行一些计算,完成后,向writeResults()发出信号,表示准备写入一组新的结果数据。writeResults()将验证复制是否完成,并开始写入输出数据。
这听起来合理吗?是否有一种方法,使loadAllTiles()加载在一个瓷砖,传递该数据以某种方式processTile(),然后继续加载下一个瓷砖?我在考虑是否可以建立一个列表来存储准备处理的磁贴,以及另一个列表来存储准备写入磁盘的结果磁贴。我想缺点是我必须以某种方式保持这些列表的完整性,这样多个线程就不会试图从列表中添加/删除项目。
你的问题不完全清楚,但似乎你想把工作分成几个线程,这样瓷砖的处理可以在你完成加载整个集之前开始。
考虑一个多线程处理管道架构。为每个任务分配一个线程(加载、复制、处理),并通过Producer-Consumer队列(又名BlockingQueue)在任务之间传递tile。更精确地说,将指针(或共享指针)传递给tile,以避免不必要的复制。 在Qt中似乎没有现成的线程安全的BlockingQueue类,但您可以使用QQueue
, QWaitCondition
和QMutex
来卷起自己的。以下是一些灵感来源:
- Just Software Solutions的博客文章
- Java的BlockingQueue
- ZThreads的BlockingQueue
虽然Qt内没有现成的BlockingQueue,但似乎使用信号&带有Qt::QueuedConnection
选项的槽可以达到相同的目的。这篇Qt博客文章就是这样使用信号和槽的。
您可能希望将这种管道方法与内存池或空闲列表相结合,以便已经分配的瓷砖在您的管道中回收。
这是管道的概念草图:
TilePool -> TileLoader -> PCQ -> TileProcessor -> PCQ -> TileSaver -
^ |
----------------------------------------------------------------/
其中PCQ
表示一个生产者-消费者队列。
为了利用更多的并行性,您可以尝试在每个阶段使用线程池。
你也可以考虑看看英特尔的线程构建块。我自己没试过。请注意开源版本的GPL许可。
任何类型的并行化锁机制都可以防止列表损坏,无论是简单的锁,信号量等等。
否则,这种方法听起来是合理的,即使我要说文件必须是大的才有意义。只要它们能轻松地装入内存,我不认为分段加载它们有什么意义。另外:你打算如何在不读取整个图像重复提取瓷砖?- 如何设计具有不同类型的通知和观察器的观察者模式?
- 反射 + 函数指针与观察者模式
- 观察者模式不起作用
- 观察者模式:为什么主题应该是抽象的?
- 观察者模式专业化
- 如何在不必绑定到特定类的情况下实现观察者模式
- C++,函数指针与观察者模式
- C++11观察者模式(信号、插槽、事件、更改广播器/侦听器,或任何您想称之为的东西)
- 实施观察者模式C
- C++自己的观察者模式
- 不同可观察量的观察者模式
- 通过Boost信号的观察者模式2
- 具有类型信息的观察者模式(C++)
- 代码设计:观察者模式
- 观察者模式和继承:未调用正确的函数
- C++和Qt:观察者模式错误
- 在C++中实现观察者模式
- 多少听众是太多的观察者模式
- 当观察者希望观察不同的项目时实现观察者模式
- 通用观察者模式