.TH "FBB::OMutexStream" "3bobcat" "2005\-2020" "libbobcat\-dev_5\&.07\&.00" "Mutex protected std::ostream" .PP .SH "NAME" FBB::OMutexStream \- Offers mutex protected std::ostream facilities .PP .SH "SYNOPSIS" \fB#include \fP .br Linking option: \fI\-lbobcat\fP .PP .SH "DESCRIPTION" .PP In multi\-threaded programs output written by different threads to the same output stream may be intermixed due to context switches\&. This is prevented by using mutexes: before writing to the output stream a mutex lock is acquired, releasing the lock once the output is completed\&. .PP \fIOMutexStream\fP supports writing to output streams while handling the mutex locks\&. The \fIOMutexStream\fP object itself is initialized with the \fIstd::ostream\fP object to receive the information written to the \fIOMutexStream\fP object\&. This object, like \fIstd::cout\fP and \fIstd::err\fP usually is defined as a globally accessible object\&. When inserting information into the \fIOMutexStream\fP object \fIOMutexStream\fP first returns an \fIOMutexStream::Out\fP object, whose constructor locks the \fIOMutexStream::Out\fP mutex\&. The \fIOMutexStream::Out\fP object\(cq\&s lifetime ends at the end of the insertion statement, and at that time its destructor releases the lock\&. .PP In many cases this is appropriate\&. Especially when statements end in newlines (\fI\(cq\&\en\(cq\&\fP or \fIendl\fP) this results in clean output\&. In some cases this approach doesn\(cq\&t work\&. Consider the situation where the output is produced by a series of iterations in a \fIfor\fP\-statement\&. For these cases \fIOMutexStream\fP offers the member \fIostream\fP returning an \fIOMutexStream::Out\fP object\&. As that object also locks the mutex, the lock also remains active during its lifetime\&. During its lifetime separate \fIOMutexStream\fP insertions expressions may be executed\&. E\&.g\&., the following code fragment will complete all output forcing competing threads to wait: .nf void fun() { OMutexStream mout{ std::cout }; // create an OMutexStream object { auto out{ mout\&.ostream() } // locks the mutex (lock #1) mout << \(dq\&Hello \(dq\&; // also locks (lock #2, at ; // back to lock #1) out << \(dq\&world\en\(dq\&; } // \(cq\&out\(cq\& releases the lock } .fi Be careful to restrict the lifetime of the object returned by \fIOMutexStream::ostream()\fP\&. .PP .SH "NAMESPACE" \fBFBB\fP .br All constructors, members, operators and manipulators, mentioned in this man\-page, are defined in the namespace \fBFBB\fP\&. .PP .SH "INHERITS FROM" (via \fIOMutexStream::Out\fP) \fIstd::ostream\fP .PP .SH "CONSTRUCTORS" .IP o \fBOMutexStream(std::ostream &out)\fP: .br The \fIOMutexStream\fP object is initialized with an \fIstd::ostream\fP object\&. .PP Copy and move constructors (and assignment operators) are available\&. .PP .SH "OVERLOADED OPERATORS" .IP o \fBOMutexStream::Out operator<<(OMutexStream const &mstr, Tp &&tp)\fP: .br This member is a function template\&. Its forwarding reference is passed on to the \fIOMutexStream::Out\fP object constructed by \fImstr\fP\&. Since \fIOMutexStream::Out\fP constructors lock the class\(cq\&s mutex, and since \fIOMutexStream::Out\fP was derived from \fIstd::ostream\fP all insertion and other operations that are allowed for \fIstd::ostream\fP can also be used for \fIOMutexStream::Out\fP objects\&. .IP .IP o \fBOMutexStream::Out operator<<(OMutexStream const &mstr, Ret &(*manip)(Ret &os))\fP: .br This member also is a function template\&. It is used for inserting manipulators without arguments into \fIOMutexStream::Out\fP objects\&. .PP .SH "MEMBER FUNCTIONS" .IP o \fBOMutexStream::Out ostream() const\fP: .br A \fIOMutexStream::Out\fP object is returned that has locked its mutex, and will keep the lock during its lifetime\&. All functionality of the \fIstd::ostream\fP class can also be used for the \fIOMutexStream::Out\fP object returned by \fIostream\fP\&. .IP Be careful to restrict the lifetime of the object returned by \fIOMutexStream::ostream()\fP to avoid needlessly long mutex locks\&. .PP .SH "EXAMPLE" .nf #include #include #include #include #include #include #include using namespace std; using namespace FBB; OMutexStream mout(cout); void run(int nr) { for (size_t idx = 0; idx != 3; ++idx) { mout << \(dq\&hello world 1 from thread \(dq\& << nr << \(dq\&: \(dq\& << log(rand()) << endl; this_thread::sleep_for( chrono::milliseconds(200 + rand() % 800)); mout << \(dq\&hello world 2 from thread \(dq\& << nr << \(dq\&: \(dq\& << log(rand()) << \(cq\&\en\(cq\&; this_thread::sleep_for( chrono::milliseconds(200 + rand() % 800)); } auto out{ mout\&.ostream() }; cout << nr << \(dq\&: \(dq\& << out\&.tellp() << \(cq\&\en\(cq\&; } int main() { srand(time(0)); thread t1(run, 1); thread t2(run, 2); thread t3(run, 3); thread t4(run, 4); t1\&.join(); t2\&.join(); t3\&.join(); t4\&.join(); } .fi .PP .SH "FILES" \fIbobcat/omutexstream\fP \- defines the class interface .PP .SH "SEE ALSO" \fBbobcat\fP(7) .PP .SH "BUGS" None Reported\&. .PP .SH "BOBCAT PROJECT FILES" .PP .IP o \fIhttps://fbb\-git\&.gitlab\&.io/bobcat/\fP: gitlab project page; .IP o \fIbobcat_5\&.07\&.00\-x\&.dsc\fP: detached signature; .IP o \fIbobcat_5\&.07\&.00\-x\&.tar\&.gz\fP: source archive; .IP o \fIbobcat_5\&.07\&.00\-x_i386\&.changes\fP: change log; .IP o \fIlibbobcat1_5\&.07\&.00\-x_*\&.deb\fP: debian package containing the libraries; .IP o \fIlibbobcat1\-dev_5\&.07\&.00\-x_*\&.deb\fP: debian package containing the libraries, headers and manual pages; .PP .SH "BOBCAT" Bobcat is an acronym of `Brokken\(cq\&s Own Base Classes And Templates\(cq\&\&. .PP .SH "COPYRIGHT" This is free software, distributed under the terms of the GNU General Public License (GPL)\&. .PP .SH "AUTHOR" Frank B\&. Brokken (\fBf\&.b\&.brokken@rug\&.nl\fP)\&. .PP