#include #include #include #include #include namespace a8 { struct JsonLogMsgNode { a8::XObject* xobj = nullptr; JsonLogMsgNode* next = nullptr; }; struct JsonLogImpl { std::string log_filename; std::thread* save_thread = nullptr; bool save_thread_shutdown = false; std::mutex msg_mutex; JsonLogMsgNode* top_node = nullptr; JsonLogMsgNode* bot_node = nullptr; JsonLogMsgNode* work_node = nullptr; std::mutex *save_cond_mutex = nullptr; std::condition_variable *save_cond = nullptr; }; JsonLog::JsonLog() { impl_ = new a8::JsonLogImpl(); impl_->save_cond_mutex = new std::mutex(); impl_->save_cond = new std::condition_variable(); impl_->top_node = nullptr; impl_->bot_node = nullptr; impl_->work_node = nullptr; } JsonLog::~JsonLog() { delete impl_->save_cond_mutex; impl_->save_cond_mutex = nullptr; delete impl_->save_cond; impl_->save_cond = nullptr; delete impl_; impl_ = nullptr; } void JsonLog::Init() { impl_->save_thread_shutdown = false; impl_->save_thread = new std::thread(&JsonLog::SaveToFileThreadProc, this); } void JsonLog::UnInit() { impl_->save_thread_shutdown = true; impl_->save_thread->join(); delete impl_->save_thread; impl_->save_thread = nullptr; } void JsonLog::SetLogFileName(const std::string& filename) { impl_->log_filename = filename; } void JsonLog::AddLog(a8::XObject* xobj) { JsonLogMsgNode *p = new JsonLogMsgNode(); p->xobj = xobj; impl_->msg_mutex.lock(); if (impl_->bot_node) { impl_->bot_node->next = p; impl_->bot_node = p; } else { impl_->top_node = p; impl_->bot_node = p; } impl_->msg_mutex.unlock(); { std::unique_lock lk(*impl_->save_cond_mutex); impl_->save_cond->notify_all(); } } void JsonLog::SaveToFileThreadProc() { while (!impl_->save_thread_shutdown) { if (!impl_->work_node && impl_->top_node) { impl_->msg_mutex.lock(); impl_->work_node = impl_->top_node; impl_->top_node = nullptr; impl_->bot_node = nullptr; impl_->msg_mutex.unlock(); } if (impl_->work_node) { time_t nowtime = time(nullptr); struct tm tm_nowtime = {0}; localtime_r(&nowtime, &tm_nowtime); char szfilename[256]; strftime(szfilename, a8::ArraySize(szfilename), impl_->log_filename.c_str(), &tm_nowtime); std::string filename((char*)szfilename); FILE *logfile = fopen(filename.c_str(), "a+"); if (logfile) { while (impl_->work_node) { JsonLogMsgNode *nextnode = impl_->work_node->next; std::string logmsg; impl_->work_node->xobj->ToJsonStr(logmsg); logmsg.push_back('\n'); fwrite(logmsg.c_str(), 1, logmsg.size(), logfile); delete impl_->work_node->xobj; delete impl_->work_node; impl_->work_node = nextnode; } fclose(logfile); } } { std::unique_lock lk(*impl_->save_cond_mutex); impl_->save_cond->wait_for(lk, std::chrono::seconds(10)); } } } }