diff options
| author | Martin Hořeňovský | 2025-08-23 00:15:53 +0200 |
|---|---|---|
| committer | Martin Hořeňovský | 2025-08-23 11:08:18 +0200 |
| commit | 582200a1f8ddd6f435d1264668c7074121c2636c (patch) | |
| tree | 06629812ca77ebbd77a35424162e197bb979d85e /src/catch2/internal/catch_reusable_string_stream.cpp | |
| parent | f4e05a67bb5a57ee6e051fc8c391b32cbf927f7d (diff) | |
| download | catch3-582200a1f8ddd6f435d1264668c7074121c2636c.tar.gz | |
Make message macros (FAIL, WARN, INFO, etc) thread safe
This builds on the existing work to make assertion thread safe,
by adding an extra synchronization point in the holder of
`ReusableStringStream`'s stream instances, as those are used to
build the messages, and finishing the move of message scope holders
to be thread-local.
Diffstat (limited to 'src/catch2/internal/catch_reusable_string_stream.cpp')
| -rw-r--r-- | src/catch2/internal/catch_reusable_string_stream.cpp | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/src/catch2/internal/catch_reusable_string_stream.cpp b/src/catch2/internal/catch_reusable_string_stream.cpp index 33eafde4..a2dd5a63 100644 --- a/src/catch2/internal/catch_reusable_string_stream.cpp +++ b/src/catch2/internal/catch_reusable_string_stream.cpp @@ -7,6 +7,7 @@ // SPDX-License-Identifier: BSL-1.0 #include <catch2/internal/catch_reusable_string_stream.hpp> #include <catch2/internal/catch_singletons.hpp> +#include <catch2/internal/catch_thread_support.hpp> #include <catch2/internal/catch_unique_ptr.hpp> #include <cstdio> @@ -20,8 +21,10 @@ namespace Catch { std::vector<Detail::unique_ptr<std::ostringstream>> m_streams; std::vector<std::size_t> m_unused; std::ostringstream m_referenceStream; // Used for copy state/ flags from + Detail::Mutex m_mutex; auto add() -> std::size_t { + Detail::LockGuard _( m_mutex ); if( m_unused.empty() ) { m_streams.push_back( Detail::make_unique<std::ostringstream>() ); return m_streams.size()-1; @@ -33,9 +36,13 @@ namespace Catch { } } - void release( std::size_t index ) { - m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state - m_unused.push_back(index); + void release( std::size_t index, std::ostream* originalPtr ) { + assert( originalPtr ); + originalPtr->copyfmt( m_referenceStream ); // Restore initial flags and other state + + Detail::LockGuard _( m_mutex ); + assert( originalPtr == m_streams[index].get() && "Mismatch between release index and stream ptr" ); + m_unused.push_back( index ); } }; @@ -47,7 +54,7 @@ namespace Catch { ReusableStringStream::~ReusableStringStream() { static_cast<std::ostringstream*>( m_oss )->str(""); m_oss->clear(); - Singleton<StringStreams>::getMutable().release( m_index ); + Singleton<StringStreams>::getMutable().release( m_index, m_oss ); } std::string ReusableStringStream::str() const { |