[C ++] boost :: property_tree :: ptree 스레드가 안전한가요?
boost json 파서는 boost :: spirit에 의존하고 spirit은 스레드 안전성 기본값이 아니기 때문입니다.이 매크로를 ptree 헤더 파일 앞에 추가하여 해결할 수 있습니다.
#define BOOST_SPIRIT_THREADSAFE
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
-------------------
요약 :내 제안 : 원자 스왑 관용구 사용
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
) 루트 노드를 파서의 컨텍스트 트리와 함께.분명히 아토믹 스왑 기능은 주로 예외 안전을 위해 존재합니다 (JSON 구문 분석 도중 예외가 발생한 경우 ptree를 변경하고 싶지 않음). 그러나
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 개 표준 라이브러리 클래스로 분명히 스레드 안전되지 않는-------------------
ptree의 JSON 파서가 Boost 1.59에서 다시 작성되고 릴리스되었습니다. 추가
BOOST_SPIRIT_THREADSAFE
는 사용하지 않기 때문에 정의는 더 이상 재산권 트리 필요하지 않습니다
Boost.Spirit
더 이상 및
read_json
기능 스레드 안전한 것으로 간주 할 수있다.-------------------
Wei와 liquidblueocean에게 감사드립니다. #define이 내 문제를 해결했습니다. 참고로 read_json을 호출하는 두 개의 스레드가있을 때 windbg! analyse -v에서이 스택 추적을 얻었습니다.
10 07b3e4fc 0021b2de sseng!_STL::for_each<_STL::reverse_iterator<boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::less<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> > > > >,boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > > * *>,_STL::binder2nd<_STL::mem_fun1_t<int,boost::spirit::classic::impl::grammar_helper_base<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::less<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> > > > >,boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >,boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::less<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> > > > >,boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > *> > >+0x11 [c:\ss\tp\aoo341\main\stlport\rel\inc\stlport\stl\_algo.h @ 65]
11 07b3e520 0021f867 sseng!boost::spirit::classic::impl::grammar_destruct<boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::less<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> > > > >,boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> > >+0x28 [c:\ss\tp\aoo341\main\boost\rel\inc\boost\spirit\home\classic\core\non_terminal\impl\grammar.ipp @ 325]
12 07b3e54c 002224fa sseng!boost::spirit::classic::grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::less<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> > > > >,boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> >::~grammar<boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::less<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> > > > >,boost::spirit::classic::parser_context<boost::spirit::classic::nil_t> >+0x1e [c:\ss\tp\aoo341\main\boost\rel\inc\boost\spirit\home\classic\core\non_terminal\grammar.hpp @ 52]
13 07b3e574 00226e37 sseng!boost::property_tree::json_parser::json_grammar<boost::property_tree::basic_ptree<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::less<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> > > > >::~json_grammar<boost::property_tree::basic_ptree<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::less<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> > > > >+0x28
14 07b3e784 00226f5c sseng!boost::property_tree::json_parser::read_json_internal<boost::property_tree::basic_ptree<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::less<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> > > > >+0x149 [c:\ss\tp\aoo341\main\boost\rel\inc\boost\property_tree\detail\json_parser_read.hpp @ 317]
15 07b3e7c0 00232261 sseng!boost::property_tree::json_parser::read_json<boost::property_tree::basic_ptree<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> >,_STL::less<_STL::basic_string<char,_STL::char_traits<char>,_STL::allocator<char> > > > >+0x25 [c:\ss\tp\aoo341\main\boost\rel\inc\boost\property_tree\json_parser.hpp @ 45]
16 07b3ea20 00232a28 sseng!SSPhone::Handshake+0x15b [c:\ss\xl\src\cpp\bin\eng\ssphone.cpp @ 272]
17 07b3ea5c 00234fc7 sseng!SSPhone::OnEvent+0x1a9 [c:\ss\xl\src\cpp\bin\eng\ssphone.cpp @ 232]
18 07b3fb7c 6f6b3433 sseng!PhoneThreadFunc+0x1ed [c:\ss\xl\src\cpp\bin\eng\ssthrd.cpp @ 198]
출처
https://stackoverflow.com/questions/22089792