Files
Catch2/src/catch2/internal/catch_thread_support.hpp
T
Martin Hořeňovský 2a8a8a7210 Add configuration option to make assertions thread-safe
All the previous refactoring to make the assertion fast paths
smaller and faster also allows us to implement the fast paths
just with thread-local and atomic variables, without full mutexes.

However, the performance overhead of thread-safe assertions is
still significant for single threaded usage:

|  slowdown |  Debug  | Release |
|-----------|--------:|--------:|
| fast path |   1.04x |   1.43x |
| slow path |   1.16x |   1.22x |

Thus, we don't make the assertions thread-safe by default, and instead
provide a build-time configuration option that the users can set to get
thread-safe assertions.

This commit is functional, but it still needs some follow-up work:
 * We do not need full seq_cst increments for the atomic counters,
   and using weaker ones can be faster.
 * We brute-force updating the reporter-friendly totals from internal
   atomic counters by doing it everywhere. We should properly trace
   where this is needed instead.
 * Message macros (`INFO`, `UNSCOPED_INFO`, `CAPTURE`, etc) are not
   made thread safe in this commit, but they can be made thread safe
   in the future, by building on top of this work.
 * Add more tests, including with thread-sanitizer, and compiled
   examples to the repository. Right now, these changes have been
   compiled with tsan manually, but these tests are not added to CI.

Closes #2948
2025-07-24 10:10:00 +02:00

50 lines
1.3 KiB
C++

// 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_SUPPORT_HPP_INCLUDED
#define CATCH_THREAD_SUPPORT_HPP_INCLUDED
#include <catch2/catch_user_config.hpp>
#if defined( CATCH_CONFIG_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS )
# include <atomic>
# include <mutex>
#endif
#include <catch2/catch_totals.hpp>
namespace Catch {
namespace Detail {
#if defined( CATCH_CONFIG_EXPERIMENTAL_THREAD_SAFE_ASSERTIONS )
using Mutex = std::mutex;
using LockGuard = std::lock_guard<std::mutex>;
struct AtomicCounts {
std::atomic<std::uint64_t> passed = 0;
std::atomic<std::uint64_t> failed = 0;
std::atomic<std::uint64_t> failedButOk = 0;
std::atomic<std::uint64_t> skipped = 0;
};
#else // ^^ Use actual mutex, lock and atomics
// vv Dummy implementations for single-thread performance
struct Mutex {
void lock() {}
void unlock() {}
};
struct LockGuard {
LockGuard( Mutex ) {}
};
using AtomicCounts = Counts;
#endif
} // namespace Detail
} // namespace Catch
#endif // CATCH_THREAD_SUPPORT_HPP_INCLUDED