// Copyright (C) 2024 Intel Corporation. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QLATCH_P_H #define QLATCH_P_H // // W A R N I N G // ------------- // // This file is not part of the Qt API. It exists purely as an implementation // detail. This header file may change from version to version without notice, // or even be removed. // // We mean it. // #include #include #include #include QT_BEGIN_NAMESPACE class QLatch { public: constexpr explicit QLatch(int expected) noexcept : counter(expected | NoWaiters) {} int pending() const noexcept { return (counter.loadAcquire() & CounterMask); } void countDown(int n = 1) noexcept { QtTsan::latchCountDown(&counter); if (counter.fetchAndSubRelease(n) == n) // addAndFetch(n) == 0 wakeUp(); } bool tryWait() const noexcept { if (pending() != 0) return false; QtTsan::latchWait(&counter); return true; } void wait() noexcept // not const { if (int current = counter.loadAcquire(); (current & CounterMask) != 0) { waitInternal(current); QtTsan::latchWait(&counter); } } void arriveAndWait(int n = 1) noexcept { countDown(n); wait(); } // API compatible with C++20: static constexpr int max() noexcept { return std::numeric_limits::max(); } void count_down(int n = 1) noexcept { countDown(n); } bool try_wait() const noexcept { return tryWait(); } void arrive_and_wait(int n = 1) noexcept { arriveAndWait(n); } private: static constexpr int NoWaitersBit = 31; static constexpr int NoWaiters = 1 << NoWaitersBit; static constexpr int CounterMask = ~NoWaiters; QBasicAtomicInt counter; Q_DISABLE_COPY_MOVE(QLatch) #ifdef QATOMICWAIT_USE_FALLBACK # define Q_LATCH_EXPORT /* being linked into the unit test */ #else # define Q_LATCH_EXPORT Q_CORE_EXPORT #endif void Q_LATCH_EXPORT waitInternal(int current) noexcept; void Q_LATCH_EXPORT wakeUp() noexcept; #undef Q_LATCH_EXPORT }; QT_END_NAMESPACE #endif // QLATCH_P_H