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