Multithreading C++;使用互斥锁锁定流运算符

Multithreading C++;使用互斥锁锁定流运算符,multithreading,c++11,logging,stdout,mutex,Multithreading,C++11,Logging,Stdout,Mutex,我需要在我的日志应用程序中锁定stdout,以防止多线程应用程序在日志记录到stdout时出现字符串交错。无法理解如何使用move构造函数或std::move或其他方法将唯一锁定移动到另一个对象 我创建了用于设置配置和封装的对象,并了解了如何使用静态std::mutex锁定stdout,以从这些对象(称为碎片)锁定 类似这样的东西对我很有用: l->log(1, "Test message 1"); 虽然这很好,并且可以通过模板和可变数量的参数来实现,但我想探讨更多类似流的可能性。我在找

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

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

类似这样的东西对我很有用:

l->log(1, "Test message 1");
虽然这很好,并且可以通过模板和可变数量的参数来实现,但我想探讨更多类似流的可能性。我在找这样的东西:

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

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

您需要的是在创建流时锁定一些“输出锁”,并在流被破坏时解锁它。如果您只是包装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;
}
#包括
#包括
类锁定流
{
静态std::互斥体s_out_互斥体;
std::唯一锁;
std::ostream*stream\u;//无法进行此引用,因此我们可以移动
公众:
锁定的_流(标准::ostream&stream)
:锁定(s\U out\U互斥)
,流(和流)
{ }
锁定的\u流(锁定的\u流和其他)
:lock_(std::move(other.lock_))
,stream_u2;(其他.stream_2;)
{
other.stream uz=nullptr;
}

friend locked_stream&&operator不确定是否会欣赏该评论,但在这种情况下,我会做的是将日志记录卸载到另一个线程上。日志记录线程将在不带任何锁的情况下写入标准输出,而其他线程可以通过无锁队列发送消息。这样可以减少争用,提高吞吐量,并且不需要使用任何锁通过流操作编织锁。不管怎样,我都会添加一个答案。我非常感谢!我会尝试将您的答案与现有代码合并,但会记住您的建议!以后不妨尝试以这种方式重写它。
#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;
}