SpECTRE Documentation Coverage Report
Current view: top level - Parallel - Spinlock.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 33.3 % 12 4
Test Date: 2026-10-22 17:29:42
Legend: Lines:     hit not hit

            Line data    Source code
       1            0 : // Distributed under the MIT License.
       2              : // See LICENSE.txt for details.
       3              : 
       4              : #pragma once
       5              : 
       6              : #include <atomic>
       7              : 
       8              : namespace Parallel {
       9              : /*!
      10              :  * \brief A simple spinlock implemented in `std::atomic`s
      11              :  *
      12              :  * Implementation adapted from https://rigtorp.se/spinlock/
      13              :  */
      14            1 : class Spinlock {
      15              :  public:
      16            0 :   Spinlock() = default;
      17            0 :   Spinlock(const Spinlock&) = delete;
      18            0 :   Spinlock& operator=(const Spinlock&) = delete;
      19            0 :   Spinlock(Spinlock&&) = delete;
      20            0 :   Spinlock& operator=(Spinlock&&) = delete;
      21            0 :   ~Spinlock() = default;
      22              : 
      23              :   /// \brief Acquire the lock. Will block until the lock is acquired.
      24            1 :   void lock() {
      25              :     for (;;) {
      26              :       // Optimistically assume the lock is free on the first try
      27              :       if (not lock_.exchange(true, std::memory_order_acquire)) {
      28              :         return;
      29              :       }
      30              :       // Wait for lock to be released without generating cache misses
      31              :       while (lock_.load(std::memory_order_relaxed)) {
      32              :         // Issue X86 PAUSE or ARM YIELD instruction to reduce contention between
      33              :         // hyper-threads
      34              :         //
      35              :         // If no hyperthreading is being used, this will actually slow down the
      36              :         // code.
      37              :         //
      38              :         // We keep this comment and code around just in case we want to
      39              :         // experiment with it in the future.
      40              :         //
      41              :         // __builtin_ia32_pause();
      42              :       }
      43              :     }
      44              :   }
      45              : 
      46              :   /// \brief Try to acquire the lock.
      47              :   ///
      48              :   /// Returns `true` if the lock was acquired, `false` if it wasn't.
      49            1 :   bool try_lock() {
      50              :     // First do a relaxed load to check if lock is free in order to prevent
      51              :     // unnecessary cache misses if someone does while(!try_lock())
      52              :     return not lock_.load(std::memory_order_relaxed) and
      53              :            not lock_.exchange(true, std::memory_order_acquire);
      54              :   }
      55              : 
      56              :   /// \brief Release the lock.
      57            1 :   void unlock() { lock_.store(false, std::memory_order_release); }
      58              : 
      59              :  private:
      60            0 :   std::atomic<bool> lock_{false};
      61              : };
      62              : }  // namespace Parallel
        

Generated by: LCOV version 2.0-1