我使用boost
和std::stringstream
编写了一个小课程来提供并发std::ostream
支持。该类需要事先知道线程数(即使这个行为可以调整),并且类使用通道的概念来识别不同的线程,以便最小化资源并发,输出整个块并避免阻塞,类缓冲stringstream
对象中每个线程的输入。当线程调用flush()时,如果ostream
资源不忙或缓冲区已满,则刷新缓冲区。
您是否看到此实施存在任何(性能)问题?特别是,使用频道我试图限制stringstream
对象结构的数量。有没有一种好方法告诉stringstream
对象要分配的字符串的长度?是否值得使用char数组进行缓冲?我选择stringstream
不仅因为它易于使用,而且因为我在()-operator成员函数中实现了完全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_;
};