线程安全流和流操纵器

Kir*_*han 2 c++ multithreading iostream

我正在尝试编写一个线程安全记录器类,以便我可以完成与cout完全相同但具有线程安全性.

这是记录器类(仍然在处理所需的锁类型)

class logger {

public:

    logger(LOGGER::output_type type);

    logger(const logger& orig);

    virtual ~logger();

    template <typename T>
    logger & operator << (const T & data){
        boost::mutex::scoped_lock io_mutex_lock(io_mutex);
        (*out)<<data;
        return *this;
    }

private:
    static boost::mutex io_mutex;
    std::ostream * out;

};
Run Code Online (Sandbox Code Playgroud)

问题是我无法做到以下几点

  1. log<<"asdfg";
    我不得不这样做
    log<<string("asdfg");

  2. int i = 10;
    log<<string ("i = ") << i << endl;

以下是编译错误.

gcc.compile.c++ src/simpleThread/bin/gcc-4.4.5/debug/simpleThread.o
src/simpleThread/simpleThread.cc: In function ‘int main()’:
src/simpleThread/simpleThread.cc:28: error: no match for ‘operator<<’ in ‘((logger*)logOut.logger::operator<< [with T = char [18]](((const char (&)[18])"fibonacci thread ")))->logger::operator<< [with T = int](((const int&)((const int*)(& i)))) << std::endl’
Run Code Online (Sandbox Code Playgroud)

所以我想我错过了一些重要的C++概念.请让我知道它是什么?我的要求是否可以实现

谢谢,Kiran

How*_*ant 5

请注意,您的记录器类仍然不是线程安全的:

int i = 10;
log <<string ("i = ") << i << endl;
Run Code Online (Sandbox Code Playgroud)

没有什么能阻止这个线程被另一个另一个线程打印到记录器并产生类似的东西:

i = i = 12
Run Code Online (Sandbox Code Playgroud)

代替:

i = 1
i = 2
Run Code Online (Sandbox Code Playgroud)

如果你有一个带可变参数模板的编译器,这里有一种解决方法:

#include <ostream>
#include <mutex>

inline void sub_print(std::ostream&) {}

template <class A0, class ...Args>
void
sub_print(std::ostream& os, const A0& a0, const Args& ...args)
{
    os << a0;
    sub_print(os, args...);
}

std::mutex&
io_mut()
{
    static std::mutex m;
    return m;
}

template <class ...Args>
void
log(std::ostream& os, const Args& ...args)
{
    std::lock_guard<std::mutex> _(io_mut());
    sub_print(os, args...);
    os.flush();
}

#include <iostream>

int main()
{
    int i = 10;
    log(std::cout, "i = ", i, '\n');
}
Run Code Online (Sandbox Code Playgroud)

即,互斥锁被锁定,直到处理给定日志消息的所有参数. std::endl通过在每条消息之后始终刷新流来单独处理.