私は C++ 開発者で、最近まで Windows 向けのアプリケーションの作成を余儀なくされるまで、主に Solaris と Linux でプログラミングを行っていました。
私は、TCP ソケットに支えられた C++ I/O ストリームに基づく通信設計を使用してきました。この設計は、他のスレッドが同じストリームを介して送信する (mutex によって同期される) 間、ストリームから継続的に読み取る単一のスレッド (ほとんどの場合、データを待機するソケット読み取りでブロックされる) に基づいています。
Windows に移行するとき、boost::asio::ip::tcp::iostream を使用してソケット ストリームを実装することにしました。上記のマルチスレッド設計により、Windows でデッドロックが発生したことを知り、がっかりしました。はoperator<<(std::basic_ostream<...>,std::basic_string<...>)
、入力操作と出力操作の両方でストリーム全体をロックする「Sentry」を宣言しているようです。読み取りスレッドは常にストリームを待機しているため、この Sentry が作成されると、他のスレッドからの送信操作がデッドロックします。
operator<< と Sentry の構築中のコール スタックの関連部分を次に示します。
...
ntdll.dll!7c901046()
CAF.exe!_Mtxlock(_RTL_CRITICAL_SECTION * _Mtx=0x00397ad0) Line 45 C
CAF.exe!std::_Mutex::_Lock() Line 24 + 0xb bytes C++
CAF.exe!std::basic_streambuf<char,std::char_traits<char> >::_Lock() Line 174 C++
CAF.exe!std::basic_ostream<char,std::char_traits<char> >::_Sentry_base::_Sentry_base(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}) Line 78 C++
CAF.exe!std::basic_ostream<char,std::char_traits<char> >::sentry::sentry(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}) Line 95 + 0x4e bytes C++
> CAF.exe!std::operator<<<char,std::char_traits<char>,std::allocator<char> >(std::basic_ostream<char,std::char_traits<char> > & _Ostr={...}, const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & _Str="###") Line 549 + 0xc bytes C++
...
istream コンポーネントと ostream コンポーネントが別々にロックされていれば問題ありませんが、そうではありません。
使用できるストリーム演算子の代替実装はありますか? ロックしないように指示できますか?自分で実装する必要がありますか (これを行う方法がわからない)。
任意の提案をいただければ幸いです。
(プラットフォームは Windows 32 ビットおよび 64 ビットです。Visual Studio 2003 Pro および 2008 Express で観察された動作)