log4cplus在很多方面做的都很出色,但是使用過程有些地方感覺不爽。在繼續(xù)吹捧之前我先把不爽之處
稍微提一提,然后繼續(xù)介紹關(guān)于線程和套接字的知識。
### 一些可以改進(jìn)之處 ###
1. 用戶自定義LogLevel的實現(xiàn)機(jī)制不夠開放
在第五篇中曾經(jīng)介紹過如何實現(xiàn)用戶自行定義LogLevel,為了實現(xiàn)比較理想的效果,甚至還需要改log4cplus
的源代碼。:(
2. 生成Logger對象的機(jī)制可以改進(jìn)
我在使用時候,經(jīng)常需要在不同的文件、函數(shù)中操作同一個logger,雖然log4cplus實現(xiàn)了樹狀存儲以及根據(jù)
名稱生成Logger,卻沒有充分利用這樣的特點確保同一個名稱對應(yīng)的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;
???
??? ... ...
???
???
運(yùn)行結(jié)果:
plogger1: 0xbfffe5a0
plogger2: 0xbfffe580
從結(jié)果可以看出,明明是同一個Logger,但每次調(diào)用都會產(chǎn)生一個Logger副本,雖然結(jié)果是正確的(因為將存
儲和操作分開了),但是資源有些浪費(fèi),我看了一下log4cplus的代碼,其實可以按照如下方式實現(xiàn)(示意性
的):
#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;
}
運(yùn)行結(jié)果:
ctor of Logger
plogger1: 0x804fc30
plogger2: 0x804fc30
dtor of Logger
這里的LoggerContainer相當(dāng)于log4cplus中的Hierarchy類,結(jié)果可以看出,通過同一個名稱可以獲取相同的
Logger實例。
還有一些小毛病比如RollingFileAppender和DailyRollingFileAppender的參數(shù)輸入順序可以調(diào)整成統(tǒng)一方式
等等,就不細(xì)說了。
本部分提到了使用log4cplus時候感覺不爽的地方,最后一部分將介紹一下log4cplus中線程和套接字實現(xiàn)情況