Notinlist
Notinlist

Reputation: 16640

Concurrent cout formatting

This is an academic question.

sdt::mutex m;
typedef std::lock_guard<std::mutex> G;

void thread1(){
  G g(m);       
  std::cout << std::setw(9);
  std::cout << 3.14;
  std::cout << std::endl;
}

void thread2(){
  G g(m);       
  std::cout << std::setw(7);
  std::cout << 3.14;
  std::cout << std::endl;
}

My problem is that the formatting is bound to the output stream, so I need to set all the formatting options ever invented on my thread if I want to be sure about the output I produce. Which will or will not work next year.

Upvotes: 2

Views: 153

Answers (1)

Richard Hodges
Richard Hodges

Reputation: 69882

I've used boost for brevity but you could write your own optional and state saver.

#include <mutex>
#include <iostream>
#include <iomanip>
#include <tuple>
#include <utility>
#include <boost/io/ios_state.hpp>
#include <boost/optional.hpp>

std::mutex m;

struct save_and_lock
{
    boost::optional<boost::io::ios_all_saver> saver;
    std::unique_lock<std::mutex> lock;

    void init(std::ostream& os)
    {
        lock = std::unique_lock<std::mutex>(m);
        saver.emplace(os);
        os.flags(std::ios_base::fmtflags(0));
    }

    friend std::ostream& operator<<(std::ostream& os, save_and_lock&& s)
    {
        s.init(os);
        return os;
    }
};

void thread1(){
    std::cout << save_and_lock() << std::setw(9) << 3.14 << std::endl;
}

void thread2(){
    std::cout << save_and_lock() << std::setw(9) << 3.14 << std::endl;

}

This will work because the evaluation order of user-defined operator << is left to right.

Upvotes: 2

Related Questions