在C++11中同步整个类

Synchronize entire class in C++11

本文关键字:同步 C++11      更新时间:2023-10-16

看看这个简单的日志记录类(这里只有相关部分):

class Logger {
public:
    void log(string& msg){
        //lock for all instances
        cout << "[" << tag << "] " << msg;
        //unlock
    }
private:
     string tag;
};

同步整个类(而不是实例)以便Logger的单独实例(在不同线程中)按顺序(而不是一次全部)写入cout的最简单方法是什么?

通常的方法,使用互斥:

#include <mutex>
class Logger {
public:
    void log(string& msg)
    {
        // Lock for all instances
        std::lock_guard<std::mutex> lock(coutMutex);
        cout << "[" << tag << "] " << msg;
        // Unlocking happens automatically since the lock
        // gets destroyed here.
    }
private:
    string tag;
    static std::mutex coutMutex; // Don't forget to define this somewhere.
};

短版本:编写一个同步的包装器,包装std::cout,然后使用同步的cout进行写入。

长版本:

#include <mutex>
template<typename T>
struct Synchronized {
  explicit Synchronized(T& t_):t(t_) {}
  template<typename Functor>
  auto operator()( Functor&& f ) const->decltype(f(t)) {
    std::lock_guard<std::mutex> guard(myMutex);
    return f(t);
  }
// I could implement these, but I'm lazy:
  Synchronized& operator=(Synchronized const&) = delete;
  Synchronized& operator=(Synchronized &&) = delete;
  Synchronized(Synchronized const&) = delete;
  Synchronized(Synchronized &&) = delete;
private:
  mutable T& t;
  mutable std::mutex myMutex;
};

// in "sync_cout.h"
extern Synchronized<std::ostream> sync_cout;
// in "sync_cout.cpp"
Synchronized<std::ostream> sync_cout(std::cout);
// In "logger.h"
// #include "sync_cout.h"
class Logger {
public:
  void log(string& msg){
    sync_cout( [&](std::ostream& os) {
      os << "[" << tag << "] " << msg;
    });
  }
private:
   string tag;
};

(从赫伯那里偷来的。上面的任何错误都是我自己的,而不是赫伯的。)

为了获得更高的性能,上面的链接还包括一个非阻塞异步包装器。

最简单的方法:

class Logger {
public:
   void log(std::string& msg){
   //lock for all instances
   {  std::unique_lock<std::mutex> locker(_mut); // or std::lock_guard<std::mutex> locker(_mut);
      std::cout << "[" << tag << "] " << msg;
   } //unlock
private:
   std::string tag;
   static std::mutex _mut;
};
//use c++ 11 mutex
class CircularQueue
{
protected:
    int * data;
    int head;
    int tail;
    int size;
    std::mutex queueMutex;
public:
    CircularQueue(void);
    int dequeue();
    void enqueue(int x);
    void initialize(int size);
    virtual ~CircularQueue(void);
};

CircularQueue::CircularQueue(void)
{
    data = 0x0;
    head = -1;
    tail = -1;
    size=0;
}
int CircularQueue::dequeue()
{
    if(tail == head)
    {
        throw "empty queue!";
    }
    std::lock_guard<std::mutex> lock(queueMutex);
    int result = data[head];
    head ++;
    if(head >= size) 
    {
        head =head % size;
    }
    return result;
}

void CircularQueue::enqueue(int x)
{
    std::lock_guard<std::mutex> lock(queueMutex);
    data[tail] = x;
    tail ++;
    if(tail >= size)
    {
        tail = tail % size;
    }
    if(tail == head)
    {
        throw "overflow!";
    }
}
void CircularQueue::initialize(int size)
{
    data = new int[size]; 
    head = 0;
    tail = 0;
    this->size = size;
}
CircularQueue::~CircularQueue(void)
{
    delete [] data;
}