「C++/ライブラリ/mt_stream」の編集履歴(バックアップ)一覧はこちら
「C++/ライブラリ/mt_stream」(2008/12/15 (月) 10:47:51) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
***概要
マルチスレッドでも出力の順番を保証する ostream ラッパークラス。~
ロック用にBoostを使ってるので要Boost。~
Boost使わずにロックできるならBoostなしでも可。
***使い方
#codehighlight(C++){{
util::mt_ostream mt(std::cout);
void multithreded_func()
{
mt << "foo" << "bar" << std::endl; // 出力が"foobar"になることを保証
}
}}
***コード
#codehighlight(C++){{
#ifndef UTIL_MT_STREAM_H
#define UTIL_MT_STREAM_H
#include <iostream>
#include <boost/thread.hpp>
namespace util {
namespace detail {
/* Boost を使用したロック用クラス */
class boost_lock {
public:
boost_lock()
{}
~boost_lock()
{}
void lock()
{
mutex_.lock();
}
void unlock()
{
mutex_.unlock();
}
private:
explicit boost_lock(const boost_lock&);
boost_lock &operator=(const boost_lock&);
boost::mutex mutex_;
};
/* 例外安全ロッククラス */
template<class Lk>
class lock_holder {
public:
lock_holder(Lk &lock)
: lock_(lock)
{
lock_.lock();
}
~lock_holder()
{
try {
lock_.unlock();
} catch(...) {}
}
private:
explicit lock_holder(const lock_holder&);
lock_holder &operator=(const lock_holder&);
Lk &lock_;
};
/* Boostを使用したスレッド・ローカル・ストレージクラス */
template<class Ch>
class boost_thread_specific_storage {
public:
boost_thread_specific_storage(size_t num)
: default_size_(num)
{}
~boost_thread_specific_storage()
{}
Ch *begin()
{
return &(get_storage()[0]);
}
void resize(size_t new_size)
{
get_storage().resize(new_size);
}
size_t size()
{
return get_storage().size();
}
void push_back(Ch c)
{
get_storage().push_back(c);
}
void clear()
{
get_storage().clear();
}
private:
std::vector<Ch> &get_storage()
{
std::vector<Ch> *p = storage_.get();
if(p==NULL) {
p = new std::vector<Ch>;
p->reserve(default_size_);
storage_.reset(p);
}
return *p;
}
size_t default_size_;
boost::thread_specific_ptr<std::vector<Ch> > storage_;
};
/* スレッドセーフなstreambufクラス */
template <class Ch, class Lk, class St, class Tr=std::char_traits<Ch> >
class basic_mt_streambuf : public std::basic_streambuf<Ch,Tr> {
public:
typedef typename std::basic_streambuf<Ch, Tr>::int_type int_type;
basic_mt_streambuf(std::basic_ostream<Ch,Tr>& os)
: out_(os), buf_(16)
{}
~basic_mt_streambuf()
{}
protected:
int_type overflow(int_type c=Tr::eof())
{
if(c!=Tr::eof()) {
buf_.push_back(c);
return Tr::not_eof(c);
}
return Tr::eof();
}
int sync()
{
lock_holder<Lk> l(lock_);
out_.write(buf_.begin(), buf_.size());
out_.flush();
buf_.clear();
return 0;
}
private:
explicit basic_mt_streambuf(const basic_mt_streambuf&);
basic_mt_streambuf &operator=(const basic_mt_streambuf&);
std::basic_ostream<Ch,Tr> &out_;
St buf_;
Lk lock_;
};
/**
ostreamのラッパークラス
@param Ch 文字型(charまたはwchar_t)
@param Lk 使用するロック用クラス
@param St 使用するスレッド・ローカル・ストレージクラス
@param Tr traitsクラス
*/
template <class Ch, class Lk, class St, class Tr=std::char_traits<Ch> >
class basic_mt_ostream : public std::basic_iostream<Ch,Tr> {
public:
basic_mt_ostream(std::basic_ostream<Ch,Tr> &os)
: std::basic_iostream<Ch,Tr>(&streambuf_), streambuf_(os)
{}
~basic_mt_ostream()
{}
private:
explicit basic_mt_ostream(const basic_mt_ostream&);
basic_mt_ostream &operator=(const basic_mt_ostream&);
basic_mt_streambuf<Ch, Lk, St, Tr> streambuf_;
};
}
typedef detail::basic_mt_ostream<char, detail::boost_lock, detail::boost_thread_specific_storage<char> > mt_ostream;
typedef detail::basic_mt_ostream<wchar_t, detail::boost_lock, detail::boost_thread_specific_storage<wchar_t> > mt_wostream;
}
#endif
}}
***概要
マルチスレッドでも出力の順番を保証する ostream ラッパークラス。~
ロック用にBoostを使ってるので要Boost。~
Boost使わずにロックできるならBoostなしでも可。
***使い方
#codehighlight(C++){{
util::mt_ostream mt(std::cout);
void multithreded_func()
{
mt << "foo" << "bar" << std::endl; // 出力が"foobar"になることを保証
}
}}
***コード
#codehighlight(C++){{
#ifndef UTIL_MT_STREAM_H
#define UTIL_MT_STREAM_H
#include <iostream>
#include <boost/thread.hpp>
namespace util {
namespace detail {
/* Boost を使用したロック用クラス */
class boost_lock {
public:
boost_lock()
{}
~boost_lock()
{}
void lock()
{
mutex_.lock();
}
void unlock()
{
mutex_.unlock();
}
private:
explicit boost_lock(const boost_lock&);
boost_lock &operator=(const boost_lock&);
boost::mutex mutex_;
};
/* 例外安全ロッククラス */
template<class Lk>
class lock_holder {
public:
lock_holder(Lk &lock)
: lock_(lock)
{
lock_.lock();
}
~lock_holder()
{
try {
lock_.unlock();
} catch(...) {}
}
private:
explicit lock_holder(const lock_holder&);
lock_holder &operator=(const lock_holder&);
Lk &lock_;
};
/* Boostを使用したスレッド・ローカル・ストレージクラス */
template<class Ch>
class boost_thread_specific_storage {
public:
boost_thread_specific_storage(size_t num)
: default_size_(num)
{}
~boost_thread_specific_storage()
{}
Ch *begin()
{
return &(get_storage()[0]);
}
void resize(size_t new_size)
{
get_storage().resize(new_size);
}
size_t size()
{
return get_storage().size();
}
void push_back(Ch c)
{
get_storage().push_back(c);
}
void clear()
{
get_storage().clear();
}
private:
std::vector<Ch> &get_storage()
{
std::vector<Ch> *p = storage_.get();
if(p==NULL) {
p = new std::vector<Ch>;
p->reserve(default_size_);
storage_.reset(p);
}
return *p;
}
size_t default_size_;
boost::thread_specific_ptr<std::vector<Ch> > storage_;
};
/* スレッドセーフなstreambufクラス */
template <class Ch, class Lk, class St, class Tr=std::char_traits<Ch> >
class basic_mt_streambuf : public std::basic_streambuf<Ch,Tr> {
public:
typedef typename std::basic_streambuf<Ch, Tr>::int_type int_type;
basic_mt_streambuf(std::basic_ostream<Ch,Tr>& os)
: out_(os), buf_(16)
{}
~basic_mt_streambuf()
{}
protected:
int_type overflow(int_type c=Tr::eof())
{
if(c!=Tr::eof()) {
buf_.push_back(c);
return Tr::not_eof(c);
}
return Tr::eof();
}
int sync()
{
lock_holder<Lk> l(lock_);
out_.write(buf_.begin(), buf_.size());
out_.flush();
buf_.clear();
return 0;
}
private:
explicit basic_mt_streambuf(const basic_mt_streambuf&);
basic_mt_streambuf &operator=(const basic_mt_streambuf&);
std::basic_ostream<Ch,Tr> &out_;
St buf_;
Lk lock_;
};
/**
ostreamのラッパークラス
@param Ch 文字型(charまたはwchar_t)
@param Lk 使用するロック用クラス
@param St 使用するスレッド・ローカル・ストレージクラス
@param Tr traitsクラス
*/
template <class Ch, class Lk, class St, class Tr=std::char_traits<Ch> >
class basic_mt_ostream : public std::basic_iostream<Ch,Tr> {
public:
basic_mt_ostream(std::basic_ostream<Ch,Tr> &os)
: std::basic_iostream<Ch,Tr>(&streambuf_), streambuf_(os)
{}
~basic_mt_ostream()
{}
private:
explicit basic_mt_ostream(const basic_mt_ostream&);
basic_mt_ostream &operator=(const basic_mt_ostream&);
basic_mt_streambuf<Ch, Lk, St, Tr> streambuf_;
};
}
typedef detail::basic_mt_ostream<char, detail::boost_lock, detail::boost_thread_specific_storage<char> > mt_ostream;
typedef detail::basic_mt_ostream<wchar_t, detail::boost_lock, detail::boost_thread_specific_storage<wchar_t> > mt_wostream;
}
#endif
}}
表示オプション
横に並べて表示:
変化行の前後のみ表示: