carnold 2005/01/03 19:37:07
Modified: include/log4cxx mdc.h ndc.h stream.h
include/log4cxx/helpers aprinitializer.h
threadspecificdata.h
performance main.cpp
src aprinitializer.cpp loggingevent.cpp mdc.cpp ndc.cpp
threadspecificdata.cpp
Log:
LOGCXX-36: APR migration, thread-specific data
Revision Changes Path
1.10 +63 -67 logging-log4cxx/include/log4cxx/mdc.h
Index: mdc.h
===================================================================
RCS file: /home/cvs/logging-log4cxx/include/log4cxx/mdc.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- mdc.h 12 Dec 2004 05:53:57 -0000 1.9
+++ mdc.h 4 Jan 2005 03:37:07 -0000 1.10
@@ -1,5 +1,5 @@
/*
- * Copyright 2003,2004 The Apache Software Foundation.
+ * Copyright 2003-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,88 +17,84 @@
#ifndef _LOG4CXX_MDC_H
#define _LOG4CXX_MDC_H
+#include <log4cxx/portability.h>
#include <log4cxx/logstring.h>
-#include <log4cxx/helpers/threadspecificdata.h>
#include <map>
namespace log4cxx
{
- /**
- The MDC class is similar to the [EMAIL PROTECTED] NDC} class except
that it is
- based on a map instead of a stack. It provides <em>mapped
- diagnostic contexts</em>. A <em>Mapped Diagnostic Context</em>, or
- MDC in short, is an instrument for distinguishing interleaved log
- output from different sources. Log output is typically interleaved
- when a server handles multiple clients near-simultaneously.
-
- <p><b><em>The MDC is managed on a per thread basis</em></b>. A
- child thread automatically inherits a <em>copy</em> of the mapped
- diagnostic context of its parent.
-
- <p>The MDC class requires JDK 1.2 or above. Under JDK 1.1 the MDC
- will always return empty values but otherwise will not affect or
- harm your application.
- */
- class LOG4CXX_EXPORT MDC
- {
- public:
- /** String to string stl mp
- */
- typedef std::map<LogString, LogString> Map;
-
- private:
- static Map * getCurrentThreadMap();
- static void setCurrentThreadMap(Map * map);
-
- static helpers::ThreadSpecificData threadSpecificData;
- const LogString& key;
-
- public:
- MDC(const LogString& key, const LogString& value);
- ~MDC();
-
- /**
- * Put a context value (the <code>o</code> parameter) as
identified
- * with the <code>key</code> parameter into the current thread's
- * context map.
- *
- * <p>If the current thread does not have a context map it is
- * created as a side effect.
- * */
- static void put(const std::wstring& key, const std::wstring&
value);
+ /**
+ The MDC class is similar to the [EMAIL PROTECTED] NDC} class except
that it is
+ based on a map instead of a stack. It provides <em>mapped
+ diagnostic contexts</em>. A <em>Mapped Diagnostic Context</em>, or
+ MDC in short, is an instrument for distinguishing interleaved log
+ output from different sources. Log output is typically interleaved
+ when a server handles multiple clients near-simultaneously.
+
+ <p><b><em>The MDC is managed on a per thread basis</em></b>. A
+ child thread automatically inherits a <em>copy</em> of the mapped
+ diagnostic context of its parent.
+
+ <p>The MDC class requires JDK 1.2 or above. Under JDK 1.1 the MDC
+ will always return empty values but otherwise will not affect or
+ harm your application.
+ */
+ class LOG4CXX_EXPORT MDC
+ {
+ public:
+ /** String to string stl mp
+ */
+ typedef std::map<LogString, LogString> Map;
+
+ private:
+ const LogString& key;
+
+ public:
+ MDC(const LogString& key, const LogString& value);
+ ~MDC();
+
+ /**
+ * Put a context value (the <code>o</code> parameter) as
identified
+ * with the <code>key</code> parameter into the current
thread's
+ * context map.
+ *
+ * <p>If the current thread does not have a context map it is
+ * created as a side effect.
+ * */
+ static void put(const std::wstring& key, const std::wstring&
value);
static void put(const std::string& key, const std::string&
value);
static void putLogString(const LogString& key, const
LogString& value);
- /**
- * Get the context identified by the <code>key</code> parameter.
- *
- * <p>This method has no side effects.
- * */
- static std::wstring get(const std::wstring& key);
+ /**
+ * Get the context identified by the <code>key</code>
parameter.
+ *
+ * <p>This method has no side effects.
+ * */
+ static std::wstring get(const std::wstring& key);
static std::string get(const std::string& key);
static bool get(const LogString& key, LogString& value);
- /**
- * Remove the the context identified by the <code>key</code>
- * parameter. */
- static std::string remove(const std::string& key);
+ /**
+ * Remove the the context identified by the <code>key</code>
+ * parameter. */
+ static std::string remove(const std::string& key);
static std::wstring remove(const std::wstring& key);
static bool remove(const LogString& key, LogString&
prevValue);
- /**
- * Clear all entries in the MDC.
- */
- static void clear();
-
- /**
- * Get the current thread's MDC as a Map. This method is
- * intended to be used internally.
- * */
- static const Map getContext();
+ /**
+ * Clear all entries in the MDC.
+ */
+ static void clear();
+
+ /**
+ * Get the current thread's MDC as a Map. This method is
+ * intended to be used internally.
+ * */
+// static const Map getContext();
- static void setContext(Map& map);
+// static void setContext(Map& map);
- }; // class MDC;
+ }; // class MDC;
} // namespace log4cxx
#endif // _LOG4CXX_MDC_H
1.10 +183 -188 logging-log4cxx/include/log4cxx/ndc.h
Index: ndc.h
===================================================================
RCS file: /home/cvs/logging-log4cxx/include/log4cxx/ndc.h,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- ndc.h 12 Dec 2004 05:53:57 -0000 1.9
+++ ndc.h 4 Jan 2005 03:37:07 -0000 1.10
@@ -1,5 +1,5 @@
/*
- * Copyright 2003,2004 The Apache Software Foundation.
+ * Copyright 2003-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,202 +17,197 @@
#ifndef _LOG4CXX_NDC_H
#define _LOG4CXX_NDC_H
+#include <log4cxx/portability.h>
#include <log4cxx/logstring.h>
-#include <log4cxx/helpers/threadspecificdata.h>
#include <stack>
namespace log4cxx
{
- class DiagnosticContext;
- typedef std::stack<DiagnosticContext> Stack;
+ class DiagnosticContext;
+ typedef std::stack<DiagnosticContext> Stack;
- /**
- the ndc class implements <i>nested diagnostic contexts</i> as
- defined by neil harrison in the article "patterns for logging
- diagnostic messages" part of the book "<i>pattern languages of
- program design 3</i>" edited by martin et al.
-
- <p>a nested diagnostic context, or ndc in short, is an instrument
- to distinguish interleaved log output from different sources. log
- output is typically interleaved when a server handles multiple
- clients near-simultaneously.
-
- <p>interleaved log output can still be meaningful if each log entry
- from different contexts had a distinctive stamp. this is where ndcs
- come into play.
-
- <p><em><b>note that ndcs are managed on a per thread
- basis</b></em>. ndc operations such as #push,
- #pop, #clear and #getDepth
- affect the ndc of the <em>current</em> thread only. ndcs of other
- threads remain unaffected.
-
- <p>for example, a servlet can build a per client request ndc
- consisting the clients host name and other information contained in
- the the request. <em>cookies</em> are another source of distinctive
- information. to build an ndc one uses the #push
- operation. simply put,
-
- <p><ul>
- <li>contexts can be nested.
-
- <p><li>when entering a context, call <code>ndc.push</code>. as a
- side effect, if there is no nested diagnostic context for the
- current thread, this method will create it.
-
- <p><li>when leaving a context, call <code>ndc.pop</code>.
-
- <p><li><b>when exiting a thread make sure to call #remove
- </b>.
- </ul>
-
- <p>there is no penalty for forgetting to match each
- <code>push</code> operation with a corresponding <code>pop</code>,
- except the obvious mismatch between the real application context
- and the context set in the ndc.
-
- <p>if configured to do so, PatternLayout and
- TTCCLayout instances automatically retrieve the nested diagnostic
- context for the current thread without any user intervention.
- hence, even if a servlet is serving multiple clients
- simultaneously, the logs emanating from the same code (belonging to
- the same category) can still be distinguished because each client
- request will have a different ndc tag.
-
- <p>heavy duty systems should call the #remove method when
- leaving the run method of a thread. this ensures that the memory
- used by the thread can be freed by the java garbage
- collector. there is a mechanism to lazily remove references to dead
- threads. in practice, this means that you can be a little sloppy
- and sometimes forget to call #remove before exiting a
- thread.
-
- <p>a thread may inherit the nested diagnostic context of another
- (possibly parent) thread using the #inherit
- method. a thread may obtain a copy of its ndc with the
- #clonestack method and pass the reference to any other
- thread, in particular to a child.
- */
- class LOG4CXX_EXPORT NDC
- {
- private:
- class DiagnosticContext
- {
- public:
- LogString fullMessage;
- LogString message;
-
- DiagnosticContext(const LogString& message,
- const DiagnosticContext * parent);
- };
-
- typedef std::stack<DiagnosticContext> Stack;
-
- static Stack * getCurrentThreadStack();
- static void setCurrentThreadStack(Stack * stack);
-
- static helpers::ThreadSpecificData_ptr<Stack>
threadSpecificData;
-
- public:
- NDC(const LogString& message);
- ~NDC();
-
- /**
- Clear any nested diagnostic information if any. This method is
- useful in cases where the same thread can be potentially used
- over and over in different unrelated contexts.
- <p>This method is equivalent to calling the #setMaxDepth
- method with a zero <code>maxDepth</code> argument.
- */
- static void clear();
-
- /**
- Clone the diagnostic context for the current thread.
- <p>Internally a diagnostic context is represented as a stack. A
- given thread can supply the stack (i.e. diagnostic context) to a
- child thread so that the child can inherit the parent thread's
- diagnostic context.
- <p>The child thread uses the #inherit method to
- inherit the parent's diagnostic context.
- @return Stack A clone of the current thread's diagnostic
context.
- */
- static Stack * cloneStack();
-
- /**
- Inherit the diagnostic context of another thread.
- <p>The parent thread can obtain a reference to its diagnostic
- context using the #cloneStack method. It should
- communicate this information to its child so that it may inherit
- the parent's diagnostic context.
- <p>The parent's diagnostic context is cloned before being
- inherited. In other words, once inherited, the two diagnostic
- contexts can be managed independently.
- <p>In java, a child thread cannot obtain a reference to its
- parent, unless it is directly handed the reference.
Consequently,
- there is no client-transparent way of inheriting diagnostic
- contexts. Do you know any solution to this problem?
- @param stack The diagnostic context of the parent thread.
- */
- static void inherit(Stack * stack);
-
- /**
- <b>Never use this method directly, use the
- [EMAIL PROTECTED] spi::LoggingEvent#getNDC LoggingEvent::getNDC}
- method instead.</b>
- */
- static LogString get();
-
- /**
- Get the current nesting depth of this diagnostic context.
- */
- static int getDepth();
-
- /**
- Clients should call this method before leaving a diagnostic
- context.
- <p>The returned value is the value that was pushed last. If no
- context is available, then the empty string "" is returned.
- @return String The innermost diagnostic context.
- */
- static LogString pop();
-
- /**
- Looks at the last diagnostic context at the top of this NDC
- without removing it.
- <p>The returned value is the value that was pushed last. If no
- context is available, then the empty string "" is returned.
- @return String The innermost diagnostic context.
- */
- static LogString peek();
-
- /**
- Push new diagnostic context information for the current thread.
- <p>The contents of the <code>message</code> parameter is
- determined solely by the client.
- @param message The new diagnostic context information.
- */
- static void push(const std::wstring& message);
+ /**
+ the ndc class implements <i>nested diagnostic contexts</i> as
+ defined by neil harrison in the article "patterns for logging
+ diagnostic messages" part of the book "<i>pattern languages of
+ program design 3</i>" edited by martin et al.
+
+ <p>a nested diagnostic context, or ndc in short, is an instrument
+ to distinguish interleaved log output from different sources. log
+ output is typically interleaved when a server handles multiple
+ clients near-simultaneously.
+
+ <p>interleaved log output can still be meaningful if each log entry
+ from different contexts had a distinctive stamp. this is where ndcs
+ come into play.
+
+ <p><em><b>note that ndcs are managed on a per thread
+ basis</b></em>. ndc operations such as #push,
+ #pop, #clear and #getDepth
+ affect the ndc of the <em>current</em> thread only. ndcs of other
+ threads remain unaffected.
+
+ <p>for example, a servlet can build a per client request ndc
+ consisting the clients host name and other information contained in
+ the the request. <em>cookies</em> are another source of distinctive
+ information. to build an ndc one uses the #push
+ operation. simply put,
+
+ <p><ul>
+ <li>contexts can be nested.
+
+ <p><li>when entering a context, call <code>ndc.push</code>. as a
+ side effect, if there is no nested diagnostic context for the
+ current thread, this method will create it.
+
+ <p><li>when leaving a context, call <code>ndc.pop</code>.
+
+ <p><li><b>when exiting a thread make sure to call #remove
+ </b>.
+ </ul>
+
+ <p>there is no penalty for forgetting to match each
+ <code>push</code> operation with a corresponding <code>pop</code>,
+ except the obvious mismatch between the real application context
+ and the context set in the ndc.
+
+ <p>if configured to do so, PatternLayout and
+ TTCCLayout instances automatically retrieve the nested diagnostic
+ context for the current thread without any user intervention.
+ hence, even if a servlet is serving multiple clients
+ simultaneously, the logs emanating from the same code (belonging to
+ the same category) can still be distinguished because each client
+ request will have a different ndc tag.
+
+ <p>heavy duty systems should call the #remove method when
+ leaving the run method of a thread. this ensures that the memory
+ used by the thread can be freed by the java garbage
+ collector. there is a mechanism to lazily remove references to dead
+ threads. in practice, this means that you can be a little sloppy
+ and sometimes forget to call #remove before exiting a
+ thread.
+
+ <p>a thread may inherit the nested diagnostic context of another
+ (possibly parent) thread using the #inherit
+ method. a thread may obtain a copy of its ndc with the
+ #clonestack method and pass the reference to any other
+ thread, in particular to a child.
+ */
+ class LOG4CXX_EXPORT NDC
+ {
+ private:
+ class DiagnosticContext
+ {
+ public:
+ LogString fullMessage;
+ LogString message;
+
+ DiagnosticContext(const LogString& message,
+ const DiagnosticContext * parent);
+ };
+
+ public:
+ typedef std::stack<DiagnosticContext> Stack;
+
+ NDC(const LogString& message);
+ ~NDC();
+
+ /**
+ Clear any nested diagnostic information if any. This method
is
+ useful in cases where the same thread can be potentially used
+ over and over in different unrelated contexts.
+ <p>This method is equivalent to calling the #setMaxDepth
+ method with a zero <code>maxDepth</code> argument.
+ */
+ static void clear();
+
+ /**
+ Clone the diagnostic context for the current thread.
+ <p>Internally a diagnostic context is represented as a
stack. A
+ given thread can supply the stack (i.e. diagnostic context)
to a
+ child thread so that the child can inherit the parent
thread's
+ diagnostic context.
+ <p>The child thread uses the #inherit method to
+ inherit the parent's diagnostic context.
+ @return Stack A clone of the current thread's diagnostic
context.
+ */
+// static Stack * cloneStack();
+
+ /**
+ Inherit the diagnostic context of another thread.
+ <p>The parent thread can obtain a reference to its diagnostic
+ context using the #cloneStack method. It should
+ communicate this information to its child so that it may
inherit
+ the parent's diagnostic context.
+ <p>The parent's diagnostic context is cloned before being
+ inherited. In other words, once inherited, the two diagnostic
+ contexts can be managed independently.
+ <p>In java, a child thread cannot obtain a reference to its
+ parent, unless it is directly handed the reference.
Consequently,
+ there is no client-transparent way of inheriting diagnostic
+ contexts. Do you know any solution to this problem?
+ @param stack The diagnostic context of the parent thread.
+ */
+// static void inherit(Stack * stack);
+
+ /**
+ <b>Never use this method directly, use the
+ [EMAIL PROTECTED] spi::LoggingEvent#getNDC
LoggingEvent::getNDC}
+ method instead.</b>
+ */
+ static LogString get();
+
+ /**
+ Get the current nesting depth of this diagnostic context.
+ */
+ static int getDepth();
+
+ /**
+ Clients should call this method before leaving a diagnostic
+ context.
+ <p>The returned value is the value that was pushed last. If
no
+ context is available, then the empty string "" is returned.
+ @return String The innermost diagnostic context.
+ */
+ static LogString pop();
+
+ /**
+ Looks at the last diagnostic context at the top of this NDC
+ without removing it.
+ <p>The returned value is the value that was pushed last. If
no
+ context is available, then the empty string "" is returned.
+ @return String The innermost diagnostic context.
+ */
+ static LogString peek();
+
+ /**
+ Push new diagnostic context information for the current
thread.
+ <p>The contents of the <code>message</code> parameter is
+ determined solely by the client.
+ @param message The new diagnostic context information.
+ */
+ static void push(const std::wstring& message);
static void push(const std::string& message);
static void pushLogString(const LogString& message);
- /**
- Remove the diagnostic context for this thread.
- <p>Each thread that created a diagnostic context by calling
- #push should call this method before exiting. Otherwise,
- the memory used by the <b>thread</b> cannot be reclaimed by the
- VM.
- <p>As this is such an important problem in heavy duty systems
and
- because it is difficult to always guarantee that the remove
- method is called before exiting a thread, this method has been
- augmented to lazily remove references to dead threads. In
- practice, this means that you can be a little sloppy and
- occasionally forget to call #remove before exiting a
- thread. However, you must call <code>remove</code> sometime. If
- you never call it, then your application is sure to run out of
- memory.
- */
- static void remove();
- }; // class NDC;
+ /**
+ Remove the diagnostic context for this thread.
+ <p>Each thread that created a diagnostic context by calling
+ #push should call this method before exiting. Otherwise,
+ the memory used by the <b>thread</b> cannot be reclaimed by
the
+ VM.
+ <p>As this is such an important problem in heavy duty
systems and
+ because it is difficult to always guarantee that the remove
+ method is called before exiting a thread, this method has
been
+ augmented to lazily remove references to dead threads. In
+ practice, this means that you can be a little sloppy and
+ occasionally forget to call #remove before exiting a
+ thread. However, you must call <code>remove</code> sometime.
If
+ you never call it, then your application is sure to run out
of
+ memory.
+ */
+ static void remove();
+ }; // class NDC;
} // namespace log4cxx
#endif // _LOG4CXX_NDC_H
1.8 +1 -1 logging-log4cxx/include/log4cxx/stream.h
Index: stream.h
===================================================================
RCS file: /home/cvs/logging-log4cxx/include/log4cxx/stream.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- stream.h 26 Dec 2004 07:31:52 -0000 1.7
+++ stream.h 4 Jan 2005 03:37:07 -0000 1.8
@@ -108,9 +108,9 @@
if (0 == impl) {
impl = new ::std::wostringstream();
}
+ impl->flags(flags());
impl->precision(precision());
impl->width(width());
- impl->flags(flags());
return *impl;
}
1.9 +5 -0 logging-log4cxx/include/log4cxx/helpers/aprinitializer.h
Index: aprinitializer.h
===================================================================
RCS file: /home/cvs/logging-log4cxx/include/log4cxx/helpers/aprinitializer.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- aprinitializer.h 2 Jan 2005 05:40:04 -0000 1.8
+++ aprinitializer.h 4 Jan 2005 03:37:07 -0000 1.9
@@ -20,6 +20,7 @@
#include <log4cxx/portability.h>
#include <log4cxx/helpers/pool.h>
#include <apr_pools.h>
+#include <apr_thread_proc.h>
namespace log4cxx
{
@@ -30,6 +31,7 @@
public:
static log4cxx_time_t initialize();
static apr_pool_t* getRootPool();
+ static apr_threadkey_t* getTlsKey();
static bool isDestructed;
private:
@@ -38,7 +40,10 @@
APRInitializer& operator=(const APRInitializer&);
apr_pool_t* p;
log4cxx_time_t startTime;
+ apr_threadkey_t* tlsKey;
static APRInitializer& getInstance();
+ static void tlsDestruct(void*);
+
public:
~APRInitializer();
};
1.13 +14 -59
logging-log4cxx/include/log4cxx/helpers/threadspecificdata.h
Index: threadspecificdata.h
===================================================================
RCS file:
/home/cvs/logging-log4cxx/include/log4cxx/helpers/threadspecificdata.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- threadspecificdata.h 15 Dec 2004 00:38:47 -0000 1.12
+++ threadspecificdata.h 4 Jan 2005 03:37:07 -0000 1.13
@@ -17,78 +17,33 @@
#ifndef _LOG4CXX_HELPERS_THREAD_SPECIFIC_DATA_H
#define _LOG4CXX_HELPERS_THREAD_SPECIFIC_DATA_H
-#include <log4cxx/portability.h>
-#include <memory>
+#include <log4cxx/ndc.h>
+#include <log4cxx/mdc.h>
+
namespace log4cxx
{
namespace helpers
{
+ /**
+ * This class contains all the thread-specific
+ * data in use by log4cxx.
+ */
class LOG4CXX_EXPORT ThreadSpecificData
{
public:
ThreadSpecificData();
- ThreadSpecificData(void (*cleanup)(void*));
~ThreadSpecificData();
- void * GetData() const;
- void SetData(void * data);
-
- protected:
- struct Impl;
- std::auto_ptr<Impl> impl;
- };
-
- template < typename T >
- class ThreadSpecificData_ptr
- {
- public:
- ThreadSpecificData_ptr(T * p = 0):
impl(&cleanup)
- {
- reset(p);
- }
-
- T * get() const
- {
- return static_cast<T*>(
impl.GetData() );
- }
- void reset(T * p = 0)
- {
- T * tmp = get();
- if(tmp)
- delete tmp;
- impl.SetData(p);
- }
+ static log4cxx::NDC::Stack& getCurrentThreadStack();
+ static log4cxx::MDC::Map& getCurrentThreadMap();
- operator T * () const
- {
- return get();
- }
-
- T * operator->() const
- {
- return get();
- }
-
- T & operator*() const
- {
- return *get();
- }
-
- T * release()
- {
- T * tmp = get();
- impl.SetData(0);
- return tmp;
- }
+ private:
+ static ThreadSpecificData& getCurrentData();
+ log4cxx::NDC::Stack ndcStack;
+ log4cxx::MDC::Map mdcMap;
+ };
- private:
- ThreadSpecificData impl;
- static void cleanup(void * p)
- {
- delete static_cast<T*>(p);
- }
- };
} // namespace helpers
} // namespace log4cxx
1.14 +2 -9 logging-log4cxx/performance/main.cpp
Index: main.cpp
===================================================================
RCS file: /home/cvs/logging-log4cxx/performance/main.cpp,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- main.cpp 15 Dec 2004 08:10:39 -0000 1.13
+++ main.cpp 4 Jan 2005 03:37:07 -0000 1.14
@@ -1,5 +1,5 @@
/*
- * Copyright 2003,2004 The Apache Software Foundation.
+ * Copyright 2003-2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,13 +52,6 @@
exit(EXIT_FAILURE);
}
-class IllegalRunLengthException : public IllegalArgumentException {
- public:
- IllegalRunLengthException() throw() {}
- const char* what() const throw() {
- return "run Length must be greater than 0";
- }
-};
void init(const std::string& configFile, const std::string& runLengthStr,
const std::string& delayStr, const std::string&
burstLenStr)
@@ -66,7 +59,7 @@
runLength = atoi(runLengthStr.c_str());
if (runLength < 1)
{
- throw IllegalRunLengthException();
+ throw IllegalArgumentException("run Length must be greater
than 0");
}
if (!delayStr.empty())
{
1.6 +11 -0 logging-log4cxx/src/aprinitializer.cpp
Index: aprinitializer.cpp
===================================================================
RCS file: /home/cvs/logging-log4cxx/src/aprinitializer.cpp,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- aprinitializer.cpp 2 Jan 2005 05:40:04 -0000 1.5
+++ aprinitializer.cpp 4 Jan 2005 03:37:07 -0000 1.6
@@ -18,6 +18,8 @@
#include <apr_pools.h>
#include <apr_atomic.h>
#include <apr_time.h>
+#include <assert.h>
+#include <log4cxx/helpers/threadspecificdata.h>
using namespace log4cxx::helpers;
using namespace log4cxx;
@@ -29,6 +31,8 @@
apr_pool_create(&p, NULL);
apr_atomic_init(p);
startTime = apr_time_now();
+ apr_status_t stat = apr_threadkey_private_create(&tlsKey, tlsDestruct,
p);
+ assert(stat == APR_SUCCESS);
}
APRInitializer::~APRInitializer() {
@@ -57,3 +61,10 @@
return getInstance().p;
}
+apr_threadkey_t* APRInitializer::getTlsKey() {
+ return getInstance().tlsKey;
+}
+
+void APRInitializer::tlsDestruct(void* ptr) {
+ delete ((ThreadSpecificData*) ptr);
+}
1.23 +3 -2 logging-log4cxx/src/loggingevent.cpp
Index: loggingevent.cpp
===================================================================
RCS file: /home/cvs/logging-log4cxx/src/loggingevent.cpp,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- loggingevent.cpp 2 Jan 2005 05:40:05 -0000 1.22
+++ loggingevent.cpp 4 Jan 2005 03:37:07 -0000 1.23
@@ -25,6 +25,7 @@
#include <log4cxx/helpers/loader.h>
#include <log4cxx/helpers/socket.h>
#include <log4cxx/helpers/aprinitializer.h>
+#include <log4cxx/helpers/threadspecificdata.h>
#include <apr_time.h>
#include <apr_portable.h>
@@ -127,7 +128,7 @@
}
else
{
- MDC::Map m = MDC::getContext();
+ MDC::Map& m = ThreadSpecificData::getCurrentThreadMap();
MDC::Map::const_iterator it;
for (it = m.begin(); it != m.end(); it++)
@@ -145,7 +146,7 @@
{
((LoggingEvent *)this)->mdcCopyLookupRequired = false;
// the clone call is required for asynchronous logging.
- ((LoggingEvent *)this)->mdcCopy = MDC::getContext();
+ ((LoggingEvent *)this)->mdcCopy =
ThreadSpecificData::getCurrentThreadMap();
}
}
1.7 +21 -72 logging-log4cxx/src/mdc.cpp
Index: mdc.cpp
===================================================================
RCS file: /home/cvs/logging-log4cxx/src/mdc.cpp,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- mdc.cpp 11 Dec 2004 04:53:25 -0000 1.6
+++ mdc.cpp 4 Jan 2005 03:37:07 -0000 1.7
@@ -16,43 +16,25 @@
#include <log4cxx/mdc.h>
#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/threadspecificdata.h>
using namespace log4cxx;
using namespace log4cxx::helpers;
-helpers::ThreadSpecificData MDC::threadSpecificData;
-
MDC::MDC(const LogString& key, const LogString& value) : key(key)
{
- put(key, value);
+ put(key, value);
}
MDC::~MDC()
{
- remove(key);
-}
-
-MDC::Map * MDC::getCurrentThreadMap()
-{
- return (MDC::Map *)threadSpecificData.GetData();
-}
-
-void MDC::setCurrentThreadMap(MDC::Map * map)
-{
- threadSpecificData.SetData((void *)map);
+ remove(key);
}
void MDC::putLogString(const LogString& key, const LogString& value)
{
- Map * map = getCurrentThreadMap();
-
- if (map == 0)
- {
- map = new Map;
- setCurrentThreadMap(map);
- }
-
- (*map)[key] = value;
+ Map& map = ThreadSpecificData::getCurrentThreadMap();
+ map[key] = value;
}
@@ -72,17 +54,13 @@
bool MDC::get(const LogString& key, LogString& value)
{
- Map::iterator it;
- Map * map = getCurrentThreadMap();
+ Map& map = ThreadSpecificData::getCurrentThreadMap();
- if (map != 0)
- {
- Map::iterator it = map->find(key);
- if (it != map->end()) {
- value = it->second;
- return true;
- }
- }
+ Map::iterator it = map.find(key);
+ if (it != map.end()) {
+ value = it->second;
+ return true;
+ }
return false;
}
@@ -111,14 +89,14 @@
bool MDC::remove(const LogString& key, LogString& value)
{
- Map::iterator it;
- Map * map = getCurrentThreadMap();
- if (map != 0 && (it = map->find(key)) != map->end())
- {
- value = it->second;
- map->erase(it);
+ Map::iterator it;
+ Map& map = ThreadSpecificData::getCurrentThreadMap();
+ if ((it = map.find(key)) != map.end())
+ {
+ value = it->second;
+ map.erase(it);
return true;
- }
+ }
return false;
}
@@ -147,36 +125,7 @@
void MDC::clear()
{
- Map * map = getCurrentThreadMap();
- if(map != 0)
- {
- delete map;
- setCurrentThreadMap(0);
- }
-}
-
-const MDC::Map MDC::getContext()
-{
- Map * map = getCurrentThreadMap();
- if(map != 0)
- {
- return *map;
- }
- else
- {
- return Map();
- }
-}
-
-void MDC::setContext(Map& map)
-{
- Map * currentMap = getCurrentThreadMap();
-
- if (currentMap == 0)
- {
- currentMap = new Map;
- setCurrentThreadMap(currentMap);
- }
-
- *currentMap = map;
+ Map& map = ThreadSpecificData::getCurrentThreadMap();
+ map.erase(map.begin(), map.end());
}
+
1.8 +58 -85 logging-log4cxx/src/ndc.cpp
Index: ndc.cpp
===================================================================
RCS file: /home/cvs/logging-log4cxx/src/ndc.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- ndc.cpp 11 Dec 2004 04:53:25 -0000 1.7
+++ ndc.cpp 4 Jan 2005 03:37:07 -0000 1.8
@@ -16,141 +16,114 @@
#include <log4cxx/ndc.h>
#include <log4cxx/helpers/transcoder.h>
+#include <log4cxx/helpers/threadspecificdata.h>
using namespace log4cxx;
using namespace log4cxx::helpers;
NDC::DiagnosticContext::DiagnosticContext(const LogString& message,
- const DiagnosticContext * parent)
- : message(message)
+ const DiagnosticContext * parent)
+ : message(message), fullMessage(message)
{
- if (parent != 0)
- {
- fullMessage = parent->fullMessage + LOG4CXX_STR(' ') + message;
- }
- else
- {
- fullMessage = message;
- }
+ if (parent != 0)
+ {
+ fullMessage.insert(0, 1, LOG4CXX_STR(' '));
+ fullMessage.insert(0, parent->fullMessage);
+ }
}
-// static member instanciation
-ThreadSpecificData_ptr<NDC::Stack> NDC::threadSpecificData;
-
NDC::NDC(const LogString& message)
{
- push(message);
+ push(message);
}
NDC::~NDC()
{
- pop();
-}
-
-NDC::Stack * NDC::getCurrentThreadStack()
-{
- return threadSpecificData;
+ pop();
}
-void NDC::setCurrentThreadStack(NDC::Stack * stack)
-{
- threadSpecificData.reset(stack);
-}
void NDC::clear()
{
- setCurrentThreadStack(0);
+ Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ while(!stack.empty()) {
+ stack.pop();
+ }
}
+#if 0
NDC::Stack * NDC::cloneStack()
{
- Stack * stack = getCurrentThreadStack();
- if(stack != 0)
- {
- return new Stack(*stack);
- }
- else
- {
- return new Stack();
- }
+ Stack * stack = getCurrentThreadStack();
+ if(stack != 0)
+ {
+ return new Stack(*stack);
+ }
+ else
+ {
+ return new Stack();
+ }
}
void NDC::inherit(NDC::Stack * stack)
{
- if(stack != 0)
- {
- setCurrentThreadStack(stack);
- }
+ if(stack != 0)
+ {
+ setCurrentThreadStack(stack);
+ }
}
+#endif
LogString NDC::get()
{
- Stack * stack = getCurrentThreadStack();
- if(stack != 0 && !stack->empty())
- {
- return stack->top().fullMessage;
- }
+ Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ if(!stack.empty())
+ {
+ return stack.top().fullMessage;
+ }
return LogString();
}
int NDC::getDepth()
{
- Stack * stack = getCurrentThreadStack();
- if(stack == 0)
- {
- return 0;
- }
- else
- {
- return stack->size();
- }
+ return ThreadSpecificData::getCurrentThreadStack().size();
}
LogString NDC::pop()
{
- Stack * stack = getCurrentThreadStack();
- if(stack != 0 && !stack->empty())
- {
- LogString value(stack->top().message);
- stack->pop();
- if (stack->empty())
- {
- setCurrentThreadStack(0);
- }
+ Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ if(!stack.empty())
+ {
+ LogString value(stack.top().message);
+ stack.pop();
return value;
- }
+ }
return LogString();
}
LogString NDC::peek()
{
- Stack * stack = getCurrentThreadStack();
- if(stack != 0 && !stack->empty())
- {
- return stack->top().message;
- }
+ Stack& stack = ThreadSpecificData::getCurrentThreadStack();
+ if(!stack.empty())
+ {
+ return stack.top().message;
+ }
return LogString();
}
void NDC::pushLogString(const LogString& message)
{
- Stack * stack = getCurrentThreadStack();
+ Stack& stack = ThreadSpecificData::getCurrentThreadStack();
- if (stack == 0)
- {
- stack = new Stack;
- setCurrentThreadStack(stack);
- stack->push(DiagnosticContext(message, 0));
- }
- else if (stack->empty())
- {
- stack->push(DiagnosticContext(message, 0));
- }
- else
- {
- DiagnosticContext& parent = stack->top();
- stack->push(DiagnosticContext(message, &parent));
- }
+ if (stack.empty())
+ {
+ stack.push(DiagnosticContext(message, 0));
+ }
+ else
+ {
+ DiagnosticContext& parent = stack.top();
+ stack.push(DiagnosticContext(message, &parent));
+ }
}
void NDC::push(const std::string& message)
@@ -165,8 +138,8 @@
pushLogString(msg);
}
-
void NDC::remove()
{
- setCurrentThreadStack(0);
+ clear();
}
+
1.10 +30 -62 logging-log4cxx/src/threadspecificdata.cpp
Index: threadspecificdata.cpp
===================================================================
RCS file: /home/cvs/logging-log4cxx/src/threadspecificdata.cpp,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- threadspecificdata.cpp 26 Oct 2004 18:12:28 -0000 1.9
+++ threadspecificdata.cpp 4 Jan 2005 03:37:07 -0000 1.10
@@ -1,88 +1,56 @@
/*
* Copyright 2003,2004 The Apache Software Foundation.
- *
+ *
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#include <log4cxx/portability.h>
-
-#ifdef LOG4CXX_HAVE_PTHREAD
-#include <pthread.h>
-#elif defined(LOG4CXX_HAVE_MS_THREAD)
-#include <windows.h>
-#endif
+#include <log4cxx/portability.h>
#include <log4cxx/helpers/threadspecificdata.h>
+#include <log4cxx/helpers/aprinitializer.h>
+#include <log4cxx/helpers/exception.h>
using namespace log4cxx::helpers;
-struct ThreadSpecificData::Impl
-{
- Impl(): key(0) {}
-#ifdef LOG4CXX_HAVE_PTHREAD
- pthread_key_t key;
-//#elif defined(LOG4CXX_HAVE_MS_THREAD)
-#else
- void * key;
-#endif
-};
-
-ThreadSpecificData::ThreadSpecificData() : impl(new Impl)
-{
-#ifdef LOG4CXX_HAVE_PTHREAD
- pthread_key_create(&impl->key, NULL);
-#elif defined(LOG4CXX_HAVE_MS_THREAD)
- impl->key = (void *)TlsAlloc();
-#endif
+ThreadSpecificData::ThreadSpecificData()
+ : ndcStack(), mdcMap() {
}
-ThreadSpecificData::ThreadSpecificData(void (*cleanup)(void*)): impl(new
Impl)
-{
-#ifdef LOG4CXX_HAVE_PTHREAD
- pthread_key_create(&impl->key, cleanup);
-#elif defined(LOG4CXX_HAVE_MS_THREAD)
- impl->key = (void *)TlsAlloc();
-#endif
+ThreadSpecificData::~ThreadSpecificData() {
}
-ThreadSpecificData::~ThreadSpecificData()
-{
-#ifdef LOG4CXX_HAVE_PTHREAD
- pthread_key_delete(impl->key);
-#elif defined(LOG4CXX_HAVE_MS_THREAD)
- TlsFree((DWORD)impl->key);
-#endif
-}
-void * ThreadSpecificData::GetData() const
-{
-#ifdef LOG4CXX_HAVE_PTHREAD
- return pthread_getspecific((pthread_key_t)impl->key);
-#elif defined(LOG4CXX_HAVE_MS_THREAD)
- return TlsGetValue((DWORD)impl->key);
-#else
- return impl->key;
-#endif
+log4cxx::NDC::Stack& ThreadSpecificData::getCurrentThreadStack() {
+ return getCurrentData().ndcStack;
}
-void ThreadSpecificData::SetData(void * data)
-{
-#ifdef LOG4CXX_HAVE_PTHREAD
- pthread_setspecific((pthread_key_t)impl->key, data);
-#elif defined(LOG4CXX_HAVE_MS_THREAD)
- TlsSetValue((DWORD)impl->key, data);
-#else
- impl->key = data;
-#endif
+log4cxx::MDC::Map& ThreadSpecificData::getCurrentThreadMap() {
+ return getCurrentData().mdcMap;
}
+ThreadSpecificData& ThreadSpecificData::getCurrentData() {
+ void* pData = NULL;
+ apr_status_t stat = apr_threadkey_private_get(&pData,
APRInitializer::getTlsKey());
+ if (stat != APR_SUCCESS) {
+ throw ThreadException(stat);
+ }
+ if (pData == NULL) {
+ ThreadSpecificData* newData = new ThreadSpecificData();
+ stat = apr_threadkey_private_set(newData, APRInitializer::getTlsKey());
+ if (stat != APR_SUCCESS) {
+ delete newData;
+ throw ThreadException(stat);
+ }
+ return *newData;
+ }
+ return *((ThreadSpecificData*) pData);
+}