日志操作大致分为两种(本人拙见):
A 插入日志,实时写入到文件(好处:实时保存了程序的运行信息,不便之处对于高并发的网络操作则严重影响IO性能)
B 前端只管往日志容器(暂定为list)添加日志信息,后端开启工作线程,不断从容器内取出信息,写入到文件。(好处:读写分离能较高适应高并发环境的io操作,不便之处:程序意外宕机,还缓存在容器中的日志无法写入到文件内)
具体情况,具体分析,对于工业自动化控制设备,以及流程比较重要的软件来说,方法A是比较好的,当然,对于大型服务器框架来说,B是更好的选择。
下面代码仅仅是简单演示下B方法的流程设计,才能有限,未能考虑其他方面的知识。
class Logger;提供日志标准输出以及文件输出(转载于网络大神)
class CLog ;提供日志容器主线程写入操作,工作线程读取容器操作。
void handle_work( ); //工作函数,从list列表中取出数据输出
typedef list<std::string> LISTLOG;
LISTLOG m_list_log; //日志容器
bool m_bExit;
boost::mutex _mutex;//用于日志容器锁
boost::mutex _io_mutex;//标准输出流/文件锁
boost::thread_group _group_threads; //boost线程组
int n_un_read; //未能读取日志数量
int n_capacity; //定义日志存储容量
boost::condition_variable_any cond_not_empty, cond_not_full; //list容器未空,未满条件变量
bool is_full(){return n_un_read == n_capacity;}
bool is_empty(){return n_un_read == 0;}
主线程插入操作
bool CLog::insertLog(boost::string_ref strLog)
{
std::string strInfo = boost::posix_time::to_iso_string(microsec_clock::universal_time() + hours(8));
int pos = strInfo.find('T');
strInfo.replace(pos,1,std::string("-"));
strInfo.replace(pos + 3,0,std::string(":"));
strInfo.replace(pos + 6,0,std::string(":"));
strInfo += ":"; //格式化时间
strInfo = strInfo + strLog.to_string(); //格式化时间+内容
{
boost::mutex::scoped_lock lock(_mutex); //局部域锁
while(is_full()) //判断日志容器是否已满
{
cond_not_full.wait(_mutex); //等待容器未满信号
}
m_list_log.push_back(strInfo); //写入log容器
++n_un_read;
}
cond_not_empty.notify_one(); //通知容器已不为空信号
return true;
}
读取日志容器操作
void CLog::handle_work()
{
while(! m_bExit)
{
std::string strLog;
{
boost::mutex::scoped_lock lock(_mutex); //局部域锁
while(is_empty())
{
cond_not_empty.wait(_mutex);
}
boost::this_thread::sleep(boost::posix_time::microsec(1)); //延时1ms,此处也可作为外部操作该线程中断(Interrupt)
--n_un_read;
if(!is_full())
cond_not_full.notify_one();
strLog = m_list_log.front();
m_list_log.pop_front();
}
//cout<<strLog<<endl;
if(strLog.size() != 0)
{
boost::mutex::scoped_lock lock(_io_mutex); //输出流也需要锁来保护
LOG(INFO)<<strLog<<endl;
}
}
初始化线程组
void CLog::init(int nThreads)
{
for (int i = 0; i < nThreads; i++)
{
boost::function0< void> fun = boost::bind(&CLog::handle_work,this);
_group_threads.create_thread(fun);
}
测试:简单写入10000条信息。
CLog log(10);//日志容器为10
for (int i =0; i < 10000; i++)
{
string s = boost::lexical_cast<string>(i);
log.insertLog(s);
boost::this_thread::sleep(boost::posix_time::microsec(1));
}
结构大体如上,只是简单演示下流程。
考虑不周的请大神多多指点。