From d427034253a3eed147d5c93683f43316b8d89f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 1 Dec 2025 14:18:54 +0100 Subject: [PATCH] Only use thread_local in builds with thread safety enabled --- src/CMakeLists.txt | 1 + src/catch2/catch_all.hpp | 1 + src/catch2/internal/catch_message_info.cpp | 2 +- src/catch2/internal/catch_message_info.hpp | 3 ++- src/catch2/internal/catch_run_context.cpp | 11 ++++++----- src/catch2/internal/catch_thread_local.hpp | 19 +++++++++++++++++++ src/catch2/meson.build | 1 + 7 files changed, 31 insertions(+), 7 deletions(-) create mode 100644 src/catch2/internal/catch_thread_local.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 554346f4..f8256f1e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -140,6 +140,7 @@ set(IMPL_HEADERS ${SOURCES_DIR}/internal/catch_test_registry.hpp ${SOURCES_DIR}/internal/catch_test_spec_parser.hpp ${SOURCES_DIR}/internal/catch_textflow.hpp + ${SOURCES_DIR}/internal/catch_thread_local.hpp ${SOURCES_DIR}/internal/catch_thread_support.hpp ${SOURCES_DIR}/internal/catch_to_string.hpp ${SOURCES_DIR}/internal/catch_uncaught_exceptions.hpp diff --git a/src/catch2/catch_all.hpp b/src/catch2/catch_all.hpp index 3dc4609e..693f6595 100644 --- a/src/catch2/catch_all.hpp +++ b/src/catch2/catch_all.hpp @@ -122,6 +122,7 @@ #include #include #include +#include #include #include #include diff --git a/src/catch2/internal/catch_message_info.cpp b/src/catch2/internal/catch_message_info.cpp index bc887abf..2352f36c 100644 --- a/src/catch2/internal/catch_message_info.cpp +++ b/src/catch2/internal/catch_message_info.cpp @@ -21,6 +21,6 @@ namespace Catch { // Messages are owned by their individual threads, so the counter should be thread-local as well. // Alternative consideration: atomic, so threads don't share IDs and things are easier to debug. - thread_local unsigned int MessageInfo::globalCount = 0; + CATCH_INTERNAL_THREAD_LOCAL unsigned int MessageInfo::globalCount = 0; } // end namespace Catch diff --git a/src/catch2/internal/catch_message_info.hpp b/src/catch2/internal/catch_message_info.hpp index 8c18186b..803a0c61 100644 --- a/src/catch2/internal/catch_message_info.hpp +++ b/src/catch2/internal/catch_message_info.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -38,7 +39,7 @@ namespace Catch { return sequence < other.sequence; } private: - static thread_local unsigned int globalCount; + static CATCH_INTERNAL_THREAD_LOCAL unsigned int globalCount; }; } // end namespace Catch diff --git a/src/catch2/internal/catch_run_context.cpp b/src/catch2/internal/catch_run_context.cpp index 3d72131d..7fce10da 100644 --- a/src/catch2/internal/catch_run_context.cpp +++ b/src/catch2/internal/catch_run_context.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -175,25 +176,25 @@ namespace Catch { // from heap, to avoid consuming too much thread-local storage. // This is used for the "if" part of CHECKED_IF/CHECKED_ELSE - static thread_local bool g_lastAssertionPassed = false; + static CATCH_INTERNAL_THREAD_LOCAL bool g_lastAssertionPassed = false; // This is the source location for last encountered macro. It is // used to provide the users with more precise location of error // when an unexpected exception/fatal error happens. - static thread_local SourceLineInfo g_lastKnownLineInfo("DummyLocation", static_cast(-1)); + static CATCH_INTERNAL_THREAD_LOCAL SourceLineInfo g_lastKnownLineInfo("DummyLocation", static_cast(-1)); // Should we clear message scopes before sending off the messages to // reporter? Set in `assertionPassedFastPath` to avoid doing the full // clear there for performance reasons. - static thread_local bool g_clearMessageScopes = false; + static CATCH_INTERNAL_THREAD_LOCAL bool g_clearMessageScopes = false; CATCH_INTERNAL_START_WARNINGS_SUPPRESSION CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS // Actual messages to be provided to the reporter - static thread_local std::vector g_messages; + static CATCH_INTERNAL_THREAD_LOCAL std::vector g_messages; // Owners for the UNSCOPED_X information macro - static thread_local std::vector g_messageScopes; + static CATCH_INTERNAL_THREAD_LOCAL std::vector g_messageScopes; CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION } // namespace Detail diff --git a/src/catch2/internal/catch_thread_local.hpp b/src/catch2/internal/catch_thread_local.hpp new file mode 100644 index 00000000..b1ea2f61 --- /dev/null +++ b/src/catch2/internal/catch_thread_local.hpp @@ -0,0 +1,19 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +#ifndef CATCH_THREAD_LOCAL_HPP_INCLUDED +#define CATCH_THREAD_LOCAL_HPP_INCLUDED + +#include + +#if defined( CATCH_CONFIG_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS ) +#define CATCH_INTERNAL_THREAD_LOCAL thread_local +#else +#define CATCH_INTERNAL_THREAD_LOCAL +#endif + +#endif // CATCH_THREAD_LOCAL_HPP_INCLUDED diff --git a/src/catch2/meson.build b/src/catch2/meson.build index 273e330f..45b9d2de 100644 --- a/src/catch2/meson.build +++ b/src/catch2/meson.build @@ -148,6 +148,7 @@ internal_headers = [ 'internal/catch_test_registry.hpp', 'internal/catch_test_spec_parser.hpp', 'internal/catch_textflow.hpp', + 'internal/catch_thread_local.hpp', 'internal/catch_thread_support.hpp', 'internal/catch_to_string.hpp', 'internal/catch_uncaught_exceptions.hpp',