• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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