「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 }}

表示オプション

横に並べて表示:
変化行の前後のみ表示:
目安箱バナー