zoukankan      html  css  js  c++  java
  • 整理:一个简单的基于策略的多线程logsystem(3)

          最后一个步骤是实现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++的语法和设计方面,希望能够有所收获。接下来该是多学习算法,数据结构的时候了,面试的时候吃了不少亏哈。

  • 相关阅读:
    Python基础-常用模块
    Python基础-递归函数
    Python基础-内置函数和匿名函数
    python函数-迭代器和生成器
    Python函数-装饰器
    Python基础-文件操作&函数回顾总结
    Python入门 Day3-博客登录程序
    Python入门 Day3-小练习
    错题
    SSM整合
  • 原文地址:https://www.cnblogs.com/flytrace/p/2174930.html
Copyright © 2011-2022 走看看