同時サポートを提供するためにboost
、 andを使用して小さなクラスを作成しました。クラスは事前にスレッドの数を知る必要があり (この動作は調整可能ですが)、クラスはチャネルの概念を使用してさまざまなスレッドを識別し、リソースの同時実行を最小限に抑え、ブロック全体を出力してブロックを回避します。オブジェクト内の各スレッドの入力をバッファリングします。スレッドが flush() を呼び出すと、リソースがビジーでない場合、またはバッファがいっぱいの場合、バッファがフラッシュされます。std::stringstream
std::ostream
stringstream
ostream
この実装で (パフォーマンス) 問題はありますか? stringstream
特に、チャネルを使用して、オブジェクト構築の数を制限しようとしました。stringstream
割り当てる文字列の長さをオブジェクトに伝える良い方法はありますか? 代わりに、バッファリングに char 配列を使用する価値はありますか? stringstream
使いやすさだけでなくostream
、() 演算子メンバー関数で完全な互換性を実現するという事実のために選択しました。
#include <boost/thread.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include<ostream>
#include<sstream>
class ConcurrentOutStream {
public:
ConcurrentOutStream( std::ostream& os, const uint channels, const uint buffer_size ) :
os_( os ),
max_buffer_size_( buffer_size ),
buffers_( channels )
{
for ( uint i=0; i<threads; ++i ) buffers_.push_back( new std::ostringstream ); //because streams are not copyable
};
~ConcurrentOutStream() {
for ( uint i=0; i<buffers_.size(); ++i ) forceFlush( i );
}
std::ostream& operator()( const uint channel ) { return buffers_[channel]; }
void flush( const uint channel ) {
if ( buffers_[channel].str().size() < max_buffer_size_ ) tryFlush( channel );
else forceFlush( channel );
}
const uint channels() { return buffers_.size(); };
protected:
void tryFlush( const uint channel ) { // write if ostream not busy
if ( mutex_.try_lock() ) {
os_ << buffers_[channel].str();
buffers_[channel].str("");
mutex_.unlock();
}
}
void forceFlush( const uint channel ) {
if ( ! buffers_[channel].str().empty() ) {
boost::mutex::scoped_lock( mutex_ );
os_ << buffers_[channel].str();
buffers_[channel].str("");
}
}
std::ostream& os_;
const uint max_buffer_size_;
boost::ptr_vector< std::ostringstream > buffers_;
boost::mutex mutex_;
};