logging-log4cxx-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From carn...@apache.org
Subject cvs commit: logging-log4cxx/src aprinitializer.cpp loggingevent.cpp mdc.cpp ndc.cpp threadspecificdata.cpp
Date Tue, 04 Jan 2005 03:37:07 GMT
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 {@link 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 {@link 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
  -		{@link 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
  +                {@link 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);
  +}
  
  
  

Mime
View raw message