multithreading - C++ 使用互斥量锁定流运算符

标签 multithreading c++11 logging stdout mutex

我需要在我的日志记录应用程序中锁定标准输出,以防止在记录到标准输出的多线程应用程序中出现字符串交错。无法弄清楚如何使用移动构造函数或 std::move 或其他方式将 unique_lock 移动到另一个对象。

我创建了用于设置配置和封装的对象,并想出了如何使用静态 std::mutex 锁定 stdout 以锁定这些对象(称为分片)。

这样的东西对我有用:

l->log(1, "Test message 1");

虽然这很好并且可以使用模板和可变数量的参数来实现,但我想接近更多类似流的可能性。我正在寻找这样的东西:

*l << "Module id: " << 42 << "value: " << 42 << std::endl;

我不想强制用户使用连接和 to_string(42) 预先计算字符串,我只是想找到一种方法来锁定标准输出。

到目前为止,我的方法是创建运算符 << 和另一个对象锁定流,正如其他答案中所建议的那样。事情是我不知道如何将互斥体移动到另一个对象。我的代码:

locked_stream& shard::operator<<(int num)
{
    static std::mutex _out_mutex;
    std::unique_lock<std::mutex> lock(_out_mutex);
    //std::lock_guard<std::mutex> lock (_out_mutex);
    std::cout << std::to_string(num) << "(s)";
    locked_stream s;
    return s;
}

在将输入输出到 std::cout 之后,我想将锁移动到对象流中。

最佳答案

在这种情况下,我会小心不要在函数中使用静态锁,因为您会为您创建的每个流运算符获得不同的锁。

您需要的是在流创建时锁定一些“输出锁”,并在流销毁时解锁。如果您只是包装 std::ostream,则可以利用现有的流操作。这是一个有效的实现:

#include <mutex>
#include <iostream>


class locked_stream
{
    static std::mutex s_out_mutex;

    std::unique_lock<std::mutex> lock_;
    std::ostream* stream_; // can't make this reference so we can move

public:
    locked_stream(std::ostream& stream)
        : lock_(s_out_mutex)
        , stream_(&stream)
    { }

    locked_stream(locked_stream&& other)
        : lock_(std::move(other.lock_))
        , stream_(other.stream_)
    {
        other.stream_ = nullptr;
    }

    friend locked_stream&& operator << (locked_stream&& s, std::ostream& (*arg)(std::ostream&))
    {
        (*s.stream_) << arg;
        return std::move(s);
    }

    template <typename Arg>
    friend locked_stream&& operator << (locked_stream&& s, Arg&& arg)
    {
        (*s.stream_) << std::forward<Arg>(arg);
        return std::move(s);
    }
};

std::mutex locked_stream::s_out_mutex{};

locked_stream locked_cout()
{
    return locked_stream(std::cout);
}

int main (int argc, char * argv[])
{
    locked_cout() << "hello world: " << 1 << 3.14 << std::endl;
    return 0;
}

在 ideone 上:https://ideone.com/HezJBD

另外,请原谅,由于在线编辑器的笨拙,上面会混合使用空格和制表符。

关于multithreading - C++ 使用互斥量锁定流运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36439373/

相关文章:

c++ - 将提供 operator<< 的对象转换为 std::string 的标准库函数

c++ - 为什么从构造函数抛出异常时会发生内存泄漏?

c++ - C++ 中的 operator()() 是做什么的?

java - 如何读取 logback.xml 中的环境变量或属性并在每个日志行中打印该属性

java - 通过并发请求多次运行 JAR

Python threading.Thread 只能通过私有(private)方法 self.__Thread_stop() 停止

Python。如何重定向玛雅历史?

postgresql - Postgres 9.1 : Measure time taken for a transaction (including commit)

multithreading - 如何在主线程中等待,直到 Qt 中的所有工作线程都完成?

c# - 在启动 Windows 服务时,启动线程。我怎样才能做到这一点?