• 开源日志系统log4cplus(六)


    log4cplus在很多方面做的都很出色,但是使用过程有些地方感觉不爽。在继续吹捧之前我先把不爽之处
    稍微提一提,然后继续介绍关于线程和套接字的知识。

    ### 一些可以改进之处 ###
    1. 用户自定义LogLevel的实现机制不够开放
    在第五篇中曾经介绍过如何实现用户自行定义LogLevel,为了实现比较理想的效果,甚至还需要改log4cplus
    的源代码。:(
    2. 生成Logger对象的机制可以改进
    我在使用时候,经常需要在不同的文件、函数中操作同一个logger,虽然log4cplus实现了树状存储以及根据
    名称生成Logger,却没有充分利用这样的特点确保同一个名称对应的logger对象的唯一性,比如以下代码:
        ... ...
       
        Logger logger1 = Logger::getInstance("test");
        Logger logger2 = Logger::getInstance("test");
        Logger * plogger1 = &logger1;
        Logger * plogger2 = &logger2;
        std::cout << "plogger1: " << plogger1 << std::endl << "plogger2: " << plogger2 << std::endl;
       
        ... ...
       
       
    运行结果:
    plogger1: 0xbfffe5a0
    plogger2: 0xbfffe580

    从结果可以看出,明明是同一个Logger,但每次调用都会产生一个Logger副本,虽然结果是正确的(因为将存
    储和操作分开了),但是资源有些浪费,我看了一下log4cplus的代码,其实可以按照如下方式实现(示意性
    的):
    #include <iostream>
    #include <string>
    #include <map>
    /* forward declaration */
    class Logger;
    class LoggerContainer
    {
    public:
        ~LoggerContainer();
        Logger * getinstance(const std::string & strLogger);
    private:
        typedef std::map<:string,> LoggerMap;
        LoggerMap loggerPtrs;
    };
    class Logger
    {
    public:
         Logger() {std::cout << "ctor of Logger " << std::endl; }
        ~Logger() {std::cout << "dtor of Logger " << std::endl; }
        static Logger * getInstance( const std::string & strLogger)
        {
            static LoggerContainer defaultLoggerContainer;
            return defaultLoggerContainer.getinstance(strLogger);
        }
    };
    LoggerContainer::~LoggerContainer()
    {
        /* release all ptr in LoggerMap */
        LoggerMap::iterator itr = loggerPtrs.begin();
        for( ; itr != loggerPtrs.end(); ++itr )
     {
         delete (*itr).second;
     }
    }
    Logger * LoggerContainer::getinstance(const std::string & strLogger)
    {
       LoggerMap::iterator itr = loggerPtrs.find(strLogger);
       if(itr != loggerPtrs.end())
       {
           /* logger exist, just return it */
           return (*itr).second;
       }
       else
       {
           /* return a new logger */
           Logger * plogger = new Logger();
           loggerPtrs.insert(std::make_pair(strLogger, plogger));
           return plogger;
       }
    }
    int main()
    {
        Logger * plogger1 = Logger::getInstance("test");
        Logger * plogger2 = Logger::getInstance("test");
        std::cout << "plogger1: " << plogger1 << std::endl << "plogger2: " << plogger2 << std::endl;
        return 0;
    }

    运行结果:
    ctor of Logger
    plogger1: 0x804fc30
    plogger2: 0x804fc30
    dtor of Logger
    这里的LoggerContainer相当于log4cplus中的Hierarchy类,结果可以看出,通过同一个名称可以获取相同的
    Logger实例。

    还有一些小毛病比如RollingFileAppender和DailyRollingFileAppender的参数输入顺序可以调整成统一方式
    等等,就不细说了。
    本部分提到了使用log4cplus时候感觉不爽的地方,最后一部分将介绍一下log4cplus中线程和套接字实现情况
  • 相关阅读:
    lambda续集——1
    c++之—— lambda表达式(有个未能解决的问题等待大佬解答)——(在stack overflow找到了答案)
    交换两个变量,只使用2个变量——权当面试了解使用
    移位实现正负数原码输出
    算法导论之——插入排序
    类模板的实现与定义相分离
    类模板
    当函数模板遇到普通函数
    c++之——template模板函数
    字符转数字,数字转字符
  • 原文地址:https://www.cnblogs.com/rosesmall/p/2469277.html
Copyright © 2020-2023  润新知