Coverage Report

Created: 2025-07-18 06:34

/src/immer/immer/lock/spinlock_policy.hpp
Line
Count
Source (jump to first uncovered line)
1
//
2
// immer: immutable data structures for C++
3
// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
4
//
5
// This software is distributed under the Boost Software License, Version 1.0.
6
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
7
//
8
9
#pragma once
10
11
#include <atomic>
12
#include <thread>
13
14
// This has been shamelessly copied from boost...
15
#if defined(_MSC_VER) && _MSC_VER >= 1310 &&                                   \
16
    (defined(_M_IX86) || defined(_M_X64)) && !defined(__c2__)
17
extern "C" void _mm_pause();
18
#define IMMER_SMT_PAUSE _mm_pause()
19
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
20
#define IMMER_SMT_PAUSE __asm__ __volatile__("rep; nop" : : : "memory")
21
#endif
22
23
namespace immer {
24
25
// This is an atomic spinlock similar to the one used by boost to provide
26
// "atomic" shared_ptr operations.  It also does not differ much from the one
27
// from libc++ or libstdc++...
28
struct spinlock_policy
29
{
30
    std::atomic_flag v_{};
31
32
0
    bool try_lock() { return !v_.test_and_set(std::memory_order_acquire); }
33
34
    void lock()
35
0
    {
36
0
        for (auto k = 0u; !try_lock(); ++k) {
37
0
            if (k < 4)
38
0
                continue;
39
0
#ifdef IMMER_SMT_PAUSE
40
0
            else if (k < 16)
41
0
                IMMER_SMT_PAUSE;
42
0
#endif
43
0
            else
44
0
                std::this_thread::yield();
45
0
        }
46
0
    }
47
48
0
    void unlock() { v_.clear(std::memory_order_release); }
49
50
    struct scoped_lock
51
    {
52
        scoped_lock(const scoped_lock&)            = delete;
53
        scoped_lock& operator=(const scoped_lock&) = delete;
54
55
        explicit scoped_lock(spinlock_policy& sp)
56
            : sp_{sp}
57
0
        {
58
0
            sp.lock();
59
0
        }
60
61
0
        ~scoped_lock() { sp_.unlock(); }
62
63
    private:
64
        spinlock_policy& sp_;
65
    };
66
};
67
68
} // namespace immer