Использование паттерна наблюдателя в контексте сигналов / слотов Qt - PullRequest
3 голосов
/ 13 июля 2011

Я пытаюсь принять некоторые конструктивные решения для алгоритма, над которым я работаю. Я думаю, что я хочу использовать сигналы и слоты для реализации шаблона наблюдателя, но я не уверен в некоторых вещах.

Вот алгоритм, над которым я работаю:

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 (), что другая плитка готова для обработки, и в то же время перейти к загрузке следующей плитки.

processTile () будет выполнять некоторые вычисления и, когда будет завершено, сообщать writeResults (), что новый набор данных результатов готов для записи. writeResults () проверит, что копирование завершено, и начнет запись выходных данных.

Это звучит разумно? Есть ли способ заставить loadAllTiles () загрузиться в плитку, как-то передать эти данные в processTile (), а затем продолжить и загрузить следующую плитку? Я думал о том, чтобы, возможно, создать какой-то список для хранения плиток, готовых к обработке, и другой список для готовых к записи плиток на диск. Я предполагаю, что недостатком является то, что я должен как-то держать эти списки в такте, чтобы несколько потоков не пытались добавлять / удалять элементы из списка.

Спасибо за понимание.

Ответы [ 2 ]

5 голосов
/ 13 июля 2011

Это не совсем ясно в вашем вопросе, но кажется, что вы хотите разделить работу на несколько потоков, чтобы обработка плиток могла начаться до того, как вы закончите загрузку всего набора.

Рассмотрим конвейер многопоточной обработки архитектура.Назначьте один поток для каждой задачи (загрузка, копирование, обработка) и передавайте тайлы между задачами через Producer-Consumer очереди (также известный как BlockingQueue).Чтобы быть более точным, передавайте указатели (или общие указатели) на листы, чтобы избежать ненужного копирования.

Кажется, в Qt нет готового поточно-ориентированного класса BlockingQueue, но вы можете свернутьпо своему усмотрению, используя QQueue, QWaitCondition и QMutex.Вот несколько источников вдохновения:

Хотя в Qt нет готового BlockingQueue, кажется, что использование сигналов и слотов с опцией Qt::QueuedConnection может служитьта же цель.В этой статье блога Qt используются такие сигналы и слоты.

Возможно, вы захотите объединить этот конвейерный подход с пулом памяти или свободным списком плиток, так что уже выделенные плитки повторно используются в вашем конвейере.

Вот концептуальный эскиз конвейера:

TilePool -> TileLoader -> PCQ -> TileProcessor -> PCQ -> TileSaver -\
  ^                                                                 |
   \----------------------------------------------------------------/

, где PCQ представляет очередь Производитель-Потребитель.

Чтобы использовать еще больший параллелизм, вы можете попробовать пулы потоков на каждом этапе.

Вы также можете рассмотреть возможность использования Intel Threading Building Blocks .Я сам не пробовал.Помните о лицензии GPL для версии с открытым исходным кодом.

0 голосов
/ 13 июля 2011

Сохранение списков от повреждения должно быть возможно с любыми механизмами блокировки распараллеливания, будь то простые блокировки, семафоры и т. Д. И т. Д.

В противном случае подход звучит разумно, хотя я бы сказал, что файлы имелибыть большим , чтобы это имело смысл.Пока они легко помещаются в памяти, я не вижу смысла загружать их по кусочкам.Также: Как вы планируете извлекать тайлы, не читая все изображение повторно?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...