2

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

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

};

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

4

4 回答 4

7

通常的方式,使用互斥锁:

#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.
};
于 2013-02-18T08:26:16.883 回答
3

短版:写一个同步的包装器, wrap std::cout,然后使用 synchronizedcout来写。

长版:

#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;

};

(从Herb偷来的。以上任何错误都是我自己的,不是 Herb 的。)

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

于 2013-02-18T15:15:03.130 回答
2

最简单的方法:

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;
};
于 2013-02-18T08:28:18.917 回答
0
//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;
}
于 2013-12-27T06:11:30.637 回答