BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslstl_osyncstream.h
Go to the documentation of this file.
1/// @file bslstl_osyncstream.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslstl_osyncstream.h -*-C++-*-
8#ifndef INCLUDED_BSLSTL_OSYNCSTREAM
9#define INCLUDED_BSLSTL_OSYNCSTREAM
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslstl_osyncstream bslstl_osyncstream
15/// @brief Provide a C++20-compatible `basic_osyncstream` class template.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslstl
19/// @{
20/// @addtogroup bslstl_osyncstream
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslstl_osyncstream-purpose"> Purpose</a>
25/// * <a href="#bslstl_osyncstream-classes"> Classes </a>
26/// * <a href="#bslstl_osyncstream-description"> Description </a>
27/// * <a href="#bslstl_osyncstream-usage"> Usage </a>
28/// * <a href="#bslstl_osyncstream-example-1-using-osyncstream"> Example 1: Using osyncstream </a>
29///
30/// # Purpose {#bslstl_osyncstream-purpose}
31/// Provide a C++20-compatible @ref basic_osyncstream class template.
32///
33/// # Classes {#bslstl_osyncstream-classes}
34///
35/// - bsl::basic_osyncstream: C++20-compatible @ref basic_osyncstream class.
36/// - bsl::osyncstream: C++20-compatible `osyncstream` class.
37/// - bsl::wosyncstream: C++20-compatible `wosyncstream` class.
38///
39/// **Canonical header:** bsl_syncstream.h
40///
41/// @see bslstl_syncbuf
42///
43/// # Description {#bslstl_osyncstream-description}
44/// This component is for internal use only. Please include
45/// `<bsl_syncstream.h>` instead.
46///
47/// This component defines a class template, `bsl::basic_osyncstream`, that is a
48/// convenience wrapper for `bsl::basic_syncbuf`. It provides a mechanism to
49/// synchronize threads writing to the same stream, or more precisely, to the
50/// same `streambuf`. It's guaranteed that all output made to the same final
51/// destination buffer will be free of data races and will not be interleaved or
52/// garbled in any way, as long as every write to that final destination buffer
53/// is made through (possibly different) instances of `bsl::basic_syncbuf`.
54///
55/// Types `bsl::osyncstream` and `bsl::wosyncstream` are aliases for
56/// `bsl::basic_osyncstream<char>` and `bsl::basic_osyncstream<wchar_t>`,
57/// respectively.
58///
59/// ## Usage {#bslstl_osyncstream-usage}
60///
61///
62/// This section illustrates intended use of this component.
63///
64/// In a multi-threaded environment attempts to write from different threads to
65/// one `ostream` "may result in a data race", according to the ISO C++
66/// Standard. Concurrent access to the special synchronized iostream objects,
67/// like `cout`, `cerr`, etc, does not result in a data race, but output
68/// characters from one thread can interleave with the characters from other
69/// threads still. `osyncstream` solves both problems: prevents data races and
70/// characters interleaving.
71///
72/// ### Example 1: Using osyncstream {#bslstl_osyncstream-example-1-using-osyncstream}
73///
74///
75/// The following example demonstrates concurrent printing of a standard STL
76/// container of values that can be streamed out. The elements are separated by
77/// comma and the whole sequence is enclosed in curly brackets. Note that this
78/// example requires at least C++11.
79/// @code
80/// template <class t_CONTAINER>
81/// void printContainer(bsl::ostream& stream, const t_CONTAINER& container)
82/// // Print elements of the specified 'container' to the specified
83/// // 'stream' in a multi-threaded environment without interleaving with
84/// // output from another threads.
85/// {
86/// bsl::osyncstream out(stream);
87/// out << '{';
88/// bool first = true;
89/// for(auto& value : container) {
90/// if (first) {
91/// first = false;
92/// }
93/// else {
94/// out << ", ";
95/// }
96/// out << value;
97/// }
98/// out << '}';
99/// } // all output is atomically transferred to 'stream' on 'out' destruction
100/// @endcode
101/// Now this function can safely be used in a multi-threaded environment:
102/// @code
103/// int main()
104/// {
105/// bsl::vector<int> container1 = {1, 2, 3};
106/// bsl::vector<double> container2 = {4.0, 5.0, 6.0, 7.0};
107///
108/// bsl::thread thread1{[&]{ printContainer(bsl::cout, container1); }};
109/// bsl::thread thread2{[&]{ printContainer(bsl::cout, container2); }};
110/// thread1.join();
111/// thread2.join();
112/// }
113/// @endcode
114/// @}
115/** @} */
116/** @} */
117
118/** @addtogroup bsl
119 * @{
120 */
121/** @addtogroup bslstl
122 * @{
123 */
124/** @addtogroup bslstl_osyncstream
125 * @{
126 */
127
128#include <bslscm_version.h>
129
130#include <bslstl_syncbuf.h>
131
132#include <bsls_keyword.h>
133#include <bsls_libraryfeatures.h>
134
135#include <ostream>
136
137#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE
138#include <utility> // move
139#endif
140
141namespace bsl {
142
143 // =======================
144 // class basic_osyncstream
145 // =======================
146
147/// This class implements a standard output stream providing an internal
148/// buffer to accumulate the written data in order to atomically transmit
149/// its entire contents to the wrapped buffer on destruction (or `emit`
150/// call).
151///
152/// See @ref bslstl_osyncstream
153template <class CHAR_TYPE, class CHAR_TRAITS, class ALLOCATOR>
154class basic_osyncstream : public std::basic_ostream<CHAR_TYPE, CHAR_TRAITS> {
155
156 // PRIVATE TYPES
157 typedef std::basic_ostream<CHAR_TYPE, CHAR_TRAITS> Base;
158
159 public:
160 // TYPES
161 typedef CHAR_TYPE char_type;
162 typedef typename CHAR_TRAITS::int_type int_type;
163 typedef typename CHAR_TRAITS::pos_type pos_type;
164 typedef typename CHAR_TRAITS::off_type off_type;
165 typedef CHAR_TRAITS traits_type;
166 typedef ALLOCATOR allocator_type;
167
168 typedef std::basic_streambuf<CHAR_TYPE, CHAR_TRAITS> streambuf_type;
170
171 private:
172 // DATA
173 syncbuf_type d_syncbuf; // wrapped 'syncbuf'
174
175 public:
176 // CREATORS
177
178 /// Create a @ref basic_osycnstream object that will forward stream output
179 /// to the specified `wrapped` buffer. Optionally specify an
180 /// `allocator` used to supply memory. If `allocator` is not supplied,
181 /// a default-constructed object of the (template parameter) `ALLOCATOR`
182 /// type is used. If the `ALLOCATOR` argument is of type
183 /// `bsl::allocator` (the default), then `allocator`, if supplied, shall
184 /// be convertible to `bslma::Allocator *`. If the `ALLOCATOR` argument
185 /// is of type `bsl::allocator` and `allocator` is not supplied, the
186 /// currently installed default allocator will be used to supply memory.
187 explicit basic_osyncstream(streambuf_type *wrapped,
188 const ALLOCATOR& allocator = ALLOCATOR());
189
190 /// Create a @ref basic_osycnstream object that will forward stream output
191 /// to `rdbuf` of the specified `stream`. Optionally specify an
192 /// `allocator` used to supply memory. If `allocator` is not supplied,
193 /// a default-constructed object of the (template parameter) `ALLOCATOR`
194 /// type is used. If the `ALLOCATOR` argument is of type
195 /// `bsl::allocator` (the default), then `allocator`, if supplied, shall
196 /// be convertible to `bslma::Allocator *`. If the `ALLOCATOR` argument
197 /// is of type `bsl::allocator` and `allocator` is not supplied, the
198 /// currently installed default allocator will be used to supply memory.
200 std::basic_ostream<CHAR_TYPE, CHAR_TRAITS>& stream,
201 const ALLOCATOR& allocator = ALLOCATOR());
202
204 // Destroy this object.
205
206#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE
208
209 /// Create a @ref basic_osyncstream object having the same value as the
210 /// specified `original` object by moving the contents of `original` to
211 /// the newly-created object. Optionally specify an `allocator` used
212 /// to supply memory. `original.get_wrapped() == nullptr` after the
213 /// call.
215 const ALLOCATOR& allocator) BSLS_KEYWORD_NOEXCEPT;
216#endif
217
218 // MANIPULATORS
219#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE
220 /// Transfer the associated output to the wrapped stream buffer then
221 /// assign to this object the value of the specified `original`, and
222 /// return a reference providing modifiable access to this object. The
223 /// contents of `original` are move-assigned to this object.
224 /// `original.get_wrapped() == nullptr` after the call.
225 basic_osyncstream &operator=(basic_osyncstream&& original) = default;
226#endif
227
228 /// Atomically transfer any characters buffered by this object to the
229 /// wrapped stream buffer, so that it appears in the output stream as a
230 /// contiguous sequence of characters. If an error occurs, set the
231 /// `badbit` of the `rdstate` to `true`.
232 void emit();
233
234 // ACCESSORS
235
236 /// Return the allocator used to supply memory.
238
239 /// Return the wrapped buffer.
241
242 /// Return an address providing modifiable access to the @ref basic_syncbuf
243 /// object that is internally used by this stream object to buffer
244 /// unformatted characters.
246};
247
248// STANDARD TYPEDEFS
249typedef basic_osyncstream<char> osyncstream;
250typedef basic_osyncstream<wchar_t> wosyncstream;
251
252 // -----------------------
253 // class basic_osyncstream
254 // -----------------------
255
256// CREATORS
257template <class CHAR, class TRAITS, class ALLOCATOR>
258basic_osyncstream<CHAR,TRAITS,ALLOCATOR>::basic_osyncstream(
259 streambuf_type *wrapped,
260 const ALLOCATOR& allocator)
261:
262#ifndef BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD
263 // The Rogue Wave library used by Solaris does not correctly initialize the
264 // buffer pointer in the constructor for @ref basic_streambuf . As a result, on
265 // Solaris, we need to perform two-phase initialization using the
266 // 'basic_osyncstream::init' function instead.
267 Base(&d_syncbuf),
268#endif
269 d_syncbuf(wrapped, allocator)
270{
271#ifdef BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD
272 this->init(&d_syncbuf);
273#endif
274}
275
276template <class CHAR, class TRAITS, class ALLOCATOR>
278 std::basic_ostream<CHAR,TRAITS>& stream,
279 const ALLOCATOR& allocator)
280:
281#ifndef BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD
282 Base(&d_syncbuf),
283#endif
284 d_syncbuf(stream.rdbuf(), allocator)
285{
286#ifdef BSLS_LIBRARYFEATURES_STDCPP_LIBCSTD
287 this->init(&d_syncbuf);
288#endif
289}
290
291#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_STREAM_MOVE
292template <class CHAR, class TRAITS, class ALLOCATOR>
294 basic_osyncstream&& original) BSLS_KEYWORD_NOEXCEPT
295: Base(std::move(original))
296, d_syncbuf(std::move(original.d_syncbuf))
297{
298 this->set_rdbuf(&d_syncbuf);
299}
300
301template <class CHAR, class TRAITS, class ALLOCATOR>
303 basic_osyncstream&& original,
304 const ALLOCATOR& allocator) BSLS_KEYWORD_NOEXCEPT
305: Base(std::move(original))
306, d_syncbuf(std::move(original.d_syncbuf), allocator)
307{
308 this->set_rdbuf(&d_syncbuf);
309}
310#endif
311
312// MANIPULATORS
313template <class CHAR, class TRAITS, class ALLOCATOR>
315{
316 typename Base::sentry ok(*this);
317 if (!ok) {
318 this->setstate(ios_base::badbit);
319 }
320 else {
321 if (!d_syncbuf.emit()) {
322 this->setstate(ios_base::badbit);
323 }
324 }
325}
326
327// ACCESSORS
328template <class CHAR, class TRAITS, class ALLOCATOR>
329inline
335
336template <class CHAR, class TRAITS, class ALLOCATOR>
337inline
344
345template <class CHAR, class TRAITS, class ALLOCATOR>
346inline
349{
350 return const_cast<syncbuf_type*>(&d_syncbuf);
351}
352
353} // close namespace bsl
354
355#endif
356
357// ----------------------------------------------------------------------------
358// Copyright 2023 Bloomberg Finance L.P.
359//
360// Licensed under the Apache License, Version 2.0 (the "License");
361// you may not use this file except in compliance with the License.
362// You may obtain a copy of the License at
363//
364// http://www.apache.org/licenses/LICENSE-2.0
365//
366// Unless required by applicable law or agreed to in writing, software
367// distributed under the License is distributed on an "AS IS" BASIS,
368// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
369// See the License for the specific language governing permissions and
370// limitations under the License.
371// ----------------------------- END-OF-FILE ----------------------------------
372
373/** @} */
374/** @} */
375/** @} */
Definition bslma_bslallocator.h:580
Definition bslstl_osyncstream.h:154
basic_syncbuf< CHAR_TYPE, CHAR_TRAITS, ALLOCATOR > syncbuf_type
Definition bslstl_osyncstream.h:169
ALLOCATOR allocator_type
Definition bslstl_osyncstream.h:166
void emit()
Definition bslstl_osyncstream.h:314
basic_osyncstream(streambuf_type *wrapped, const ALLOCATOR &allocator=ALLOCATOR())
Definition bslstl_osyncstream.h:258
streambuf_type * get_wrapped() const BSLS_KEYWORD_NOEXCEPT
Return the wrapped buffer.
Definition bslstl_osyncstream.h:339
CHAR_TRAITS::off_type off_type
Definition bslstl_osyncstream.h:164
syncbuf_type * rdbuf() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_osyncstream.h:348
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used to supply memory.
Definition bslstl_osyncstream.h:330
CHAR_TRAITS::int_type int_type
Definition bslstl_osyncstream.h:162
CHAR_TRAITS traits_type
Definition bslstl_osyncstream.h:165
basic_osyncstream(std::basic_ostream< CHAR_TYPE, CHAR_TRAITS > &stream, const ALLOCATOR &allocator=ALLOCATOR())
~basic_osyncstream()=default
CHAR_TYPE char_type
Definition bslstl_osyncstream.h:161
std::basic_streambuf< CHAR_TYPE, CHAR_TRAITS > streambuf_type
Definition bslstl_osyncstream.h:168
CHAR_TRAITS::pos_type pos_type
Definition bslstl_osyncstream.h:163
Definition bslstl_syncbuf.h:152
bool emit()
Definition bslstl_syncbuf.h:372
allocator_type get_allocator() const BSLS_KEYWORD_NOEXCEPT
Return the allocator used to supply memory.
Definition bslstl_syncbuf.h:464
streambuf_type * get_wrapped() const BSLS_KEYWORD_NOEXCEPT
Return the wrapped buffer supplied at construction.
Definition bslstl_syncbuf.h:473
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
Definition bdlb_printmethods.h:283