void AsyncLogging::threadFunc() { assert(running_ == true); latch_.countDown(); LogFile output(basename_, rollSize_, false); BufferPtr newBuffer1(new Buffer); BufferPtr newBuffer2(new Buffer); newBuffer1->bzero(); newBuffer2->bzero(); BufferVector buffersToWrite; buffersToWrite.reserve(16); while(running_) { assert(newBuffer1 && newBuffer1->length() == 0); assert(newBuffer2 && newBuffer2->length() == 0); assert(buffersToWrite.empty()); { dbdky::MutexLockGuard lock(mutex_); if (buffers_.empty()) { cond_.waitForSeconds(flushInterval_); } buffers_.push_back(currentBuffer_.release()); 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++) { output.append(buffersToWrite[i].data(), buffersToWrite[i].length()); } if (buffersToWrite.size() > 2) { 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(); }
void AsyncLogging::threadFunc() { assert(running_ == true); latch_.countDown(); LogFile output(basename_, rollSize_, false); //Important 这里的传入的threadsafe为false,为什么,因为异步本身就保证了线程安全 BufferPtr newBuffer1(new Buffer); BufferPtr newBuffer2(new Buffer); newBuffer1->bzeroinit(); newBuffer2->bzeroinit(); BufferVector buffersToWrite; buffersToWrite.reserve(16); while (running_) { { lock_guard_t lock(mutex_); //用来和生产者互斥 if (buffers_.empty()) //unsual usage,没有使用while循环 { cond_.wait(flushInterval_ * 1000);//flushInterval_是seconds } //执行到这里有2个条件:其一是超时,其二是写满了一个或多个buffer buffers_.push_back(currentBuffer_.release());//移动,而非复制 ,release类似std::auto_ptr的release, 返回包含指针的地址,并将包含指针设为NUll currentBuffer_ = boost::ptr_container::move(newBuffer1);//移动,而非复制 buffersToWrite.swap(buffers_);//内部指针交换,而非复制 ,交换后,可在临界区外安全地访问buffersToWrite,将其中的日志数据写入文件 if (!nextBuffer_)//临界区最终干的一件事情是用newBuffer2替换nextBuffer_,这样前端始终有一个备用buffer,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(); //将buffer的指针指向头部 } if (!newBuffer2) { assert(!buffersToWrite.empty()); newBuffer2 = buffersToWrite.pop_back(); newBuffer2->reset(); } buffersToWrite.clear(); output.flush(); } output.flush(); }