# FBB::OMutexStream(3bobcat)

## Mutex protected std::ostream
(libbobcat-dev_6.06.02)

## 2005-2024

## NAME

FBB::OMutexStream - Offers mutex protected std::ostream facilities

## SYNOPSIS

#include <bobcat/omutexstream>
Linking option: -lbobcat

## DESCRIPTION

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.

OMutexStream supports writing to output streams while handling the mutex locks. The OMutexStream object itself is initialized with the std::ostream object to receive the information written to the OMutexStream object. This object, like std::cout and std::err usually is defined as a globally accessible object. When inserting information into the OMutexStream object OMutexStream first returns an OMutexStream::Out object, whose constructor locks the OMutexStream::Out mutex. The OMutexStream::Out object's lifetime ends at the end of the insertion statement, and at that time its destructor releases the lock.

In many cases this is appropriate. Especially when statements end in newlines ('\n' or endl) this results in clean output. In some cases this approach doesn't work. Consider the situation where the output is produced by a series of iterations in a for-statement. For these cases OMutexStream offers the member ostream returning an OMutexStream::Out object. As that object also locks the mutex, the lock also remains active during its lifetime. During its lifetime separate OMutexStream insertions expressions may be executed. E.g., the following code fragment will complete all output forcing competing threads to wait:

        void fun()
        {
            OMutexStream mout{ std::cout }; // create an OMutexStream object
            {
                auto out{ mout.ostream() }  // locks the mutex (lock #1)
                mout << "Hello ";           // also locks (lock #2, at ;
                                            //             back to lock #1)
                out << "world\n";
            }                               // 'out' releases the lock
        }

Be careful to restrict the lifetime of the object returned by OMutexStream::ostream().

## NAMESPACE

FBB
All constructors, members, operators and manipulators, mentioned in this man-page, are defined in the namespace FBB.

## INHERITS FROM

(via OMutexStream::Out) std::ostream

## CONSTRUCTORS

- OMutexStream(std::ostream &out):
  The OMutexStream object is initialized with an std::ostream object.

Copy and move constructors (and assignment operators) are available.

## OVERLOADED OPERATORS

- OMutexStream::Out operator<<(OMutexStream const &mstr, Tp &&tp):
  This member is a function template. Its forwarding reference is passed on to the OMutexStream::Out object constructed by mstr. Since OMutexStream::Out constructors lock the class's mutex, and since OMutexStream::Out was derived from std::ostream all insertion and other operations that are allowed for std::ostream can also be used for OMutexStream::Out objects.

- OMutexStream::Out operator<<(OMutexStream const &mstr, Ret &(*manip)(Ret &os)):
  This member also is a function template. It is used for inserting manipulators without arguments into OMutexStream::Out objects.

## MEMBER FUNCTIONS

- OMutexStream::Out ostream() const:
  A OMutexStream::Out object is returned that has locked its mutex, and will keep the lock during its lifetime. All functionality of the std::ostream class can also be used for the OMutexStream::Out object returned by ostream.

  Be careful to restrict the lifetime of the object returned by OMutexStream::ostream() to avoid needlessly long mutex locks.

## EXAMPLE

    #include <iostream>
    #include <thread>
    #include <chrono>
    #include <cstdlib>
    #include <cmath>
    #include <ctime>

    #include <bobcat/omutexstream>

    using namespace std;
    using namespace FBB;

    OMutexStream mout(cout);

    void run(int nr)
    {
        for (size_t idx = 0; idx != 3; ++idx)
        {
            mout << "hello world 1 from thread " << nr << ": " <<
                    log(rand()) << endl;

            this_thread::sleep_for(
                    chrono::milliseconds(200 + rand() % 800));

           mout << "hello world 2 from thread " << nr << ": " <<
                    log(rand()) << '\n';

            this_thread::sleep_for(
                    chrono::milliseconds(200 + rand() % 800));
        }

        auto out{ mout.ostream() };
        cout << nr << ": " << out.tellp() << '\n';
    }

    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();
    }

## FILES

bobcat/omutexstream - defines the class interface

## SEE ALSO

bobcat(7)

## BUGS

None Reported.

## BOBCAT PROJECT FILES

- https://fbb-git.gitlab.io/bobcat/: gitlab project page;
- bobcat_6.06.02-x.dsc: detached signature;
- bobcat_6.06.02-x.tar.gz: source archive;
- bobcat_6.06.02-x_i386.changes: change log;
- libbobcat1_6.06.02-x_*.deb: debian package containing the libraries;
- libbobcat1-dev_6.06.02-x_*.deb: debian package containing the libraries, headers and manual pages;

## BOBCAT

Bobcat is an acronym of `Brokken's Own Base Classes And Templates'.

## COPYRIGHT

This is free software, distributed under the terms of the GNU General Public License (GPL).

## AUTHOR

Frank B. Brokken (f.b.brokken@rug.nl).