1 // (C) Copyright 2012 Vicente J. Botet Escriba 2 // Distributed under the Boost Software License, Version 1.0. (See 3 // accompanying file LICENSE_1_0.txt or copy at 4 // http://www.boost.org/LICENSE_1_0.txt) 5 6 7 #ifndef BOOST_THREAD_EXTERNALLY_LOCKED_STREAM_HPP 8 #define BOOST_THREAD_EXTERNALLY_LOCKED_STREAM_HPP 9 10 #include <boost/thread/detail/config.hpp> 11 #include <boost/thread/detail/move.hpp> 12 #include <boost/thread/detail/delete.hpp> 13 14 #include <boost/thread/externally_locked.hpp> 15 #include <boost/thread/lock_traits.hpp> 16 #include <boost/thread/recursive_mutex.hpp> 17 #include <boost/thread/strict_lock.hpp> 18 19 #include <boost/config/abi_prefix.hpp> 20 21 namespace boost 22 { 23 24 template <typename Stream, typename RecursiveMutex=recursive_mutex> 25 class externally_locked_stream; 26 27 template <class Stream, typename RecursiveMutex=recursive_mutex> 28 class stream_guard 29 { 30 31 friend class externally_locked_stream<Stream, RecursiveMutex> ; 32 public: 33 typedef typename externally_locked_stream<Stream, RecursiveMutex>::mutex_type mutex_type; 34 35 BOOST_THREAD_MOVABLE_ONLY( stream_guard) 36 stream_guard(externally_locked_stream<Stream,RecursiveMutex> & mtx)37 stream_guard(externally_locked_stream<Stream, RecursiveMutex>& mtx) : 38 mtx_(&mtx) 39 { 40 mtx.lock(); 41 } 42 stream_guard(externally_locked_stream<Stream,RecursiveMutex> & mtx,adopt_lock_t)43 stream_guard(externally_locked_stream<Stream, RecursiveMutex>& mtx, adopt_lock_t) : 44 mtx_(&mtx) 45 { 46 } 47 stream_guard(BOOST_THREAD_RV_REF (stream_guard)rhs)48 stream_guard(BOOST_THREAD_RV_REF(stream_guard) rhs) BOOST_NOEXCEPT 49 : mtx_(rhs.mtx_) 50 { 51 rhs.mtx_= 0; 52 } 53 ~stream_guard()54 ~stream_guard() 55 { 56 if (mtx_ != 0) mtx_->unlock(); 57 } 58 owns_lock(const mutex_type * l) const59 bool owns_lock(const mutex_type * l) const BOOST_NOEXCEPT 60 { 61 return l == mtx_->mutex(); 62 } 63 64 /** 65 * @Requires mtx_ 66 */ get() const67 Stream& get() const 68 { 69 BOOST_THREAD_ASSERT_PRECONDITION( mtx_, lock_error() ); 70 return mtx_->get(*this); 71 } bypass() const72 Stream& bypass() const 73 { 74 return get(); 75 } 76 77 78 private: 79 externally_locked_stream<Stream, RecursiveMutex>* mtx_; 80 }; 81 82 template <typename Stream, typename RecursiveMutex> 83 struct is_strict_lock_sur_parole<stream_guard<Stream, RecursiveMutex> > : true_type 84 { 85 }; 86 87 /** 88 * externally_locked_stream cloaks a reference to an stream of type Stream, and actually 89 * provides full access to that object through the get and set member functions, provided you 90 * pass a reference to a strict lock object. 91 */ 92 93 //[externally_locked_stream 94 template <typename Stream, typename RecursiveMutex> 95 class externally_locked_stream: public externally_locked<Stream&, RecursiveMutex> 96 { 97 typedef externally_locked<Stream&, RecursiveMutex> base_type; 98 public: 99 BOOST_THREAD_NO_COPYABLE( externally_locked_stream) 100 101 /** 102 * Effects: Constructs an externally locked object storing the cloaked reference object. 103 */ externally_locked_stream(Stream & stream,RecursiveMutex & mtx)104 externally_locked_stream(Stream& stream, RecursiveMutex& mtx) BOOST_NOEXCEPT : 105 base_type(stream, mtx) 106 { 107 } 108 hold()109 stream_guard<Stream, RecursiveMutex> hold() BOOST_NOEXCEPT 110 { 111 return stream_guard<Stream, RecursiveMutex> (*this); 112 } bypass() const113 Stream& bypass() const 114 { 115 stream_guard<Stream, RecursiveMutex> lk(*this); 116 return get(lk); 117 } 118 }; 119 //] 120 121 template <typename Stream, typename RecursiveMutex, typename T> operator <<(const stream_guard<Stream,RecursiveMutex> & lck,T arg)122 inline const stream_guard<Stream, RecursiveMutex>& operator<<(const stream_guard<Stream, RecursiveMutex>& lck, T arg) 123 { 124 lck.get() << arg; 125 return lck; 126 } 127 128 template <typename Stream, typename RecursiveMutex> operator <<(const stream_guard<Stream,RecursiveMutex> & lck,Stream & (* arg)(Stream &))129 inline const stream_guard<Stream, RecursiveMutex>& operator<<(const stream_guard<Stream, RecursiveMutex>& lck, Stream& (*arg)(Stream&)) 130 { 131 lck.get() << arg; 132 return lck; 133 } 134 135 template <typename Stream, typename RecursiveMutex, typename T> operator >>(const stream_guard<Stream,RecursiveMutex> & lck,T & arg)136 inline const stream_guard<Stream, RecursiveMutex>& operator>>(const stream_guard<Stream, RecursiveMutex>& lck, T& arg) 137 { 138 lck.get() >> arg; 139 return lck; 140 } 141 142 template <typename Stream, typename RecursiveMutex, typename T> operator <<(externally_locked_stream<Stream,RecursiveMutex> & mtx,T arg)143 inline stream_guard<Stream, RecursiveMutex> operator<<(externally_locked_stream<Stream, RecursiveMutex>& mtx, T arg) 144 { 145 stream_guard<Stream, RecursiveMutex> lk(mtx); 146 mtx.get(lk) << arg; 147 return boost::move(lk); 148 } 149 150 template <typename Stream, typename RecursiveMutex> operator <<(externally_locked_stream<Stream,RecursiveMutex> & mtx,Stream & (* arg)(Stream &))151 inline stream_guard<Stream, RecursiveMutex> operator<<(externally_locked_stream<Stream, RecursiveMutex>& mtx, Stream& (*arg)(Stream&)) 152 { 153 stream_guard<Stream, RecursiveMutex> lk(mtx); 154 mtx.get(lk) << arg; 155 return boost::move(lk); 156 } 157 158 template <typename Stream, typename RecursiveMutex, typename T> operator >>(externally_locked_stream<Stream,RecursiveMutex> & mtx,T & arg)159 inline stream_guard<Stream, RecursiveMutex> operator>>(externally_locked_stream<Stream, RecursiveMutex>& mtx, T& arg) 160 { 161 stream_guard<Stream, RecursiveMutex> lk(mtx); 162 mtx.get(lk) >> arg; 163 return boost::move(lk); 164 } 165 166 } 167 168 #include <boost/config/abi_suffix.hpp> 169 170 #endif // header 171