You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by sw...@apache.org on 2026/10/19 04:41:38 UTC

(logging-log4cxx) branch simplify_thread_utility created (now 8b90f794)

This is an automated email from the ASF dual-hosted git repository.

swebb2066 pushed a change to branch simplify_thread_utility
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git


      at 8b90f794 Add item to list of behaviour changes

This branch includes the following new commits:

     new 04ada95c Simplify ThreadUtility class interface
     new 4978e3eb Merge branch 'master' into simplify_thread_utility
     new 8b90f794 Add item to list of behaviour changes

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(logging-log4cxx) 03/03: Add item to list of behaviour changes

Posted by sw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

swebb2066 pushed a commit to branch simplify_thread_utility
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git

commit 8b90f794b0c59b7ed2c6948991e86708bc84277b
Author: Stephen Webb <sw...@gmail.com>
AuthorDate: Mon Oct 19 15:41:13 2026 +1100

    Add item to list of behaviour changes
---
 src/site/markdown/change-report-gh.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/site/markdown/change-report-gh.md b/src/site/markdown/change-report-gh.md
index f12dc9d4..64c0542d 100644
--- a/src/site/markdown/change-report-gh.md
+++ b/src/site/markdown/change-report-gh.md
@@ -115,6 +115,9 @@ The other Log4cxx behaviour changes are:
 Instead, use 'LOG4CXX_CONFIGURATION' and 'LOG4CXX_CONFIGURATOR_CLASS'.
   \[[#784](https://github.com/apache/logging-log4cxx/pull/784)\]
 
+* Threads created by Log4cxx are assigned a name. Call log4cxx::helpers::ThreadUtility::configure to alter this behaviour.
+  \[[#785](https://github.com/apache/logging-log4cxx/pull/785)\]
+
 ## Release 1.8.0 - 2026-07-29 {#rel_1_8_0}
 
 Release 1.8.0 includes the following new features:


(logging-log4cxx) 01/03: Simplify ThreadUtility class interface

Posted by sw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

swebb2066 pushed a commit to branch simplify_thread_utility
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git

commit 04ada95c76a2e16aae51be2181a2ebcd62bc7728
Author: Stephen Webb <sw...@gmail.com>
AuthorDate: Mon Oct 19 15:32:19 2026 +1100

    Simplify ThreadUtility class interface
---
 src/main/cpp/threadutility.cpp                   | 166 ++++++++++++++---------
 src/main/include/log4cxx/helpers/threadutility.h | 108 ++++++---------
 src/site/markdown/threading.md                   |   2 +-
 src/test/cpp/helpers/threadutilitytestcase.cpp   |   3 +-
 4 files changed, 147 insertions(+), 132 deletions(-)

diff --git a/src/main/cpp/threadutility.cpp b/src/main/cpp/threadutility.cpp
index b20e20b5..0c724145 100644
--- a/src/main/cpp/threadutility.cpp
+++ b/src/main/cpp/threadutility.cpp
@@ -60,9 +60,22 @@ struct ThreadUtility::priv_data
 	~priv_data()
 	{ stopThread(); }
 
-	ThreadStartPre  start_pre{nullptr};
-	ThreadStarted   started{nullptr};
-	ThreadStartPost start_post{nullptr};
+	/**
+	 * Configured behaviour, if user-provided functions have not been provided.
+	 */
+	ThreadConfigurationType config_type{ ThreadConfigurationType::BlockSignalsAndNameThread };
+	/**
+	 * A user-provided pre-start thread function.
+	 */
+	ThreadStartPre          start_pre{nullptr};
+	/**
+	 * A user-provided thread naming function.
+	 */
+	ThreadStarted           set_name{nullptr};
+	/**
+	 * A user-provided post-start thread function.
+	 */
+	ThreadStartPost         start_post{nullptr};
 
 	using TimePoint = std::chrono::time_point<std::chrono::system_clock>;
 	struct NamedPeriodicFunction
@@ -120,18 +133,79 @@ struct ThreadUtility::priv_data
 #endif
 };
 
+struct ThreadUtility::ThreadStartContext::Impl
+{
+	ThreadUtility::priv_data* parent;
+	bool                      sigmask_valid{ false };
 #if LOG4CXX_HAS_PTHREAD_SIGMASK
-	static thread_local sigset_t old_mask;
-	static thread_local bool sigmask_valid;
+	sigset_t                  old_mask;
 #endif
 
+	Impl(ThreadUtility::priv_data* pPriv) : parent(pPriv) {}
+
+	/**
+	 * A pre-start thread function that blocks signals to the new thread
+	 * (if the system has pthreads).  If the system does not have pthreads,
+	 * does nothing.
+	 */
+	void preThreadBlockSignals();
+
+	/**
+	 * A thread_started function that names the thread using the appropriate
+	 * system call.
+	 */
+	void threadStartedNameThread
+		( LogString                threadName
+		, std::thread::id          thread_id
+		, std::thread::native_handle_type native_handle
+		);
+
+	/**
+	 * A post-start thread function that unblocks signals that preThreadBlockSignals
+	 * blocked before starting the thread.  If the system does not have pthreads,
+	 * does nothing.
+	 */
+	void postThreadUnblockSignals();
+};
+
+ThreadUtility::ThreadStartContext::ThreadStartContext(ThreadUtility* parent)
+	: m_priv( std::make_unique<Impl>(parent->m_priv.get()) )
+{
+	if (auto user_provided_pre_start = m_priv->parent->start_pre)
+		user_provided_pre_start();
+	else if (m_priv->parent->config_type == ThreadConfigurationType::BlockSignalsOnly)
+		m_priv->preThreadBlockSignals();
+	else if (m_priv->parent->config_type == ThreadConfigurationType::BlockSignalsAndNameThread)
+		m_priv->preThreadBlockSignals();
+}
+
+ThreadUtility::ThreadStartContext::~ThreadStartContext()
+{
+	if (auto user_provided_post_start = m_priv->parent->start_post)
+		user_provided_post_start();
+	else if (m_priv->parent->config_type == ThreadConfigurationType::BlockSignalsOnly)
+		m_priv->postThreadUnblockSignals();
+	else if (m_priv->parent->config_type == ThreadConfigurationType::BlockSignalsAndNameThread)
+		m_priv->postThreadUnblockSignals();
+}
+
+void ThreadUtility::ThreadStartContext::setThreadName
+	( LogString                       threadName
+	, std::thread::id                 threadId
+	, std::thread::native_handle_type nativeHandle
+	) const
+{
+	if (auto user_provided_set_name = m_priv->parent->set_name)
+		user_provided_set_name(threadName, threadId, nativeHandle);
+	else if (m_priv->parent->config_type == ThreadConfigurationType::NameThreadOnly)
+		m_priv->threadStartedNameThread(threadName, threadId, nativeHandle);
+	else if (m_priv->parent->config_type == ThreadConfigurationType::BlockSignalsAndNameThread)
+		m_priv->threadStartedNameThread(threadName, threadId, nativeHandle);
+}
+
 ThreadUtility::ThreadUtility()
 	: m_priv( std::make_unique<priv_data>() )
 {
-	// Block signals by default.
-	configureFuncs( std::bind( &ThreadUtility::preThreadBlockSignals, this ),
-		nullptr,
-		std::bind( &ThreadUtility::postThreadUnblockSignals, this ) );
 }
 
 ThreadUtility::~ThreadUtility() {}
@@ -152,48 +226,26 @@ ThreadUtility* ThreadUtility::instance()
 
 void ThreadUtility::configure( ThreadConfigurationType type )
 {
-	auto utility = instance();
-
-	if ( type == ThreadConfigurationType::NoConfiguration )
-	{
-		utility->configureFuncs( nullptr, nullptr, nullptr );
-	}
-	else if ( type == ThreadConfigurationType::NameThreadOnly )
-	{
-		utility->configureFuncs( nullptr,
-			std::bind( &ThreadUtility::threadStartedNameThread, utility,
-				std::placeholders::_1,
-				std::placeholders::_2,
-				std::placeholders::_3 ),
-			nullptr );
-	}
-	else if ( type == ThreadConfigurationType::BlockSignalsOnly )
-	{
-		utility->configureFuncs( std::bind( &ThreadUtility::preThreadBlockSignals, utility ),
-			nullptr,
-			std::bind( &ThreadUtility::postThreadUnblockSignals, utility ) );
-	}
-	else if ( type == ThreadConfigurationType::BlockSignalsAndNameThread )
-	{
-		utility->configureFuncs( std::bind( &ThreadUtility::preThreadBlockSignals, utility ),
-			std::bind( &ThreadUtility::threadStartedNameThread, utility,
-				std::placeholders::_1,
-				std::placeholders::_2,
-				std::placeholders::_3 ),
-			std::bind( &ThreadUtility::postThreadUnblockSignals, utility ) );
-	}
+	auto p = instance();
+	p->m_priv->start_pre = nullptr;
+	p->m_priv->set_name = nullptr;
+	p->m_priv->start_post = nullptr;
+	p->m_priv->config_type = type;
 }
 
-void ThreadUtility::configureFuncs( ThreadStartPre pre_start,
-	ThreadStarted started,
-	ThreadStartPost post_start )
+ThreadConfigurationType ThreadUtility::configureFuncs
+	( ThreadStartPre  pre_start
+	, ThreadStarted   set_name
+	, ThreadStartPost post_start
+	)
 {
 	m_priv->start_pre = pre_start;
-	m_priv->started = started;
+	m_priv->set_name = set_name;
 	m_priv->start_post = post_start;
+	return m_priv->config_type;
 }
 
-void ThreadUtility::preThreadBlockSignals()
+void ThreadUtility::ThreadStartContext::Impl::preThreadBlockSignals()
 {
 #if LOG4CXX_HAS_PTHREAD_SIGMASK
 	sigset_t set;
@@ -212,9 +264,11 @@ void ThreadUtility::preThreadBlockSignals()
 #endif /* LOG4CXX_HAS_PTHREAD_SIGMASK */
 }
 
-void ThreadUtility::threadStartedNameThread(LogString threadName,
-	std::thread::id /*threadId*/,
-	std::thread::native_handle_type nativeHandle)
+void ThreadUtility::ThreadStartContext::Impl::threadStartedNameThread
+	( LogString                       threadName
+	, std::thread::id                 threadId
+	, std::thread::native_handle_type nativeHandle
+	)
 {
 #if defined(_WIN32)
 	typedef HRESULT (WINAPI *TSetThreadDescription)(HANDLE, PCWSTR);
@@ -249,7 +303,7 @@ void ThreadUtility::threadStartedNameThread(LogString threadName,
 #endif
 }
 
-void ThreadUtility::postThreadUnblockSignals()
+void ThreadUtility::ThreadStartContext::Impl::postThreadUnblockSignals()
 {
 #if LOG4CXX_HAS_PTHREAD_SIGMASK
 
@@ -265,22 +319,6 @@ void ThreadUtility::postThreadUnblockSignals()
 #endif /* LOG4CXX_HAS_PTHREAD_SIGMASK */
 }
 
-
-ThreadStartPre ThreadUtility::preStartFunction()
-{
-	return m_priv->start_pre;
-}
-
-ThreadStarted ThreadUtility::threadStartedFunction()
-{
-	return m_priv->started;
-}
-
-ThreadStartPost ThreadUtility::postStartFunction()
-{
-	return m_priv->start_post;
-}
-
 /**
  * Add a periodic task
  */
diff --git a/src/main/include/log4cxx/helpers/threadutility.h b/src/main/include/log4cxx/helpers/threadutility.h
index d662e988..8cb096e0 100644
--- a/src/main/include/log4cxx/helpers/threadutility.h
+++ b/src/main/include/log4cxx/helpers/threadutility.h
@@ -23,8 +23,8 @@
 #include <memory>
 #include <chrono>
 
-#include "log4cxx/logstring.h"
-#include "singletonholder.h"
+#include <log4cxx/logstring.h>
+#include <log4cxx/helpers/singletonholder.h>
 
 namespace LOG4CXX_NS
 {
@@ -35,8 +35,8 @@ namespace helpers
  * A function that will be called before a thread is started.  This can
  * be used to (for example) block all of the signals in the thread, so
  * that when the thread is created it will have a correct signal mask.
- */
-typedef std::function<void()> ThreadStartPre;
+*/
+using ThreadStartPre = std::function<void()>;
 
 /**
  * Called when a new thread has started.  This can be used to set
@@ -47,15 +47,19 @@ typedef std::function<void()> ThreadStartPre;
  * @param nativeHandle The native handle of the thread, as reported by
  * std::thread::native_handle
  */
-typedef std::function<void( LogString threadName,
-	std::thread::id threadId,
-	std::thread::native_handle_type nativeHandle )> ThreadStarted;
+using ThreadStarted = std::function
+	< void
+		( LogString                       threadName
+		, std::thread::id                 threadId
+		, std::thread::native_handle_type nativeHandle
+		)
+	>;
 
 /**
  * Called after a thread has started. This can be used to (for example)
  * unblock the signals in the thread.
  */
-typedef std::function<void()> ThreadStartPost;
+using ThreadStartPost = std::function<void()>;
 
 enum class ThreadConfigurationType
 {
@@ -71,10 +75,6 @@ class LOG4CXX_EXPORT ThreadUtility
 		friend class SingletonHolder<ThreadUtility>;
 		ThreadUtility();
 
-		LOG4CXX_NS::helpers::ThreadStartPre preStartFunction();
-		LOG4CXX_NS::helpers::ThreadStarted threadStartedFunction();
-		LOG4CXX_NS::helpers::ThreadStartPost postStartFunction();
-
 		LOG4CXX_DECLARE_PRIVATE_MEMBER_PTR(priv_data, m_priv)
 	public:
 		~ThreadUtility();
@@ -82,73 +82,36 @@ class LOG4CXX_EXPORT ThreadUtility
 		static ThreadUtility* instance();
 
 		/**
-		 * Utility method for configuring the ThreadUtility in a standard
-		 * configuration.
+		 * Use \c new_value as the behviour when starting a thread.
+		 * Call-back function pointers are reset to nullptr.
 		 */
-		static void configure( ThreadConfigurationType type );
+		static void configure( ThreadConfigurationType new_value );
 
 		/**
-		 * Configure the thread functions that log4cxx will use.
+		 * Set call-back functions to use when starting a thread.
 		 * Note that setting any of these parameters to nullptr is valid,
 		 * and simply results in the callback not being called.
+		 * @returns The previous configuration
 		 */
-		void configureFuncs( ThreadStartPre pre_start,
-			ThreadStarted started,
-			ThreadStartPost post_start );
-
-		/**
-		 * A pre-start thread function that blocks signals to the new thread
-		 * (if the system has pthreads).  If the system does not have pthreads,
-		 * does nothing.
-		 */
-		void preThreadBlockSignals();
-
-		/**
-		 * A thread_started function that names the thread using the appropriate
-		 * system call.
-		 */
-		void threadStartedNameThread(LogString threadName,
-			std::thread::id thread_id,
-			std::thread::native_handle_type native_handle);
-
-		/**
-		 * A post-start thread function that unblocks signals that preThreadBlockSignals
-		 * blocked before starting the thread.  If the system does not have pthreads,
-		 * does nothing.
-		 */
-		void postThreadUnblockSignals();
+		ThreadConfigurationType configureFuncs
+			( ThreadStartPre  pre_start
+			, ThreadStarted   set_name
+			, ThreadStartPost post_start
+			);
 
 		/**
 		 * Start a thread
 		 */
 		template<class Function, class... Args>
-		std::thread createThread(LogString name,
-			Function&& f,
-			Args&& ... args)
+		std::thread createThread
+			( LogString name
+			, Function&& f
+			, Args&& ... args
+			)
 		{
-			LOG4CXX_NS::helpers::ThreadStartPre pre_start = preStartFunction();
-			LOG4CXX_NS::helpers::ThreadStarted thread_start = threadStartedFunction();
-			LOG4CXX_NS::helpers::ThreadStartPost post_start = postStartFunction();
-
-			if ( pre_start )
-			{
-				pre_start();
-			}
-
+			ThreadStartContext ctx(this);
 			std::thread t( f, args... );
-
-			if ( thread_start )
-			{
-				thread_start( name,
-					t.get_id(),
-					t.native_handle() );
-			}
-
-			if ( post_start )
-			{
-				post_start();
-			}
-
+			ctx.setThreadName(name, t.get_id(), t.native_handle());
 			return t;
 		}
 
@@ -188,6 +151,19 @@ class LOG4CXX_EXPORT ThreadUtility
 		LOG4CXX_PTR_DEF(Manager);
 
 		static ManagerPtr instancePtr();
+
+private:
+		struct LOG4CXX_EXPORT ThreadStartContext
+		{
+			LOG4CXX_DECLARE_PRIVATE_MEMBER_PTR(Impl, m_priv)
+			ThreadStartContext(ThreadUtility* parent);
+			~ThreadStartContext();
+			void setThreadName
+				( LogString                       threadName
+				, std::thread::id                 threadId
+				, std::thread::native_handle_type nativeHandle
+				) const;
+		};
 };
 
 } /* namespace helpers */
diff --git a/src/site/markdown/threading.md b/src/site/markdown/threading.md
index 8d19a2a7..bf62f69d 100644
--- a/src/site/markdown/threading.md
+++ b/src/site/markdown/threading.md
@@ -36,7 +36,7 @@ However there are certain circumstances that can cause threading issues with Log
 In multithreaded applications, it is possible to call `exit()` from any
 thread in the application.  When this happens, other threads in the
 application may continue to run and attempt to log information.  As of
-version 12 of Log4cxx, this should not cause the library to crash.
+version 0.12.0 of Log4cxx, this should not cause the library to crash.
 
 We recommend that a graceful exit be performed whenever possible, and that
 all threads be terminated properly before returning from `main()`.
diff --git a/src/test/cpp/helpers/threadutilitytestcase.cpp b/src/test/cpp/helpers/threadutilitytestcase.cpp
index 0d1174d4..5837ca79 100644
--- a/src/test/cpp/helpers/threadutilitytestcase.cpp
+++ b/src/test/cpp/helpers/threadutilitytestcase.cpp
@@ -74,7 +74,7 @@ public:
 		int num_run = 0;
 		int num_post = 0;
 
-		thrUtil->configureFuncs(
+		auto oldConfig = thrUtil->configureFuncs(
 			[&num_pre]()
 		{
 			num_pre++;
@@ -102,6 +102,7 @@ public:
 		LOGUNIT_ASSERT_EQUAL( num_started, 1 );
 		LOGUNIT_ASSERT_EQUAL( num_run, 1 );
 		LOGUNIT_ASSERT_EQUAL( num_post, 1 );
+		thrUtil->configure(oldConfig);
 	}
 
 	void testDefaultFunctions()


(logging-log4cxx) 02/03: Merge branch 'master' into simplify_thread_utility

Posted by sw...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

swebb2066 pushed a commit to branch simplify_thread_utility
in repository https://gitbox.apache.org/repos/asf/logging-log4cxx.git

commit 4978e3eb28cd9964bc044e18896c06256cb253fb
Merge: 04ada95c faf2dd5f
Author: Stephen Webb <sw...@gmail.com>
AuthorDate: Mon Oct 19 15:33:42 2026 +1100

    Merge branch 'master' into simplify_thread_utility

 src/main/cpp/defaultconfigurator.cpp           | 14 +-------------
 src/main/include/log4cxx/defaultconfigurator.h |  6 +++---
 src/site/markdown/change-report-gh.md          | 12 ++++++++++++
 3 files changed, 16 insertions(+), 16 deletions(-)