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