У меня есть структура диаграмм направленного графа, используемая для обработки звукового сигнала (см. http://audulus.com, если вам интересно).
Я хотел бы, чтобы графы были сильными ссылками, поэтому в отсутствие циклов std::shared_ptr
выполнил бы трюк. Увы, на графике есть потенциальные циклы.
Итак, у меня была эта идея для простого параллельного сборщика меток:
поток мутатора отправляет события в поток коллектора. Коллекторный поток поддерживает собственное представление графика и не пересекает график потока мутаторов. В коллекторной резьбе с помощью регулярных интервалов используется разметка.
События будут следующими (в форме вызова функции):
-
AddRoot(Node*)
-
RemoveRoot(Node*)
-
AddEdge(Node*, Node*)
-
RemoveEdge(Node*, Node*)
Правильно ли эта схема? В потоке коллектора есть более старая версия того, что видит мутаторный поток. Моя интуиция заключается в том, что, поскольку node, недоступный в более раннее время, по-прежнему будет недоступен позднее, поток коллектора может удалить недоступный объект, как только он найдет его.
Кроме того, если он правильный для одного потока мутаторов, будет ли он работать для нескольких потоков мутаторов?
UPDATE
Я выпустил здесь код: https://github.com/audulus/collector. Код на самом деле довольно общий. Используйте RootPtr<T>
для автоматического отслеживания корневых узлов. Связи между узлами управляются с помощью EdgePtr<T>
.
Коллекционер, похоже, работает для нескольких потоков мутаторов (как в моем приложении, так и в модульных тестах), но я чувствую, что требуется подтверждение правильности.
ОБРАТИТЕ ВНИМАНИЕ (в ответе на комментарий @AaronGolden ниже, , судя по комментариям ниже, люди не читают этот): поток мутаторов отвечает за вызов коллектора в правильном порядке. Например, если поток мутатора вызывает RemoveEdge(a,b)
перед назначением b
на RootPtr
, сборщик может вмешиваться и собирать b
.
ОБНОВЛЕНИЕ 2:
Я обновил код до своей последней версии и обновил ссылку выше. Я уже более года использовал код в своем приложении и не приписывал ему никаких ошибок.