Как поместить std::string в boost:: lockfree:: queue (или альтернативу)?

Я пытаюсь поместить std::string в boost::lockfree::queue, чтобы мои потоки могли обновлять друг друга новыми данными.

Когда я пытаюсь использовать boost::lockfree::queue<std::string> updated_data;, g++ говорит:

В создании экземпляра класса boost:: lockfree:: queue > :

Ошибка: статическое утверждение не выполнено: (boost:: has_trivial_destructor:: значение)

ошибка: статическое утверждение не выполнено: (boost:: has_trivial_assign:: значение)

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

Есть ли альтернативный способ передачи текстовых данных между потоками с помощью lockfree? Если нет, пожалуйста, покажите мне, как положить std::string в boost::lockfree::queue.

Ответ 1

Если вы помещаете необработанные указатели в очередь, старый std::strings будет просочиться, поскольку освободить их невозможно, если они больше не нужны. Это связано с тем, что невозможно освободить объекты поточно-безопасным способом без фиксации (кроме некоторых трюков, таких как указатели опасности, которые boost::lockfree::queue не используется)

По техническим причинам я действительно не понимаю, для boost::lockfree::queue требуется тривиальный оператор присваивания и тривиальный деструктор, что означает, что ваш объект не может быть и не содержать какой-либо тип данных, который должен освобождать память в своем деструкторе, например std::string.

Ответ 2

В документации boost::lockfree::queue четко указано, что содержащийся элемент должен иметь тривиальное назначение и деструктор копирования, которые std::string не имеет.

Если у вас есть один производитель и один потребитель, вы можете использовать spsc_queue (http://www.boost.org/doc/libs/1_54_0/doc/html/boost/lockfree/spsc_queue.html), для которого требуется только конструктивная возможность и возможность копирования по умолчанию.

Если у вас есть несколько продюсеров или потребителей, вы будете застревать с обычной блокировкой (или настраиваемой строкой, которая не использует динамическое распределение).

Ответ 3

У меня нет надежды когда-либо исправлять это сам, так как я почти новичок в С++.

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

Есть ли альтернативный способ передачи текстовых данных между потоками с помощью lockfree?

Да, вы можете просто сохранить указатель std::string* к данным в очереди, потому что указатель является тривиальным типом и поэтому разрешен в очереди. Эквивалентно, вы можете сохранить reference_wrapper<std::string>. Проблема заключается в том, что вам нужно хранить строки где-то в другом месте, чтобы иметь возможность указывать на них, поэтому теперь все, что вы сделали, это переместить проблему в другое место (например, вы могли бы поддерживать список строк в каждом потоке, и указатели хранилища для строки, управляемой извне, в свободной от блокировки очереди, но вы не знаете, когда можно безопасно удалить string из списка для потоков, чтобы он увеличивался и увеличивался.)

Я бы предложил использовать простой std::queue<std::string> и выполнить собственную синхронизацию с boost::mutex и boost::condition_variable или найти существующую реализацию потоковой (не блокирующей!) очереди.