mat-tso / Thread_safe_stream

A thread safe c++ stream implementation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

The problem

The c++ Standard Template Library offers numerous great tools including streams. All basic objects can be inserted in an stream using the << operator or extracted with >>.

Here is an example of a program that prints "hello world":

cout << "Hello " << "world "

The problem is that if working in an multi thread environement, 2 thread could output in parallel. The following could happend: "Hello OUTPUT_FROM_AN_OTHER_THEAD world" instead of "Hello world OUTPUT_FROM_AN_OTHER_THEAD".

The solution

To prevent this the safeStream class implements a thread safe ostream. Use it as such:

SafeStream scout(cout);
// Then use scout to access to cout.
...
... span threads
...
// Open a session for your thread
scout << scout.begin;
// You are now garanty that any other thread will now wait for your session end
scout << "Hello " << "world ";
// Do not forget to close the session.
scout << scout.end;

A log class

Deriving the SafeStream class, the Log class offers a thread safe, stream orriented, way of logging. Create a logger by giving a stream and a line prefix to the Log constructor. Then define a macro as such:

Log logger(cerr, "Log");
#define LOG(...) logger, logger.begin , ##__VA_ARGS__ , logger.end

As the Log::operator, is just just forwarding to the SafeStream::operator<<, you just defined a pseudo type and number parameter varatic function! See the @ref LOGI macro in log.hpp for an example.

Note: Of course with c++11, and it's varatic templates (challenge breaker), defining such log(...) is easy peasy (tail recursion feels so good ;).

template<class... T> log(T...);
template<class H, class... T> log(H head, T... tail) {
    mutex.lockIfNotAlready();
    stream << head;
    log(tail...);
}
template<> log<>() {mutex.unlock();}

How to compile

Use the cmake build system.

# Move in the build folder to avoid messing up with the src files.
cd build
# Generate makefiles and build your executables.
cmake .. && make
# Check that all tests are passed.
make test

TODO list

  • Add a RAII class to encapsulate the need for begin and end (exception robusness). This would make the safe stream even safer at the cost of an object creation for each lock.
  • Allow stream manipulator (endl,...) to be used direcly.

About

A thread safe c++ stream implementation

License:MIT License


Languages

Language:C++ 100.0%