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