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();
}
muduo库源码学习(base)AsyncLogging
最新推荐文章于 2022-11-21 08:25:26 发布