124 lines
4.5 KiB
C++
124 lines
4.5 KiB
C++
|
|
/*
|
||
|
|
* Appender.cpp
|
||
|
|
*
|
||
|
|
* Copyright 2000, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
|
||
|
|
* Copyright 2000, Bastiaan Bakker. All rights reserved.
|
||
|
|
*
|
||
|
|
* See the COPYING file for the terms of usage and distribution.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "PortabilityImpl.hh"
|
||
|
|
#include <log4cpp/Appender.hh>
|
||
|
|
#include <iostream>
|
||
|
|
|
||
|
|
namespace log4cpp {
|
||
|
|
static int appenders_nifty_counter; // zero initialized at load time
|
||
|
|
static char appenderMapStorage_buf[sizeof(Appender::AppenderMapStorage)]; // memory for the nifty-counter singleton object
|
||
|
|
Appender::AppenderMapStorage &Appender::_appenderMapStorageInstance = reinterpret_cast<Appender::AppenderMapStorage&> (appenderMapStorage_buf); // memory for placement new
|
||
|
|
|
||
|
|
Appender::AppenderMapStorage::AppenderMapStorage() {
|
||
|
|
_allAppenders = new AppenderMap();
|
||
|
|
}
|
||
|
|
Appender::AppenderMapStorage::~AppenderMapStorage() {
|
||
|
|
_deleteAllAppenders();
|
||
|
|
delete _allAppenders;
|
||
|
|
}
|
||
|
|
|
||
|
|
Appender::AppenderMapStorageInitializer::AppenderMapStorageInitializer() {
|
||
|
|
if (appenders_nifty_counter++ == 0) {
|
||
|
|
// MSVC's <crtdbg.h> requires redefinition of the new operator, but could not deal with placement new form of it
|
||
|
|
#ifdef MSVC_MEMORY_LEAK_CHECK
|
||
|
|
#pragma push_macro("new")
|
||
|
|
#define new new
|
||
|
|
#endif // MSVC_MEMORY_LEAK_CHECK
|
||
|
|
new (&_appenderMapStorageInstance) AppenderMapStorage(); // placement new
|
||
|
|
#ifdef MSVC_MEMORY_LEAK_CHECK
|
||
|
|
#pragma pop_macro("new")
|
||
|
|
#endif // MSVC_MEMORY_LEAK_CHECK
|
||
|
|
}
|
||
|
|
}
|
||
|
|
Appender::AppenderMapStorageInitializer::~AppenderMapStorageInitializer() {
|
||
|
|
if (--appenders_nifty_counter == 0) {
|
||
|
|
(&_appenderMapStorageInstance)->~AppenderMapStorage ();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* assume _appenderMapMutex locked */
|
||
|
|
Appender::AppenderMap& Appender::_getAllAppenders() {
|
||
|
|
return *_appenderMapStorageInstance._allAppenders;
|
||
|
|
}
|
||
|
|
|
||
|
|
Appender* Appender::getAppender(const std::string& name) {
|
||
|
|
threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
|
||
|
|
AppenderMap& allAppenders = Appender::_getAllAppenders();
|
||
|
|
AppenderMap::iterator i = allAppenders.find(name);
|
||
|
|
return (allAppenders.end() == i) ? NULL : ((*i).second);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Appender::_addAppender(Appender* appender) {
|
||
|
|
//REQUIRE(_allAppenders.find(appender->getName()) == _getAllAppenders().end())
|
||
|
|
threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
|
||
|
|
_getAllAppenders()[appender->getName()] = appender;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Appender::_removeAppender(Appender* appender) {
|
||
|
|
threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
|
||
|
|
//private called from destructor only, but may be triggered by client code in several treads
|
||
|
|
_getAllAppenders().erase(appender->getName());
|
||
|
|
}
|
||
|
|
|
||
|
|
bool Appender::reopenAll() {
|
||
|
|
threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
|
||
|
|
bool result = true;
|
||
|
|
AppenderMap& allAppenders = _getAllAppenders();
|
||
|
|
for(AppenderMap::iterator i = allAppenders.begin(); i != allAppenders.end(); i++) {
|
||
|
|
result = result && ((*i).second)->reopen();
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
void Appender::closeAll() {
|
||
|
|
threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
|
||
|
|
AppenderMap& allAppenders = _getAllAppenders();
|
||
|
|
for(AppenderMap::iterator i = allAppenders.begin(); i != allAppenders.end(); i++) {
|
||
|
|
((*i).second)->close();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Appender::_deleteAllAppenders() {
|
||
|
|
// deleting each appenders will cause a lock on Appender::_appenderMapMutex to be obtained again within destructor. to avoid nested locks:
|
||
|
|
std::vector<Appender*> appenders;
|
||
|
|
{
|
||
|
|
threading::ScopedLock lock(_appenderMapStorageInstance._appenderMapMutex);
|
||
|
|
AppenderMap& allAppenders = _getAllAppenders();
|
||
|
|
appenders.reserve(allAppenders.size());
|
||
|
|
for(AppenderMap::iterator i = allAppenders.begin(); i != allAppenders.end(); ) {
|
||
|
|
Appender* app = (*i).second;
|
||
|
|
++i;
|
||
|
|
appenders.push_back(app);
|
||
|
|
}
|
||
|
|
allAppenders.clear();
|
||
|
|
}
|
||
|
|
_deleteAllAppendersWOLock(appenders);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Appender::_deleteAllAppendersWOLock(std::vector<Appender*> &appenders) {
|
||
|
|
/* assume Appender::_appenderMapMutex not locked */
|
||
|
|
AppenderMap& allAppenders = _getAllAppenders();
|
||
|
|
for(std::vector<Appender*>::iterator i = appenders.begin(); i != appenders.end(); ++i) {
|
||
|
|
Appender *app = (*i);
|
||
|
|
delete (app);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Appender::Appender(const std::string& name) :
|
||
|
|
_name(name) {
|
||
|
|
_addAppender(this);
|
||
|
|
}
|
||
|
|
|
||
|
|
Appender::~Appender() {
|
||
|
|
_removeAppender(this);
|
||
|
|
}
|
||
|
|
}
|