muduo库源码学习(base)AsyncLogging

来源:互联网 发布:windows sdk编程是啥 编辑:程序博客网 时间:2024/05/22 05:24
class AsyncLogging: boost::noncopyable{public:  AsyncLogging(const string& basename,               size_t rollSize,//log文件临界大小,存下之后超出它的话,则滚动文件               int flushInterval = 3);//默认的后端写入时间间隔  ~AsyncLogging()  {    if (running_)//关闭log    {      stop();    }  }  void append(const char* logline, int len);//  void start()  {    running_ = true;//这里似乎有个错误,编译器。。。    thread_.start();//后端必须先开启    latch_.wait();  }  void stop()  {    running_ = false;    cond_.notify();    thread_.join();  } private:  // declare but not define, prevent compiler-synthesized functions  AsyncLogging(const AsyncLogging&);  // ptr_container  void operator=(const AsyncLogging&);  // ptr_container  void threadFunc();  typedef muduo::detail::FixedBuffer<muduo::detail::kLargeBuffer> Buffer;  typedef boost::ptr_vector<Buffer> BufferVector;//vector<uniqueptr>  typedef BufferVector::auto_type BufferPtr;//uniqueptr  const int flushInterval_;  bool running_;  string basename_;  size_t rollSize_;  muduo::Thread thread_;  muduo::CountDownLatch latch_;  muduo::MutexLock mutex_;  muduo::Condition cond_;  BufferPtr currentBuffer_;  BufferPtr nextBuffer_;  BufferVector buffers_;};AsyncLogging::AsyncLogging(const string& basename,                           size_t rollSize,                           int flushInterval)  : flushInterval_(flushInterval),    running_(false),    basename_(basename),    rollSize_(rollSize),    thread_(boost::bind(&AsyncLogging::threadFunc, this), "Logging"),    latch_(1),    mutex_(),    cond_(mutex_),    currentBuffer_(new Buffer),    nextBuffer_(new Buffer),    buffers_(){  currentBuffer_->bzero();  nextBuffer_->bzero();  buffers_.reserve(16);}void AsyncLogging::append(const char* logline, int len)//前端追加{  muduo::MutexLockGuard lock(mutex_);  if (currentBuffer_->avail() > len)//buffer1可写  {    currentBuffer_->append(logline, len);  }  else  {    buffers_.push_back(currentBuffer_.release());//buffer1读到容器    if (nextBuffer_)//buffer2可以写    {      currentBuffer_ = boost::ptr_container::move(nextBuffer_);//buffer2交换到1    }    else//说明buffer1被压入了容器,且buffer2之前已经给了1,那么干脆分配新缓冲    {      currentBuffer_.reset(new Buffer); // Rarely happens    }    currentBuffer_->append(logline, len);    cond_.notify();//通知后端写文件  }}void AsyncLogging::threadFunc()//后端线程{  assert(running_ == true);  latch_.countDown();//1个后端  LogFile output(basename_, rollSize_, false);  BufferPtr newBuffer1(new Buffer);  BufferPtr newBuffer2(new Buffer);  newBuffer1->bzero();  newBuffer2->bzero();  BufferVector buffersToWrite;  buffersToWrite.reserve(16);  while (running_)//每次循环都保证newbuffers是全新的  {    assert(newBuffer1 && newBuffer1->length() == 0);    assert(newBuffer2 && newBuffer2->length() == 0);    assert(buffersToWrite.empty());    {//似乎没办法用标准C++兼容现有代码      muduo::MutexLockGuard lock(mutex_);  //也就是说3秒之后不再检查buffer为空      if (buffers_.empty())  // unusual usage!      {        cond_.waitForSeconds(flushInterval_);      }      buffers_.push_back(currentBuffer_.release());//currentBufferr进入容器      currentBuffer_ = boost::ptr_container::move(newBuffer1);//      buffersToWrite.swap(buffers_);      if (!nextBuffer_)      {        nextBuffer_ = boost::ptr_container::move(newBuffer2);      }    }    assert(!buffersToWrite.empty());    if (buffersToWrite.size() > 25)    {      char buf[256];      snprintf(buf, sizeof buf, "Dropped log messages at %s, %zd larger buffers\n",               Timestamp::now().toFormattedString().c_str(),               buffersToWrite.size()-2);      fputs(buf, stderr);      output.append(buf, static_cast<int>(strlen(buf)));      buffersToWrite.erase(buffersToWrite.begin()+2, buffersToWrite.end());    }    for (size_t i = 0; i < buffersToWrite.size(); ++i)    {      // FIXME: use unbuffered stdio FILE ? or use ::writev ?      output.append(buffersToWrite[i].data(), buffersToWrite[i].length());    }    if (buffersToWrite.size() > 2)    {      // drop non-bzero-ed buffers, avoid trashing      buffersToWrite.resize(2);    }    if (!newBuffer1)    {      assert(!buffersToWrite.empty());      newBuffer1 = buffersToWrite.pop_back();      newBuffer1->reset();    }    if (!newBuffer2)    {      assert(!buffersToWrite.empty());      newBuffer2 = buffersToWrite.pop_back();      newBuffer2->reset();    }    buffersToWrite.clear();    output.flush();  }  output.flush();}

 
原创粉丝点击