饭后温柔

汉堡与老干妈同嚼 有可乐味
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

整理:一个简单的基于策略的多线程logsystem(3)

Posted on 2011-09-13 17:22  饭后温柔  阅读(425)  评论(0编辑  收藏  举报

      最后一个步骤是实现LogItem的集合,使用list实现。做的很简单,需要注意的是写入流(console或文件)这里尚未使用策略模板参数,而是是使用了一个静态类LogOutputPolicy,并且实际上也不该在LogQueue里使用它,应该在LogManager里使用较好。这里有些懒惰了,主要LogManager参数过多。

先看LogOutputPolicy的代码:

View Code
#ifndef __LogOutputPolicy_H__
#define __LogOutputPolicy_H__

#include
"stdafx.h"
#include
"LogConfigMacro.h"
#include
"loki/Threads.h"

using namespace std;

template
<
int ModuleID, class ItemType,
bool ToConsole = WRITE_TO_CONSOLE, bool ToFile = WRITE_TO_FILE,
template
<class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL,
class MutexPolicy = LOKI_DEFAULT_MUTEX
>
class LogOutputPolicy
{
public:
typedef LogOutputPolicy
<ModuleID, ItemType, ToConsole, ToFile, ThreadingModel, MutexPolicy> MyLogOutputPolicy;
//typename typedef ThreadingModel<MyLogOutputPolicy, MutexPolicy>::Lock Lock;

private:
static fstream ofile;

public:
static void openLog(DWORD id)
{
//Lock gurad;
if(ToFile)
{
char name[64];
sprintf_s(name,
64, "../thread_id(%d).txt", id);
ofile.open(name, ios_base::app);
}
}

static void closeLog()
{
//Lock gurad;
if(ToFile)
ofile.close();
}

static void writeLog(ItemType& item, DWORD id)
{
//Lock gurad;
if(ToConsole)
cout
<< item;
if(ToFile)
ofile
<< item;
}
};

template
<
int ModuleID, class ItemType,
bool ToConsole , bool ToFile,
template
<class, class> class ThreadingModel,
class MutexPolicy
>
fstream LogOutputPolicy
<ModuleID, ItemType, ToConsole, ToFile, ThreadingModel, MutexPolicy>::ofile;

#endif

  你希望怎么更改输出格式,输出窗口都可在LogOutputPolicy里定义。LogOutputPolicy你当然也可以实现自己的策略扩展,例如多个console窗口的选择,只是一个示例。

      LogQueue代码简单,std的2个list作为logitem的容器,有自己的字符缓冲区一个LogItem类型的buffer。这个buffer是可以在LogManager里实现的,那样的话加锁很麻烦,已经解释过logx宏非原子操作。这里迫不得已在LogQueue里实现它。虽然感觉有些破坏结构,但仍有一些方便。

View Code
#ifndef __LogQueue_H__
#define __LogQueue_H__

#include
"loki/Threads.h"
#include
"LogOutputPolicy.h"

using namespace std;//为示例方便,直接使用std名字空间

template
<
int ModuleID,
class ItemType_,
size_t QueueSize_
= 128
>
class LogQueue : public LOKI_DEFAULT_THREADING< LogQueue<ModuleID, ItemType_, QueueSize_>, LOKI_DEFAULT_MUTEX >
{
public:
typedef ItemType_ ItemType;
typedef LogQueue
<ModuleID, ItemType_, QueueSize_> QueueType;

private:
list
<ItemType*> m_freeLogQueue;
list
<ItemType*> m_usedLogQueue;

DWORD m_id;

ItemType m_buffer;

public:
LogQueue
<ModuleID, ItemType_, QueueSize_>(DWORD id):m_id(id) { init(); }
~LogQueue<ModuleID, ItemType_, QueueSize_>() { releaseQueue(); }

void pushString(const char* str)
{
//Lock guard(this);
ItemType* item = getItem();
assert(item);
(
*item) << str;
pushItem(item);
}

void pushItem(ItemType* item)
{
//Lock guard(this);
m_usedLogQueue.push_back(item);
}

ItemType
* getItem()
{
//Lock guard(this);
while(m_freeLogQueue.empty())
resizeQueue(QueueSize_);
ItemType
* item = m_freeLogQueue.front();
m_freeLogQueue.pop_front();
return item;
}

void dispatchBuffer()
{
if( m_buffer.empty() )
return;

ItemType
* item = getItem();
assert(item);
*item = m_buffer;
m_buffer.reset();
pushItem(item);
}

template
<class T>
QueueType
& operator << (const T& t)
{
m_buffer
<< t;
return *this;
}

void pumpQueue()
{
//Lock guard(this);
LogOutputPolicy<ModuleID, ItemType>::openLog(m_id);
while( !m_usedLogQueue.empty() )
{
LogOutputPolicy
<ModuleID, ItemType>::writeLog(*m_usedLogQueue.front(), m_id);

m_freeLogQueue.push_back(m_usedLogQueue.front());
m_usedLogQueue.pop_front();
}
LogOutputPolicy
<ModuleID, ItemType>::closeLog();
}

private:
void init()
{
resizeQueue(QueueSize_);
}

void resizeQueue(size_t size)
{
//Lock guard(this);
for(size_t i = 0; i < size; i++)
{
ItemType
* item = new ItemType();
m_freeLogQueue.push_back(item);
}
}

void releaseQueue()
{
//if ( !m_usedLogQueue.empty() )
// pumpQueue();

ItemType
* item;
while ( !m_freeLogQueue.empty() )
{
item
= m_freeLogQueue.front();

assert(item);
delete item;

m_freeLogQueue.pop_front();
}
}
};


#endif

  LogQueue根据QueueSize_参数决定初始化的empty list大小,。并可动态增长。这里为方便使用2个list,一个作为空的logitem池,一个则存放已经被占用的logitem。这里容器实现方式自己应需要更改吧。

      至此整个LogSystem完毕。待完善的地方还很多,抛砖引玉,各位读者如有建议又有时间,贴上吧。但做下来感觉基于策略的思维真的很有感觉,实现过程中能磨练不少c++的设计思维。这半年都花了很多时间在c++的语法和设计方面,希望能够有所收获。接下来该是多学习算法,数据结构的时候了,面试的时候吃了不少亏哈。