mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-11-04 05:59:32 +01:00 
			
		
		
		
	Better handle the global lock to avoid static init issues
This commit is contained in:
		@@ -25,23 +25,23 @@ namespace Catch {
 | 
				
			|||||||
    :   m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
 | 
					    :   m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
 | 
				
			||||||
        m_resultCapture( getResultCapture() )
 | 
					        m_resultCapture( getResultCapture() )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        m_resultCapture.notifyAssertionStarted( m_assertionInfo );
 | 
					        m_resultCapture.notifyAssertionStarted( m_assertionInfo );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AssertionHandler::~AssertionHandler() {
 | 
					    AssertionHandler::~AssertionHandler() {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        if ( !m_completed ) {
 | 
					        if ( !m_completed ) {
 | 
				
			||||||
            m_resultCapture.handleIncomplete( m_assertionInfo );
 | 
					            m_resultCapture.handleIncomplete( m_assertionInfo );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
 | 
					    void AssertionHandler::handleExpr( ITransientExpression const& expr ) {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
 | 
					        m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    void AssertionHandler::handleMessage(ResultWas::OfType resultType, std::string&& message) {
 | 
					    void AssertionHandler::handleMessage(ResultWas::OfType resultType, std::string&& message) {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        m_resultCapture.handleMessage( m_assertionInfo, resultType, CATCH_MOVE(message), m_reaction );
 | 
					        m_resultCapture.handleMessage( m_assertionInfo, resultType, CATCH_MOVE(message), m_reaction );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -68,26 +68,26 @@ namespace Catch {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void AssertionHandler::handleUnexpectedInflightException() {
 | 
					    void AssertionHandler::handleUnexpectedInflightException() {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
 | 
					        m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void AssertionHandler::handleExceptionThrownAsExpected() {
 | 
					    void AssertionHandler::handleExceptionThrownAsExpected() {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
 | 
					        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    void AssertionHandler::handleExceptionNotThrownAsExpected() {
 | 
					    void AssertionHandler::handleExceptionNotThrownAsExpected() {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
 | 
					        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void AssertionHandler::handleUnexpectedExceptionNotThrown() {
 | 
					    void AssertionHandler::handleUnexpectedExceptionNotThrown() {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
 | 
					        m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void AssertionHandler::handleThrowingCallSkipped() {
 | 
					    void AssertionHandler::handleThrowingCallSkipped() {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
 | 
					        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,10 @@ CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Catch {
 | 
					namespace Catch {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::recursive_mutex global_lock;
 | 
					    std::recursive_mutex& get_global_lock() {
 | 
				
			||||||
 | 
					        static std::recursive_mutex global_lock;
 | 
				
			||||||
 | 
					        return global_lock;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Catch
 | 
					} // namespace Catch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,10 +13,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Catch {
 | 
					namespace Catch {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    extern std::recursive_mutex global_lock;
 | 
					    std::recursive_mutex& get_global_lock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inline auto get_global_lock() {
 | 
					    inline auto take_global_lock() {
 | 
				
			||||||
        return std::unique_lock<std::recursive_mutex>(global_lock);
 | 
					        return std::unique_lock<std::recursive_mutex>(get_global_lock());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} // namespace Catch
 | 
					} // namespace Catch
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -45,13 +45,13 @@ namespace Catch {
 | 
				
			|||||||
    // instead of poking around StringStreams and Singleton.
 | 
					    // instead of poking around StringStreams and Singleton.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ReusableStringStream::ReusableStringStream() {
 | 
					    ReusableStringStream::ReusableStringStream() {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        m_index = Singleton<StringStreams>::getMutable().add();
 | 
					        m_index = Singleton<StringStreams>::getMutable().add();
 | 
				
			||||||
        m_oss = Singleton<StringStreams>::getMutable().m_streams[m_index].get();
 | 
					        m_oss = Singleton<StringStreams>::getMutable().m_streams[m_index].get();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ReusableStringStream::~ReusableStringStream() {
 | 
					    ReusableStringStream::~ReusableStringStream() {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        static_cast<std::ostringstream*>( m_oss )->str("");
 | 
					        static_cast<std::ostringstream*>( m_oss )->str("");
 | 
				
			||||||
        m_oss->clear();
 | 
					        m_oss->clear();
 | 
				
			||||||
        Singleton<StringStreams>::getMutable().release( m_index );
 | 
					        Singleton<StringStreams>::getMutable().release( m_index );
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -422,22 +422,22 @@ namespace Catch {
 | 
				
			|||||||
    // Catch benchmark macros call these functions. Since catch internals are not thread-safe locking is needed.
 | 
					    // Catch benchmark macros call these functions. Since catch internals are not thread-safe locking is needed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void RunContext::benchmarkPreparing( StringRef name ) {
 | 
					    void RunContext::benchmarkPreparing( StringRef name ) {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        auto _ = scopedDeactivate( *m_outputRedirect );
 | 
					        auto _ = scopedDeactivate( *m_outputRedirect );
 | 
				
			||||||
        m_reporter->benchmarkPreparing( name );
 | 
					        m_reporter->benchmarkPreparing( name );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
 | 
					    void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        auto _ = scopedDeactivate( *m_outputRedirect );
 | 
					        auto _ = scopedDeactivate( *m_outputRedirect );
 | 
				
			||||||
        m_reporter->benchmarkStarting( info );
 | 
					        m_reporter->benchmarkStarting( info );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {
 | 
					    void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        auto _ = scopedDeactivate( *m_outputRedirect );
 | 
					        auto _ = scopedDeactivate( *m_outputRedirect );
 | 
				
			||||||
        m_reporter->benchmarkEnded( stats );
 | 
					        m_reporter->benchmarkEnded( stats );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    void RunContext::benchmarkFailed( StringRef error ) {
 | 
					    void RunContext::benchmarkFailed( StringRef error ) {
 | 
				
			||||||
        auto lock = get_global_lock();
 | 
					        auto lock = take_global_lock();
 | 
				
			||||||
        auto _ = scopedDeactivate( *m_outputRedirect );
 | 
					        auto _ = scopedDeactivate( *m_outputRedirect );
 | 
				
			||||||
        m_reporter->benchmarkFailed( error );
 | 
					        m_reporter->benchmarkFailed( error );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -466,7 +466,7 @@ void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {
 | 
				
			|||||||
// Catch benchmark macros call these functions. Since catch internals are not thread-safe locking is needed.
 | 
					// Catch benchmark macros call these functions. Since catch internals are not thread-safe locking is needed.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ConsoleReporter::benchmarkPreparing( StringRef name ) {
 | 
					void ConsoleReporter::benchmarkPreparing( StringRef name ) {
 | 
				
			||||||
    auto lock = get_global_lock();
 | 
					    auto lock = take_global_lock();
 | 
				
			||||||
	lazyPrintWithoutClosingBenchmarkTable();
 | 
						lazyPrintWithoutClosingBenchmarkTable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	auto nameCol = TextFlow::Column( static_cast<std::string>( name ) )
 | 
						auto nameCol = TextFlow::Column( static_cast<std::string>( name ) )
 | 
				
			||||||
@@ -484,7 +484,7 @@ void ConsoleReporter::benchmarkPreparing( StringRef name ) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
 | 
					void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
 | 
				
			||||||
    auto lock = get_global_lock();
 | 
					    auto lock = take_global_lock();
 | 
				
			||||||
    (*m_tablePrinter) << info.samples << ColumnBreak()
 | 
					    (*m_tablePrinter) << info.samples << ColumnBreak()
 | 
				
			||||||
        << info.iterations << ColumnBreak();
 | 
					        << info.iterations << ColumnBreak();
 | 
				
			||||||
    if ( !m_config->benchmarkNoAnalysis() ) {
 | 
					    if ( !m_config->benchmarkNoAnalysis() ) {
 | 
				
			||||||
@@ -494,7 +494,7 @@ void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {
 | 
				
			|||||||
    ( *m_tablePrinter ) << OutputFlush{};
 | 
					    ( *m_tablePrinter ) << OutputFlush{};
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {
 | 
					void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {
 | 
				
			||||||
    auto lock = get_global_lock();
 | 
					    auto lock = take_global_lock();
 | 
				
			||||||
    if (m_config->benchmarkNoAnalysis())
 | 
					    if (m_config->benchmarkNoAnalysis())
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();
 | 
					        (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();
 | 
				
			||||||
@@ -512,7 +512,7 @@ void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ConsoleReporter::benchmarkFailed( StringRef error ) {
 | 
					void ConsoleReporter::benchmarkFailed( StringRef error ) {
 | 
				
			||||||
    auto lock = get_global_lock();
 | 
					    auto lock = take_global_lock();
 | 
				
			||||||
    auto guard = m_colour->guardColour( Colour::Red ).engage( m_stream );
 | 
					    auto guard = m_colour->guardColour( Colour::Red ).engage( m_stream );
 | 
				
			||||||
    (*m_tablePrinter)
 | 
					    (*m_tablePrinter)
 | 
				
			||||||
        << "Benchmark failed (" << error << ')'
 | 
					        << "Benchmark failed (" << error << ')'
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user