LOGCXX-500: I wasn't sure about the conflict merging before after merging "master" and simply did it again.
# Conflicts:
# pom.xml
# src/main/cpp/appenderskeleton.cpp
# src/main/cpp/asyncappender.cpp
# src/main/cpp/fileappender.cpp
# src/main/cpp/gzcompressaction.cpp
# src/main/cpp/locationinfo.cpp
# src/main/cpp/logger.cpp
# src/main/cpp/loggingevent.cpp
# src/main/cpp/mutex.cpp
# src/main/cpp/objectoutputstream.cpp
# src/main/cpp/odbcappender.cpp
# src/main/cpp/rollingfileappender.cpp
# src/main/cpp/smtpappender.cpp
# src/main/cpp/socket.cpp
# src/main/cpp/socketappender.cpp
# src/main/cpp/socketappenderskeleton.cpp
# src/main/cpp/threadcxx.cpp
# src/main/cpp/writerappender.cpp
# src/main/cpp/zipcompressaction.cpp
# src/main/include/log4cxx/appenderskeleton.h
# src/main/include/log4cxx/asyncappender.h
# src/main/include/log4cxx/helpers/messagebuffer.h
# src/main/include/log4cxx/helpers/objectoutputstream.h
# src/main/include/log4cxx/helpers/objectptr.h
# src/main/include/log4cxx/helpers/thread.h
# src/main/include/log4cxx/net/socketappender.h
# src/main/include/log4cxx/net/telnetappender.h
# src/main/include/log4cxx/rolling/timebasedrollingpolicy.h
diff --git a/configure.ac b/configure.ac
index 6ec857e..d8ad3d4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -64,6 +64,8 @@
;;
esac
+CXXFLAGS="$CXXFLAGS -std=c++11"
+
# Doxygen
AC_ARG_ENABLE(doxygen,
diff --git a/src/main/cpp/appenderskeleton.cpp b/src/main/cpp/appenderskeleton.cpp
index 7fc85d3..1d66c21 100644
--- a/src/main/cpp/appenderskeleton.cpp
+++ b/src/main/cpp/appenderskeleton.cpp
@@ -40,9 +40,9 @@
headFilter(),
tailFilter(),
pool(),
- mutex(pool)
+ SHARED_MUTEX_INIT(mutex, pool)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
closed = false;
}
@@ -54,9 +54,9 @@
headFilter(),
tailFilter(),
pool(),
- mutex(pool)
+ SHARED_MUTEX_INIT(mutex, pool)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
closed = false;
}
@@ -82,7 +82,7 @@
void AppenderSkeleton::addFilter(const spi::FilterPtr& newFilter)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if(headFilter == 0)
{
headFilter = tailFilter = newFilter;
@@ -96,7 +96,7 @@
void AppenderSkeleton::clearFilters()
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
headFilter = tailFilter = 0;
}
@@ -107,9 +107,13 @@
void AppenderSkeleton::doAppend(const spi::LoggingEventPtr& event, Pool& pool1)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
+ doAppendImpl(event, pool1);
+}
+void AppenderSkeleton::doAppendImpl(const spi::LoggingEventPtr& event, Pool& pool1)
+{
if(closed)
{
LogLog::error(((LogString) LOG4CXX_STR("Attempted to append to closed appender named ["))
@@ -144,7 +148,7 @@
void AppenderSkeleton::setErrorHandler(const spi::ErrorHandlerPtr& errorHandler1)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if(errorHandler1 == 0)
{
@@ -160,7 +164,7 @@
void AppenderSkeleton::setThreshold(const LevelPtr& threshold1)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
this->threshold = threshold1;
}
diff --git a/src/main/cpp/asyncappender.cpp b/src/main/cpp/asyncappender.cpp
index 52fc194..b7a4292 100644
--- a/src/main/cpp/asyncappender.cpp
+++ b/src/main/cpp/asyncappender.cpp
@@ -44,8 +44,8 @@
AsyncAppender::AsyncAppender()
: AppenderSkeleton(),
- buffer(),
- bufferMutex(pool),
+ buffer(DEFAULT_BUFFER_SIZE),
+ SHARED_MUTEX_INIT(bufferMutex, pool),
bufferNotFull(pool),
bufferNotEmpty(pool),
discardMap(new DiscardMap()),
@@ -96,6 +96,13 @@
}
+void AsyncAppender::doAppend(const spi::LoggingEventPtr& event, Pool& pool1)
+{
+ LOCK_R sync(mutex);
+
+ doAppendImpl(event, pool1);
+}
+
void AsyncAppender::append(const spi::LoggingEventPtr& event, Pool& p) {
#if APR_HAS_THREADS
//
@@ -118,16 +125,19 @@
{
- synchronized sync(bufferMutex);
+ LOCK_R sync(bufferMutex);
while(true) {
- int previousSize = buffer.size();
- if (previousSize < bufferSize) {
- buffer.push_back(event);
- if (previousSize == 0) {
- bufferNotEmpty.signalAll();
- }
- break;
- }
+
+ event->addRef();
+ if (buffer.bounded_push(event))
+ {
+ bufferNotEmpty.signalAll();
+ break;
+ }
+ else
+ {
+ event->releaseRef();
+ }
//
// Following code is only reachable if buffer is full
@@ -141,7 +151,7 @@
&& !Thread::interrupted()
&& !dispatcher.isCurrentThread()) {
try {
- bufferNotFull.await(bufferMutex);
+ bufferNotFull.await();
discard = false;
} catch (InterruptedException& e) {
//
@@ -157,14 +167,7 @@
// add event to discard map.
//
if (discard) {
- LogString loggerName = event->getLoggerName();
- DiscardMap::iterator iter = discardMap->find(loggerName);
- if (iter == discardMap->end()) {
- DiscardSummary summary(event);
- discardMap->insert(DiscardMap::value_type(loggerName, summary));
- } else {
- (*iter).second.add(event);
- }
+ discardedCount++;
break;
}
}
@@ -178,12 +181,13 @@
void AsyncAppender::close() {
{
- synchronized sync(bufferMutex);
+ LOCK_W sync(bufferMutex);
closed = true;
- bufferNotEmpty.signalAll();
- bufferNotFull.signalAll();
}
+ bufferNotEmpty.signalAll();
+ bufferNotFull.signalAll();
+
#if APR_HAS_THREADS
try {
dispatcher.join();
@@ -258,8 +262,12 @@
if (size < 0) {
throw IllegalArgumentException(LOG4CXX_STR("size argument must be non-negative"));
}
- synchronized sync(bufferMutex);
- bufferSize = (size < 1) ? 1 : size;
+
+ {
+ LOCK_W sync(bufferMutex);
+ bufferSize = (size < 1) ? 1 : size;
+ buffer.reserve_unsafe(bufferSize);
+ }
bufferNotFull.signalAll();
}
@@ -269,8 +277,10 @@
}
void AsyncAppender::setBlocking(bool value) {
- synchronized sync(bufferMutex);
- blocking = value;
+ {
+ LOCK_W sync(bufferMutex);
+ blocking = value;
+ }
bufferNotFull.signalAll();
}
@@ -311,41 +321,57 @@
LocationInfo::getLocationUnavailable());
}
+::log4cxx::spi::LoggingEventPtr
+AsyncAppender::DiscardSummary::createEvent(::log4cxx::helpers::Pool& p,
+ unsigned discardedCount)
+{
+ char msg[128];
+
+ snprintf(msg, 128, LOG4CXX_STR("Discarded %u messages due to a full event buffer."), discardedCount);
+
+ return new LoggingEvent(
+ "",
+ log4cxx::Level::getError(),
+ msg,
+ LocationInfo::getLocationUnavailable());
+}
#if APR_HAS_THREADS
void* LOG4CXX_THREAD_FUNC AsyncAppender::dispatch(apr_thread_t* /*thread*/, void* data) {
AsyncAppender* pThis = (AsyncAppender*) data;
- bool isActive = true;
try {
- while (isActive) {
+ while (!pThis->closed) {
+
+ pThis->bufferNotEmpty.await();
+
//
// process events after lock on buffer is released.
//
Pool p;
LoggingEventList events;
{
- synchronized sync(pThis->bufferMutex);
- size_t bufferSize = pThis->buffer.size();
- isActive = !pThis->closed;
+ LOCK_R sync(pThis->bufferMutex);
- while((bufferSize == 0) && isActive) {
- pThis->bufferNotEmpty.await(pThis->bufferMutex);
- bufferSize = pThis->buffer.size();
- isActive = !pThis->closed;
+ unsigned count = 0;
+ log4cxx::spi::LoggingEvent * logPtr = nullptr;
+ while (pThis->buffer.pop(logPtr))
+ {
+ log4cxx::spi::LoggingEventPtr ptr(logPtr);
+ events.push_back(ptr);
+ logPtr->releaseRef();
+ count++;
}
- for(LoggingEventList::iterator eventIter = pThis->buffer.begin();
- eventIter != pThis->buffer.end();
- eventIter++) {
- events.push_back(*eventIter);
+
+ if (pThis->blocking) {
+ pThis->bufferNotFull.signalAll();
}
- for(DiscardMap::iterator discardIter = pThis->discardMap->begin();
- discardIter != pThis->discardMap->end();
- discardIter++) {
- events.push_back(discardIter->second.createEvent(p));
+
+ unsigned discarded = pThis->discardedCount.exchange(0);
+
+ if (discarded != 0)
+ {
+ events.push_back(AsyncAppender::DiscardSummary::createEvent(p, discarded));
}
- pThis->buffer.clear();
- pThis->discardMap->clear();
- pThis->bufferNotFull.signalAll();
}
for (LoggingEventList::iterator iter = events.begin();
diff --git a/src/main/cpp/domconfigurator.cpp b/src/main/cpp/domconfigurator.cpp
index 95a7b60..618048a 100644
--- a/src/main/cpp/domconfigurator.cpp
+++ b/src/main/cpp/domconfigurator.cpp
@@ -44,6 +44,7 @@
#include <log4cxx/helpers/bytebuffer.h>
#include <log4cxx/helpers/charsetdecoder.h>
#include <log4cxx/net/smtpappender.h>
+#include <log4cxx/helpers/messagebuffer.h>
#define LOG4CXX 1
#include <log4cxx/helpers/aprinitializer.h>
@@ -110,6 +111,7 @@
#define REF_ATTR "ref"
#define ADDITIVITY_ATTR "additivity"
#define THRESHOLD_ATTR "threshold"
+#define STRINGSTREAM_ATTR "stringstream"
#define CONFIG_DEBUG_ATTR "configDebug"
#define INTERNAL_DEBUG_ATTR "debug"
@@ -387,7 +389,7 @@
// Setting up a logger needs to be an atomic operation, in order
// to protect potential log operations while logger
// configuration is in progress.
- synchronized sync(logger->getMutex());
+ LOCK_W sync(logger->getMutex());
bool additivity = OptionConverter::toBoolean(
subst(getAttribute(utf8Decoder, loggerElement, ADDITIVITY_ATTR)),
true);
@@ -445,7 +447,7 @@
{
LoggerPtr root = repository->getRootLogger();
// logger configuration needs to be atomic
- synchronized sync(root->getMutex());
+ LOCK_W sync(root->getMutex());
parseChildrenOfLoggerElement(p, utf8Decoder, rootElement, root, true, doc, appenders);
}
@@ -951,6 +953,13 @@
repository->setThreshold(thresholdStr);
}
+ LogString strstrValue = subst(getAttribute(utf8Decoder, element, STRINGSTREAM_ATTR));
+ LogLog::debug(LOG4CXX_STR("Stringstream =\"") + strstrValue +LOG4CXX_STR("\"."));
+ if(!strstrValue.empty() && strstrValue != NuLL)
+ {
+ MessageBufferUseStaticStream();
+ }
+
apr_xml_elem* currentElement;
for(currentElement = element->first_child;
currentElement;
diff --git a/src/main/cpp/fileappender.cpp b/src/main/cpp/fileappender.cpp
index 46ff632..70d42bd 100644
--- a/src/main/cpp/fileappender.cpp
+++ b/src/main/cpp/fileappender.cpp
@@ -36,7 +36,7 @@
FileAppender::FileAppender() {
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
fileAppend = true;
bufferedIO = false;
bufferSize = 8 * 1024;
@@ -46,7 +46,7 @@
bool append1, bool bufferedIO1, int bufferSize1)
: WriterAppender(layout1) {
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
fileAppend = append1;
fileName = fileName1;
bufferedIO = bufferedIO1;
@@ -60,7 +60,7 @@
bool append1)
: WriterAppender(layout1) {
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
fileAppend = append1;
fileName = fileName1;
bufferedIO = false;
@@ -73,7 +73,7 @@
FileAppender::FileAppender(const LayoutPtr& layout1, const LogString& fileName1)
: WriterAppender(layout1) {
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
fileAppend = true;
fileName = fileName1;
bufferedIO = false;
@@ -89,13 +89,13 @@
}
void FileAppender::setAppend(bool fileAppend1) {
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
this->fileAppend = fileAppend1;
}
void FileAppender::setFile(const LogString& file)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
fileName = file;
}
@@ -103,7 +103,7 @@
void FileAppender::setBufferedIO(bool bufferedIO1)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
this->bufferedIO = bufferedIO1;
if(bufferedIO1)
{
@@ -117,27 +117,27 @@
if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("FILE"), LOG4CXX_STR("file"))
|| StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("FILENAME"), LOG4CXX_STR("filename")))
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
fileName = stripDuplicateBackslashes(value);
}
else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("APPEND"), LOG4CXX_STR("append")))
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
fileAppend = OptionConverter::toBoolean(value, true);
}
else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BUFFEREDIO"), LOG4CXX_STR("bufferedio")))
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
bufferedIO = OptionConverter::toBoolean(value, true);
}
else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("IMMEDIATEFLUSH"), LOG4CXX_STR("immediateflush")))
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
bufferedIO = !OptionConverter::toBoolean(value, false);
}
else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BUFFERSIZE"), LOG4CXX_STR("buffersize")))
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
bufferSize = OptionConverter::toFileSize(value, 8*1024);
}
else
@@ -148,7 +148,7 @@
void FileAppender::activateOptions(Pool& p)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
int errors = 0;
if (!fileName.empty()) {
try {
@@ -240,7 +240,7 @@
bool bufferedIO1,
size_t bufferSize1,
Pool& p) {
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
// It does not make sense to have immediate flush and bufferedIO.
if (bufferedIO1) {
diff --git a/src/main/cpp/logger.cpp b/src/main/cpp/logger.cpp
index dd9a343..8c9a379 100644
--- a/src/main/cpp/logger.cpp
+++ b/src/main/cpp/logger.cpp
@@ -43,7 +43,7 @@
Logger::Logger(Pool& p, const LogString& name1)
: pool(&p), name(), level(), parent(), resourceBundle(),
-repository(), aai(), mutex(p)
+repository(), aai(), SHARED_MUTEX_INIT(mutex, p)
{
name = name1;
additive = true;
@@ -65,7 +65,7 @@
{
log4cxx::spi::LoggerRepository* rep = 0;
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if (aai == 0)
{
@@ -89,7 +89,7 @@
logger = logger->parent)
{
// Protected against simultaneous call to addAppender, removeAppender,...
- synchronized sync(logger->mutex);
+ LOCK_R sync(logger->mutex);
if (logger->aai != 0)
{
@@ -153,7 +153,7 @@
AppenderList Logger::getAllAppenders() const
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if (aai == 0)
{
@@ -167,7 +167,7 @@
AppenderPtr Logger::getAppender(const LogString& name1) const
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if (aai == 0 || name1.empty())
{
@@ -253,7 +253,7 @@
bool Logger::isAttached(const AppenderPtr& appender) const
{
- synchronized sync(mutex);
+ LOCK_R sync(mutex);
if (appender == 0 || aai == 0)
{
@@ -437,7 +437,7 @@
void Logger::removeAllAppenders()
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if(aai != 0)
{
@@ -448,7 +448,7 @@
void Logger::removeAppender(const AppenderPtr& appender)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if(appender == 0 || aai == 0)
{
@@ -460,7 +460,7 @@
void Logger::removeAppender(const LogString& name1)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if(name1.empty() || aai == 0)
{
@@ -472,7 +472,7 @@
void Logger::setAdditivity(bool additive1)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
this->additive = additive1;
}
diff --git a/src/main/cpp/messagebuffer.cpp b/src/main/cpp/messagebuffer.cpp
index 04d571e..39a5f2a 100644
--- a/src/main/cpp/messagebuffer.cpp
+++ b/src/main/cpp/messagebuffer.cpp
@@ -20,10 +20,46 @@
using namespace log4cxx::helpers;
-CharMessageBuffer::CharMessageBuffer() : stream(0) {}
+static bool gMessageBufferUseStaticStream = false;
+
+namespace log4cxx {
+namespace helpers {
+ void MessageBufferUseStaticStream()
+ {
+ gMessageBufferUseStaticStream = true;
+ }
+ }
+}
+
+template <typename T>
+void ResetStream(std::basic_ostringstream<T> &stream)
+{
+ stream.seekp(0);
+ stream.str(std::basic_string<T>());
+ stream.clear();
+}
+
+CharMessageBuffer::CharMessageBuffer() : stream(0) {
+ if (gMessageBufferUseStaticStream)
+ {
+ thread_local static char ossBuf[8192];
+ thread_local static std::basic_ostringstream<char> sStream;
+ thread_local static bool inited = false;
+ if (!inited)
+ {
+ inited = true;
+ sStream.rdbuf()->pubsetbuf(ossBuf, 8192);
+
+ ResetStream(sStream);
+ }
+ stream = &sStream;
+ }
+}
CharMessageBuffer::~CharMessageBuffer() {
- delete stream;
+ if (!gMessageBufferUseStaticStream) {
+ delete stream;
+ }
}
CharMessageBuffer& CharMessageBuffer::operator<<(const std::basic_string<char>& msg) {
@@ -73,6 +109,9 @@
const std::basic_string<char>& CharMessageBuffer::str(std::basic_ostream<char>&) {
buf = stream->str();
+
+ ResetStream(*stream);
+
return buf;
}
@@ -103,10 +142,27 @@
#if LOG4CXX_WCHAR_T_API
-WideMessageBuffer::WideMessageBuffer() : stream(0) {}
+WideMessageBuffer::WideMessageBuffer() : stream(0) {
+ if (gMessageBufferUseStaticStream)
+ {
+ thread_local static wchar_t ossBuf[8192];
+ thread_local static std::basic_ostringstream<wchar_t> sStream;
+ thread_local static bool inited = false;
+ if (!inited)
+ {
+ inited = true;
+ sStream.rdbuf()->pubsetbuf(ossBuf, 8192);
+
+ ResetStream(sStream);
+ }
+ stream = &sStream;
+ }
+}
WideMessageBuffer::~WideMessageBuffer() {
- delete stream;
+ if (!gMessageBufferUseStaticStream) {
+ delete stream;
+ }
}
WideMessageBuffer& WideMessageBuffer::operator<<(const std::basic_string<wchar_t>& msg) {
@@ -157,6 +213,9 @@
const std::basic_string<wchar_t>& WideMessageBuffer::str(std::basic_ostream<wchar_t>&) {
buf = stream->str();
+
+ ResetStream(*stream);
+
return buf;
}
@@ -312,10 +371,27 @@
}
-UniCharMessageBuffer::UniCharMessageBuffer() : stream(0) {}
+UniCharMessageBuffer::UniCharMessageBuffer() : stream(0) {
+ if (gMessageBufferUseStaticStream)
+ {
+ thread_local static log4cxx::UniChar ossBuf[8192];
+ thread_local static std::basic_ostringstream<log4cxx::UniChar> sStream;
+ thread_local static bool inited = false;
+ if (!inited)
+ {
+ inited = true;
+ sStream.rdbuf()->pubsetbuf(ossBuf, 8192);
+
+ ResetStream(sStream);
+ }
+ stream = &sStream;
+ }
+}
UniCharMessageBuffer::~UniCharMessageBuffer() {
- delete stream;
+ if (!gMessageBufferUseStaticStream) {
+ delete stream;
+ }
}
@@ -366,7 +442,8 @@
}
const std::basic_string<log4cxx::UniChar>& UniCharMessageBuffer::str(UniCharMessageBuffer::uostream&) {
- buf = stream->str();
+ buf = stream->str();
+ ResetStream(*stream);
return buf;
}
diff --git a/src/main/cpp/mutex.cpp b/src/main/cpp/mutex.cpp
old mode 100644
new mode 100755
index c50a562..2a1f79d
--- a/src/main/cpp/mutex.cpp
+++ b/src/main/cpp/mutex.cpp
@@ -16,16 +16,19 @@
*/
#include <log4cxx/logstring.h>
-#include <log4cxx/helpers/mutex.h>
#include <log4cxx/helpers/exception.h>
-#include <apr_thread_mutex.h>
+#include <log4cxx/helpers/mutex.h>
#include <log4cxx/helpers/pool.h>
+#include <apr_thread_mutex.h>
+#include <apr_thread_rwlock.h>
#include <assert.h>
#if !defined(LOG4CXX)
#define LOG4CXX 1
#endif
#include <log4cxx/helpers/aprinitializer.h>
+#include <semaphore.h>
+
using namespace log4cxx::helpers;
using namespace log4cxx;
@@ -66,3 +69,139 @@
apr_thread_mutex_t* Mutex::getAPRMutex() const {
return mutex;
}
+
+RWMutex::RWMutex(Pool& p)
+ : id((apr_os_thread_t)-1)
+ , count(0)
+{
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_thread_rwlock_create(&mutex,
+ p.getAPRPool());
+ if (stat != APR_SUCCESS) {
+ throw MutexException(stat);
+ }
+#endif
+}
+
+RWMutex::RWMutex(apr_pool_t* p)
+ : id((apr_os_thread_t)-1)
+ , count(0)
+{
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_thread_rwlock_create(&mutex, p);
+ if (stat != APR_SUCCESS) {
+ throw MutexException(stat);
+ }
+#endif
+}
+
+
+RWMutex::~RWMutex() {
+#if APR_HAS_THREADS
+ apr_thread_rwlock_destroy(mutex);
+#endif
+}
+
+void RWMutex::rdLock() const
+{
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_thread_rwlock_rdlock(mutex);
+#endif
+}
+
+void RWMutex::rdUnlock() const
+{
+#if APR_HAS_THREADS
+ apr_status_t stat = apr_thread_rwlock_unlock(mutex);
+#endif
+}
+
+void RWMutex::wrLock() const
+{
+#if APR_HAS_THREADS
+ apr_os_thread_t self = apr_os_thread_current();
+ if (id == self)
+ {
+ ++count;
+ }
+ else
+ {
+ apr_status_t stat = apr_thread_rwlock_wrlock(mutex);
+ id = self;
+ count = 1;
+ }
+#endif
+}
+
+void RWMutex::wrUnlock() const
+{
+#if APR_HAS_THREADS
+ if (--count == 0)
+ {
+ id = (apr_os_thread_t)-1; // id_ = "not a thread"
+ apr_status_t stat = apr_thread_rwlock_unlock(mutex);
+ }
+ else
+ {
+ }
+#endif
+}
+
+
+
+
+namespace log4cxx {
+ namespace helpers {
+ struct SemaphoreImpl
+ {
+ sem_t semaphore;
+ };
+ }
+}
+
+Semaphore::Semaphore(log4cxx::helpers::Pool& p)
+ : impl(nullptr)
+{
+#if APR_HAS_THREADS
+ impl = (SemaphoreImpl*)p.palloc(sizeof(SemaphoreImpl));
+ if (nullptr == impl) {
+ throw MutexException(APR_ENOMEM);
+ }
+
+ int stat = sem_init(&impl->semaphore, 0, 0);
+ if (stat != 0) {
+ throw MutexException(APR_ENOSHMAVAIL);
+ }
+#endif
+}
+
+Semaphore::~Semaphore()
+{
+#if APR_HAS_THREADS
+ if (impl)
+ {
+ int stat = sem_destroy(&impl->semaphore);
+ }
+#endif
+}
+
+void Semaphore::await() const
+{
+#if APR_HAS_THREADS
+ int stat = sem_wait(&impl->semaphore);
+ if (stat != 0) {
+ throw MutexException(stat);
+ }
+#endif
+}
+
+void Semaphore::signalAll() const
+{
+#if APR_HAS_THREADS
+ int stat = sem_post(&impl->semaphore);
+ if (stat != 0) {
+ throw MutexException(stat);
+ }
+#endif
+}
+
diff --git a/src/main/cpp/propertyconfigurator.cpp b/src/main/cpp/propertyconfigurator.cpp
index 82d9b05..e567031 100644
--- a/src/main/cpp/propertyconfigurator.cpp
+++ b/src/main/cpp/propertyconfigurator.cpp
@@ -177,6 +177,13 @@
+ LOG4CXX_STR("]."));
}
+ static const LogString STRINGSTREAM_KEY(LOG4CXX_STR("log4j.stringstream"));
+ LogString strstrValue(properties.getProperty(STRINGSTREAM_KEY));
+ if (strstrValue == LOG4CXX_STR("static"))
+ {
+ MessageBufferUseStaticStream();
+ }
+
configureRootLogger(properties, hierarchy);
configureLoggerFactory(properties);
parseCatsAndRenderers(properties, hierarchy);
@@ -235,7 +242,7 @@
{
LoggerPtr root = hierarchy->getRootLogger();
- synchronized sync(root->getMutex());
+ LOCK_W sync(root->getMutex());
static const LogString INTERNAL_ROOT_NAME(LOG4CXX_STR("root"));
parseLogger(props, root, effectiveFrefix, INTERNAL_ROOT_NAME, value);
}
@@ -271,7 +278,7 @@
LogString value = OptionConverter::findAndSubst(key, props);
LoggerPtr logger = hierarchy->getLogger(loggerName, loggerFactory);
- synchronized sync(logger->getMutex());
+ LOCK_W sync(logger->getMutex());
parseLogger(props, logger, key, loggerName, value);
parseAdditivityForLogger(props, logger, loggerName);
}
diff --git a/src/main/cpp/rollingfileappender.cpp b/src/main/cpp/rollingfileappender.cpp
index 777d0f8..33510de 100644
--- a/src/main/cpp/rollingfileappender.cpp
+++ b/src/main/cpp/rollingfileappender.cpp
@@ -85,7 +85,7 @@
}
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
triggeringPolicy->activateOptions(p);
rollingPolicy->activateOptions(p);
@@ -164,7 +164,7 @@
if (rollingPolicy != NULL) {
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
#ifdef LOG4CXX_MULTI_PROCESS
std::string fileName(getFile());
diff --git a/src/main/cpp/socketappender.cpp b/src/main/cpp/socketappender.cpp
index 0103b42..70826c3 100644
--- a/src/main/cpp/socketappender.cpp
+++ b/src/main/cpp/socketappender.cpp
@@ -79,7 +79,7 @@
void SocketAppender::setSocket(log4cxx::helpers::SocketPtr& socket, Pool& p)
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
oos = new ObjectOutputStream(new SocketOutputStream(socket), p);
}
diff --git a/src/main/cpp/socketappenderskeleton.cpp b/src/main/cpp/socketappenderskeleton.cpp
old mode 100644
new mode 100755
index a6b99cc..3010590
--- a/src/main/cpp/socketappenderskeleton.cpp
+++ b/src/main/cpp/socketappenderskeleton.cpp
@@ -78,7 +78,7 @@
}
void SocketAppenderSkeleton::close() {
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if (closed) return;
closed = true;
cleanUp(pool);
@@ -133,7 +133,7 @@
void SocketAppenderSkeleton::fireConnector()
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if ( !thread.isAlive() ) {
LogLog::debug(LOG4CXX_STR("Connector thread not alive: starting monitor."));
try {
diff --git a/src/main/cpp/sockethubappender.cpp b/src/main/cpp/sockethubappender.cpp
index 845908f..b519fb0 100644
--- a/src/main/cpp/sockethubappender.cpp
+++ b/src/main/cpp/sockethubappender.cpp
@@ -85,7 +85,7 @@
void SocketHubAppender::close()
{
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if (closed) {
return;
}
@@ -98,7 +98,7 @@
//
thread.join();
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
// close all of the connections
LogLog::debug(LOG4CXX_STR("closing client connections"));
for (std::vector<helpers::ObjectOutputStreamPtr>::iterator iter = streams.begin();
@@ -219,7 +219,7 @@
+ LOG4CXX_STR(")"));
// add it to the oosList.
- synchronized sync(pThis->mutex);
+ LOCK_W sync(pThis->mutex);
OutputStreamPtr os(new SocketOutputStream(socket));
Pool p;
ObjectOutputStreamPtr oos(new ObjectOutputStream(os, p));
diff --git a/src/main/cpp/synchronized.cpp b/src/main/cpp/synchronized.cpp
index 5233a0f..e561f54 100644
--- a/src/main/cpp/synchronized.cpp
+++ b/src/main/cpp/synchronized.cpp
@@ -59,3 +59,27 @@
}
#endif
}
+
+
+synchronized_read::synchronized_read(const RWMutex& mutex1)
+ : mutex(mutex1)
+{
+ mutex.rdLock();
+}
+
+synchronized_read::~synchronized_read()
+{
+ mutex.rdUnlock();
+}
+
+synchronized_write::synchronized_write(const RWMutex& mutex1)
+ : mutex(mutex1)
+{
+ mutex.wrLock();
+}
+
+synchronized_write::~synchronized_write()
+{
+ mutex.wrUnlock();
+}
+
diff --git a/src/main/cpp/telnetappender.cpp b/src/main/cpp/telnetappender.cpp
index 6914178..ff38ee3 100644
--- a/src/main/cpp/telnetappender.cpp
+++ b/src/main/cpp/telnetappender.cpp
@@ -46,7 +46,7 @@
encoder(CharsetEncoder::getUTF8Encoder()),
serverSocket(NULL), sh()
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
activeConnections = 0;
}
@@ -83,12 +83,12 @@
}
LogString TelnetAppender::getEncoding() const {
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
return encoding;
}
void TelnetAppender::setEncoding(const LogString& value) {
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
encoder = CharsetEncoder::getEncoder(value);
encoding = value;
}
@@ -96,7 +96,7 @@
void TelnetAppender::close()
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if (closed) return;
closed = true;
@@ -171,7 +171,7 @@
LogString::const_iterator msgIter(msg.begin());
ByteBuffer buf(bytes, bytesSize);
- synchronized sync(this->mutex);
+ LOCK_W sync(this->mutex);
while(msgIter != msg.end()) {
log4cxx_status_t stat = encoder->encode(msg, msgIter, buf);
buf.flip();
@@ -217,7 +217,7 @@
//
// find unoccupied connection
//
- synchronized sync(pThis->mutex);
+ LOCK_W sync(pThis->mutex);
for(ConnectionList::iterator iter = pThis->connections.begin();
iter != pThis->connections.end();
iter++) {
diff --git a/src/main/cpp/writerappender.cpp b/src/main/cpp/writerappender.cpp
index 951a8a0..ca1baf8 100644
--- a/src/main/cpp/writerappender.cpp
+++ b/src/main/cpp/writerappender.cpp
@@ -28,7 +28,7 @@
IMPLEMENT_LOG4CXX_OBJECT(WriterAppender)
WriterAppender::WriterAppender() {
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
immediateFlush = true;
}
@@ -36,14 +36,14 @@
log4cxx::helpers::WriterPtr& writer1)
: AppenderSkeleton(layout1), writer(writer1) {
Pool p;
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
immediateFlush = true;
activateOptions(p);
}
WriterAppender::WriterAppender(const LayoutPtr& layout1)
: AppenderSkeleton(layout1) {
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
immediateFlush = true;
}
@@ -139,7 +139,7 @@
*/
void WriterAppender::close()
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if(closed)
{
@@ -214,7 +214,7 @@
LogString msg;
layout->format(msg, event, p);
{
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
if (writer != NULL) {
writer->write(msg, p);
if (immediateFlush) {
@@ -230,7 +230,7 @@
if (layout != NULL) {
LogString foot;
layout->appendFooter(foot, p);
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
writer->write(foot, p);
}
}
@@ -240,14 +240,14 @@
if(layout != NULL) {
LogString header;
layout->appendHeader(header, p);
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
writer->write(header, p);
}
}
void WriterAppender::setWriter(const WriterPtr& newWriter) {
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
writer = newWriter;
}
@@ -266,6 +266,6 @@
void WriterAppender::setImmediateFlush(bool value) {
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
immediateFlush = value;
}
diff --git a/src/main/cpp/xmlsocketappender.cpp b/src/main/cpp/xmlsocketappender.cpp
index c5ce1a9..4a3a521 100644
--- a/src/main/cpp/xmlsocketappender.cpp
+++ b/src/main/cpp/xmlsocketappender.cpp
@@ -82,7 +82,7 @@
void XMLSocketAppender::setSocket(log4cxx::helpers::SocketPtr& socket, Pool& p) {
OutputStreamPtr os(new SocketOutputStream(socket));
CharsetEncoderPtr charset(CharsetEncoder::getUTF8Encoder());
- synchronized sync(mutex);
+ LOCK_W sync(mutex);
writer = new OutputStreamWriter(os, charset);
}
diff --git a/src/main/include/log4cxx/appenderskeleton.h b/src/main/include/log4cxx/appenderskeleton.h
index 670f683..dfdabb1 100644
--- a/src/main/include/log4cxx/appenderskeleton.h
+++ b/src/main/include/log4cxx/appenderskeleton.h
@@ -76,7 +76,7 @@
bool closed;
log4cxx::helpers::Pool pool;
- log4cxx::helpers::Mutex mutex;
+ mutable SHARED_MUTEX mutex;
/**
Subclasses of <code>AppenderSkeleton</code> should implement this
@@ -85,6 +85,8 @@
*/
virtual void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p) = 0;
+ void doAppendImpl(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool);
+
public:
DECLARE_ABSTRACT_LOG4CXX_OBJECT(AppenderSkeleton)
BEGIN_LOG4CXX_CAST_MAP()
@@ -171,7 +173,7 @@
* delegating actual logging to the subclasses specific
* AppenderSkeleton#append method.
* */
- void doAppend(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool);
+ virtual void doAppend(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& pool);
/**
Set the {@link spi::ErrorHandler ErrorHandler} for this Appender.
diff --git a/src/main/include/log4cxx/asyncappender.h b/src/main/include/log4cxx/asyncappender.h
index 3c24ae2..7d43d81 100644
--- a/src/main/include/log4cxx/asyncappender.h
+++ b/src/main/include/log4cxx/asyncappender.h
@@ -32,6 +32,7 @@
#include <log4cxx/helpers/mutex.h>
#include <log4cxx/helpers/condition.h>
+#include <boost/lockfree/queue.hpp>
namespace log4cxx
{
@@ -83,6 +84,9 @@
*/
void addAppender(const AppenderPtr& newAppender);
+ virtual void doAppend(const spi::LoggingEventPtr& event,
+ log4cxx::helpers::Pool& pool1);
+
void append(const spi::LoggingEventPtr& event, log4cxx::helpers::Pool& p);
/**
@@ -195,14 +199,15 @@
/**
* Event buffer.
*/
- LoggingEventList buffer;
+ boost::lockfree::queue<log4cxx::spi::LoggingEvent* > buffer;
+ std::atomic<unsigned> discardedCount;
/**
* Mutex used to guard access to buffer and discardMap.
*/
- ::log4cxx::helpers::Mutex bufferMutex;
- ::log4cxx::helpers::Condition bufferNotFull;
- ::log4cxx::helpers::Condition bufferNotEmpty;
+ SHARED_MUTEX bufferMutex;
+ SEMAPHORE bufferNotFull;
+ SEMAPHORE bufferNotEmpty;
class DiscardSummary {
private:
@@ -241,6 +246,10 @@
* @return new event.
*/
::log4cxx::spi::LoggingEventPtr createEvent(::log4cxx::helpers::Pool& p);
+
+ static
+ ::log4cxx::spi::LoggingEventPtr createEvent(::log4cxx::helpers::Pool& p,
+ unsigned discardedCount);
};
/**
diff --git a/src/main/include/log4cxx/helpers/messagebuffer.h b/src/main/include/log4cxx/helpers/messagebuffer.h
index 3335caf..3e5388d 100644
--- a/src/main/include/log4cxx/helpers/messagebuffer.h
+++ b/src/main/include/log4cxx/helpers/messagebuffer.h
@@ -27,6 +27,8 @@
namespace helpers {
+ void MessageBufferUseStaticStream();
+
typedef std::ios_base& (*ios_base_manip)(std::ios_base&);
/**
diff --git a/src/main/include/log4cxx/helpers/mutex.h b/src/main/include/log4cxx/helpers/mutex.h
index d26487b..58cf7db 100644
--- a/src/main/include/log4cxx/helpers/mutex.h
+++ b/src/main/include/log4cxx/helpers/mutex.h
@@ -20,9 +20,14 @@
#include <log4cxx/log4cxx.h>
+#include <apr-1.0/apr_portable.h>
+
+#include <atomic>
+
extern "C" {
struct apr_thread_mutex_t;
struct apr_pool_t;
+ struct apr_thread_rwlock_t;
}
@@ -48,4 +53,74 @@
} // namespace helpers
} // namespace log4cxx
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ class Pool;
+
+ class LOG4CXX_EXPORT RWMutex
+ {
+ public:
+ RWMutex(log4cxx::helpers::Pool& p);
+ RWMutex(apr_pool_t* p);
+ ~RWMutex();
+
+ void rdLock() const;
+ void rdUnlock() const;
+
+ void wrLock() const;
+ void wrUnlock() const;
+
+ private:
+ mutable std::atomic<apr_os_thread_t> id;
+ mutable unsigned count;
+ RWMutex(const RWMutex&);
+ RWMutex& operator=(const RWMutex&);
+ apr_thread_rwlock_t* mutex;
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+//#define SHARED_MUTEX_INIT(mutex, p) mutex()
+//#define SHARED_MUTEX shared_mutex_recursive
+
+//#define SHARED_MUTEX std::shared_mutex
+
+//#define SHARED_MUTEX_INIT(mutex, p) mutex(p)
+//#define SHARED_MUTEX log4cxx::helpers::Mutex
+
+
+#define SHARED_MUTEX log4cxx::helpers::RWMutex
+#define SHARED_MUTEX_INIT(mutex, p) mutex(p)
+
+namespace log4cxx
+{
+ namespace helpers
+ {
+ struct SemaphoreImpl;
+
+ class LOG4CXX_EXPORT Semaphore
+ {
+ public:
+ Semaphore(log4cxx::helpers::Pool& p);
+ ~Semaphore();
+
+ void await() const;
+ void signalAll() const;
+
+ private:
+ Semaphore(const Semaphore&);
+ Semaphore& operator=(const Semaphore&);
+
+ SemaphoreImpl *impl;
+ };
+ } // namespace helpers
+} // namespace log4cxx
+
+#define SEMAPHORE log4cxx::helpers::Semaphore
+
+//#define SEMAPHORE log4cxx::helpers::Condition
+
#endif //_LOG4CXX_HELPERS_MUTEX_H
diff --git a/src/main/include/log4cxx/helpers/synchronized.h b/src/main/include/log4cxx/helpers/synchronized.h
index 66e6259..f4b31d7 100644
--- a/src/main/include/log4cxx/helpers/synchronized.h
+++ b/src/main/include/log4cxx/helpers/synchronized.h
@@ -46,4 +46,61 @@
}
}
+namespace log4cxx
+{
+ namespace helpers {
+ class RWMutex;
+
+ // utility class for objects multi-thread synchronization.
+ class LOG4CXX_EXPORT synchronized_read
+ {
+ public:
+ synchronized_read(const RWMutex& mutex);
+ ~synchronized_read();
+
+
+ private:
+ const RWMutex & mutex;
+ // prevent use of copy and assignment
+ synchronized_read(const synchronized_read&);
+ synchronized_read& operator=(const synchronized_read&);
+ };
+ }
+}
+
+namespace log4cxx
+{
+ namespace helpers {
+ class RWMutex;
+
+ // utility class for objects multi-thread synchronization.
+ class LOG4CXX_EXPORT synchronized_write
+ {
+ public:
+ synchronized_write(const RWMutex& mutex);
+ ~synchronized_write();
+
+
+ private:
+ const RWMutex & mutex;
+ // prevent use of copy and assignment
+ synchronized_write(const synchronized_write&);
+ synchronized_write& operator=(const synchronized_write&);
+ };
+ }
+}
+
+//#define LOCK_R std::shared_lock<shared_mutex_recursive>
+//#define LOCK_W std::unique_lock<shared_mutex_recursive>
+
+//#define LOCK std::lock_guard<std::recursive_mutex>
+
+//#define LOCK synchronized
+
+#define LOCK_R synchronized_read
+#define LOCK_W synchronized_write
+
+//#define LOCK_R synchronized
+//#define LOCK_W synchronized
+
#endif //_LOG4CXX_HELPERS_SYNCHRONIZED_H
diff --git a/src/main/include/log4cxx/logger.h b/src/main/include/log4cxx/logger.h
index be24f65..bece458 100644
--- a/src/main/include/log4cxx/logger.h
+++ b/src/main/include/log4cxx/logger.h
@@ -1707,14 +1707,14 @@
*/
void trace(const std::string& msg) const;
- inline const log4cxx::helpers::Mutex& getMutex() const { return mutex; }
+ inline SHARED_MUTEX & getMutex() { return mutex; }
private:
//
// prevent copy and assignment
Logger(const Logger&);
Logger& operator=(const Logger&);
- log4cxx::helpers::Mutex mutex;
+ mutable SHARED_MUTEX mutex;
friend class log4cxx::helpers::synchronized;
};
LOG4CXX_LIST_DEF(LoggerList, LoggerPtr);
diff --git a/src/main/include/log4cxx/rolling/timebasedrollingpolicy.h b/src/main/include/log4cxx/rolling/timebasedrollingpolicy.h
old mode 100644
new mode 100755