TL; DR:
Мое предложение: используйте идиому атомарного свопа
ptree my_shared;
mutex shared_ptree_lock;
{
ptree parsed; // temporary
read_json(ss,pt); // this may take a while (or even fail)
lock_guard hold(shared_ptree_lock);
std::swap(pt, my_shared); // swap under lock
}
Теперь, нужно ли вам заблокировать общее дерево перед чтением, зависит от ваших знаний о потокеконтекст (другими словами, зависит от того, знаете ли вы, что ваше дерево может быть изменено в одно и то же время).
Чтобы сделать вещи безумно гибкими, проделайте то же самое с помощью shared_ptr<ptree>
- но это потребует значительных накладных расходов.Предварительно, что при использовании идиомы подкачки вам не придется блокировать вещи на стороне чтения, поскольку читатели с радостью продолжат читать старое дерево, и если они закончат чтение и выпустят shared_ptr
, оно будет уничтожено вконец.
Я не совсем уверен, что вы ожидаете.Доступ к дереву свойств для записи из двух потоков никогда не станет поточно-безопасным без блокировки.Поэтому, я предполагаю, что вы имеете в виду, является ли дерево свойств безопасным для чтения и одновременно обрабатывает его где-то еще.
Здесь мое основное ожидание: нет.В C ++ есть культура «плати за то, что тебе нужно», ты не увидишь никаких поточно-ориентированных классов общего назначения.Будет иметь возможность
- препроцессор #define для включения безопасности потока
- параметр шаблона политики, который управляет поведением
Удивительно, но, посмотрев на исходный код, он выглядит так, как будто он почти потокобезопасен.Но не полностью:)
Похоже, что не существует #define или флага, который можно установить для обеспечения безопасности потока дерева свойств, поэтому вы застряли с блокировкой.
Обоснование:
Глядя на internal_read_json
Я вижу, что он получает доступ только к потоку (который в любом случае должен быть закрыт для этого читателя, поскольку совместное использование потоков несколькими (одновременными) пользователями вряд ли когда-либо пригодится 1 ), а затем,очень правильно, только заменяет корневой узел ptree (pt
) на дерево контекста синтаксического анализатора.
Очевидно, что функция атомарного свопинга в основном существует для исключительной безопасности (вы не хотите менять свое ptree, еслина полпути разбор JSON произошла исключительная ситуация).Тем не менее, IFF операция подкачки должна была быть поточно-ориентированной, это также сделало бы доступ к pt
потоко-безопасным.
Увы, на ptree_implementation мы видим, что свопне является потокобезопасным:
template<class K, class D, class C> inline
void basic_ptree<K, D, C>::swap(basic_ptree<K, D, C> &rhs)
{
m_data.swap(rhs.m_data);
// Void pointers, no ADL necessary
std::swap(m_children, rhs.m_children);
}
Например, вы можете иметь состояние гонки между перестановками m_data
и m_children
, более того, свопы являются стандартными, а не атомарными.
1 кроме istringstream
, очевидно, не является поточно-ориентированным, поскольку это стандартная библиотека класса C ++ 98