Coverage Report

Created: 2024-05-20 07:14

/src/skia/include/private/base/SkOnce.h
Line
Count
Source
1
/*
2
 * Copyright 2013 Google Inc.
3
 *
4
 * Use of this source code is governed by a BSD-style license that can be
5
 * found in the LICENSE file.
6
 */
7
8
#ifndef SkOnce_DEFINED
9
#define SkOnce_DEFINED
10
11
#include "include/private/base/SkThreadAnnotations.h"
12
13
#include <atomic>
14
#include <cstdint>
15
#include <utility>
16
17
// SkOnce provides call-once guarantees for Skia, much like std::once_flag/std::call_once().
18
//
19
// There should be no particularly error-prone gotcha use cases when using SkOnce.
20
// It works correctly as a class member, a local, a global, a function-scoped static, whatever.
21
22
class SkOnce {
23
public:
24
86.1M
    constexpr SkOnce() = default;
25
26
    template <typename Fn, typename... Args>
27
96.1M
    void operator()(Fn&& fn, Args&&... args) {
28
96.1M
        auto state = fState.load(std::memory_order_acquire);
29
30
96.1M
        if (state == Done) {
31
96.1M
            return;
32
96.1M
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
23.7k
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
23.7k
                                                                  std::memory_order_relaxed,
37
23.7k
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
23.7k
            fn(std::forward<Args>(args)...);
40
23.7k
            return fState.store(Done, std::memory_order_release);
41
23.7k
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
9
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
31.4k
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
9
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
9
    }
FontToolUtils.cpp:void SkOnce::operator()<ToolUtils::TestFontMgr()::$_0>(ToolUtils::TestFontMgr()::$_0&&)
Line
Count
Source
27
359k
    void operator()(Fn&& fn, Args&&... args) {
28
359k
        auto state = fState.load(std::memory_order_acquire);
29
30
359k
        if (state == Done) {
31
359k
            return;
32
359k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
5
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
5
                                                                  std::memory_order_relaxed,
37
5
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
5
            fn(std::forward<Args>(args)...);
40
5
            return fState.store(Done, std::memory_order_release);
41
5
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkSemaphore.cpp:void SkOnce::operator()<SkSemaphore::osSignal(int)::$_0>(SkSemaphore::osSignal(int)::$_0&&)
Line
Count
Source
27
117
    void operator()(Fn&& fn, Args&&... args) {
28
117
        auto state = fState.load(std::memory_order_acquire);
29
30
117
        if (state == Done) {
31
111
            return;
32
111
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
6
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
1
                                                                  std::memory_order_relaxed,
37
1
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
1
            fn(std::forward<Args>(args)...);
40
1
            return fState.store(Done, std::memory_order_release);
41
1
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
5
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
3.92k
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
5
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
5
    }
SkSemaphore.cpp:void SkOnce::operator()<SkSemaphore::osWait()::$_0>(SkSemaphore::osWait()::$_0&&)
Line
Count
Source
27
117
    void operator()(Fn&& fn, Args&&... args) {
28
117
        auto state = fState.load(std::memory_order_acquire);
29
30
117
        if (state == Done) {
31
52
            return;
32
52
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
65
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
63
                                                                  std::memory_order_relaxed,
37
63
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
61
            fn(std::forward<Args>(args)...);
40
61
            return fState.store(Done, std::memory_order_release);
41
61
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
4
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
27.5k
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
4
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
4
    }
SkColorSpace.cpp:void SkOnce::operator()<SkColorSpace::computeLazyDstFields() const::$_0>(SkColorSpace::computeLazyDstFields() const::$_0&&)
Line
Count
Source
27
505k
    void operator()(Fn&& fn, Args&&... args) {
28
505k
        auto state = fState.load(std::memory_order_acquire);
29
30
505k
        if (state == Done) {
31
505k
            return;
32
505k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
177
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
177
                                                                  std::memory_order_relaxed,
37
177
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
177
            fn(std::forward<Args>(args)...);
40
177
            return fState.store(Done, std::memory_order_release);
41
177
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkData.cpp:void SkOnce::operator()<SkData::MakeEmpty()::$_0>(SkData::MakeEmpty()::$_0&&)
Line
Count
Source
27
21.9k
    void operator()(Fn&& fn, Args&&... args) {
28
21.9k
        auto state = fState.load(std::memory_order_acquire);
29
30
21.9k
        if (state == Done) {
31
21.9k
            return;
32
21.9k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
12
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
12
                                                                  std::memory_order_relaxed,
37
12
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
12
            fn(std::forward<Args>(args)...);
40
12
            return fState.store(Done, std::memory_order_release);
41
12
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkGlobalInitialization_core.cpp:void SkOnce::operator()<SkFlattenable::RegisterFlattenablesIfNeeded()::$_0>(SkFlattenable::RegisterFlattenablesIfNeeded()::$_0&&)
Line
Count
Source
27
86.9k
    void operator()(Fn&& fn, Args&&... args) {
28
86.9k
        auto state = fState.load(std::memory_order_acquire);
29
30
86.9k
        if (state == Done) {
31
86.9k
            return;
32
86.9k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
3
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
3
                                                                  std::memory_order_relaxed,
37
3
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
3
            fn(std::forward<Args>(args)...);
40
3
            return fState.store(Done, std::memory_order_release);
41
3
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkImageFilterCache.cpp:void SkOnce::operator()<SkImageFilterCache::Get(SkImageFilterCache::CreateIfNecessary)::$_0>(SkImageFilterCache::Get(SkImageFilterCache::CreateIfNecessary)::$_0&&)
Line
Count
Source
27
473k
    void operator()(Fn&& fn, Args&&... args) {
28
473k
        auto state = fState.load(std::memory_order_acquire);
29
30
473k
        if (state == Done) {
31
473k
            return;
32
473k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
9
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
9
                                                                  std::memory_order_relaxed,
37
9
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
9
            fn(std::forward<Args>(args)...);
40
9
            return fState.store(Done, std::memory_order_release);
41
9
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkPathRef.cpp:void SkOnce::operator()<SkPathRef::CreateEmpty()::$_0>(SkPathRef::CreateEmpty()::$_0&&)
Line
Count
Source
27
94.1M
    void operator()(Fn&& fn, Args&&... args) {
28
94.1M
        auto state = fState.load(std::memory_order_acquire);
29
30
94.1M
        if (state == Done) {
31
94.1M
            return;
32
94.1M
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
20
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
20
                                                                  std::memory_order_relaxed,
37
20
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
20
            fn(std::forward<Args>(args)...);
40
20
            return fState.store(Done, std::memory_order_release);
41
20
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkResourceCache.cpp:void SkOnce::operator()<SkMessageBus<SkResourceCache::PurgeSharedIDMessage, unsigned int, true>::Get()::$_0>(SkMessageBus<SkResourceCache::PurgeSharedIDMessage, unsigned int, true>::Get()::$_0&&)
Line
Count
Source
27
10.6k
    void operator()(Fn&& fn, Args&&... args) {
28
10.6k
        auto state = fState.load(std::memory_order_acquire);
29
30
10.6k
        if (state == Done) {
31
10.6k
            return;
32
10.6k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
7
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
7
                                                                  std::memory_order_relaxed,
37
7
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
7
            fn(std::forward<Args>(args)...);
40
7
            return fState.store(Done, std::memory_order_release);
41
7
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkRuntimeEffect.cpp:void SkOnce::operator()<SkRuntimeEffect::getRPProgram(SkSL::DebugTracePriv*) const::$_0>(SkRuntimeEffect::getRPProgram(SkSL::DebugTracePriv*) const::$_0&&)
Line
Count
Source
27
49.7k
    void operator()(Fn&& fn, Args&&... args) {
28
49.7k
        auto state = fState.load(std::memory_order_acquire);
29
30
49.7k
        if (state == Done) {
31
49.6k
            return;
32
49.6k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
51
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
51
                                                                  std::memory_order_relaxed,
37
51
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
51
            fn(std::forward<Args>(args)...);
40
51
            return fState.store(Done, std::memory_order_release);
41
51
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkTypeface.cpp:void SkOnce::operator()<SkTypeface::getBounds() const::$_0>(SkTypeface::getBounds() const::$_0&&)
Line
Count
Source
27
52.4k
    void operator()(Fn&& fn, Args&&... args) {
28
52.4k
        auto state = fState.load(std::memory_order_acquire);
29
30
52.4k
        if (state == Done) {
31
48.5k
            return;
32
48.5k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
3.98k
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
3.98k
                                                                  std::memory_order_relaxed,
37
3.98k
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
3.98k
            fn(std::forward<Args>(args)...);
40
3.98k
            return fState.store(Done, std::memory_order_release);
41
3.98k
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkEventTracer.cpp:void SkOnce::operator()<SkEventTracer::GetInstance()::$_0>(SkEventTracer::GetInstance()::$_0&&)
Line
Count
Source
27
245
    void operator()(Fn&& fn, Args&&... args) {
28
245
        auto state = fState.load(std::memory_order_acquire);
29
30
245
        if (state == Done) {
31
227
            return;
32
227
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
18
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
18
                                                                  std::memory_order_relaxed,
37
18
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
18
            fn(std::forward<Args>(args)...);
40
18
            return fState.store(Done, std::memory_order_release);
41
18
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkCodec.cpp:void SkOnce::operator()<SkCodecs::get_decoders_for_editing()::$_0>(SkCodecs::get_decoders_for_editing()::$_0&&)
Line
Count
Source
27
168k
    void operator()(Fn&& fn, Args&&... args) {
28
168k
        auto state = fState.load(std::memory_order_acquire);
29
30
168k
        if (state == Done) {
31
168k
            return;
32
168k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
7
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
7
                                                                  std::memory_order_relaxed,
37
7
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
7
            fn(std::forward<Args>(args)...);
40
7
            return fState.store(Done, std::memory_order_release);
41
7
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
GrResourceCache.cpp:void SkOnce::operator()<SkMessageBus<skgpu::UniqueKeyInvalidatedMessage, unsigned int, true>::Get()::$_0>(SkMessageBus<skgpu::UniqueKeyInvalidatedMessage, unsigned int, true>::Get()::$_0&&)
Line
Count
Source
27
58.2k
    void operator()(Fn&& fn, Args&&... args) {
28
58.2k
        auto state = fState.load(std::memory_order_acquire);
29
30
58.2k
        if (state == Done) {
31
58.2k
            return;
32
58.2k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
1
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
1
                                                                  std::memory_order_relaxed,
37
1
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
1
            fn(std::forward<Args>(args)...);
40
1
            return fState.store(Done, std::memory_order_release);
41
1
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
GrResourceCache.cpp:void SkOnce::operator()<SkMessageBus<GrResourceCache::UnrefResourceMessage, GrDirectContext::DirectContextID, false>::Get()::$_0>(SkMessageBus<GrResourceCache::UnrefResourceMessage, GrDirectContext::DirectContextID, false>::Get()::$_0&&)
Line
Count
Source
27
5.16k
    void operator()(Fn&& fn, Args&&... args) {
28
5.16k
        auto state = fState.load(std::memory_order_acquire);
29
30
5.16k
        if (state == Done) {
31
5.15k
            return;
32
5.15k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
1
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
1
                                                                  std::memory_order_relaxed,
37
1
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
1
            fn(std::forward<Args>(args)...);
40
1
            return fState.store(Done, std::memory_order_release);
41
1
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
void SkOnce::operator()<void (&)(SkAlignedSTStorage<1, skgpu::UniqueKey>*), SkAlignedSTStorage<1, skgpu::UniqueKey>*>(void (&)(SkAlignedSTStorage<1, skgpu::UniqueKey>*), SkAlignedSTStorage<1, skgpu::UniqueKey>*&&)
Line
Count
Source
27
4.07k
    void operator()(Fn&& fn, Args&&... args) {
28
4.07k
        auto state = fState.load(std::memory_order_acquire);
29
30
4.07k
        if (state == Done) {
31
4.07k
            return;
32
4.07k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
5
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
5
                                                                  std::memory_order_relaxed,
37
5
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
5
            fn(std::forward<Args>(args)...);
40
5
            return fState.store(Done, std::memory_order_release);
41
5
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkFontHost_FreeType.cpp:void SkOnce::operator()<SkTypeface_FreeType::onGlyphMaskNeedsCurrentColor() const::$_0>(SkTypeface_FreeType::onGlyphMaskNeedsCurrentColor() const::$_0&&)
Line
Count
Source
27
32.8k
    void operator()(Fn&& fn, Args&&... args) {
28
32.8k
        auto state = fState.load(std::memory_order_acquire);
29
30
32.8k
        if (state == Done) {
31
28.8k
            return;
32
28.8k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
3.94k
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
3.94k
                                                                  std::memory_order_relaxed,
37
3.94k
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
3.94k
            fn(std::forward<Args>(args)...);
40
3.94k
            return fState.store(Done, std::memory_order_release);
41
3.94k
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SkFontHost_FreeType.cpp:void SkOnce::operator()<SkTypeface_FreeType::getFaceRec() const::$_0>(SkTypeface_FreeType::getFaceRec() const::$_0&&)
Line
Count
Source
27
20.7k
    void operator()(Fn&& fn, Args&&... args) {
28
20.7k
        auto state = fState.load(std::memory_order_acquire);
29
30
20.7k
        if (state == Done) {
31
16.6k
            return;
32
16.6k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
4.10k
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
4.10k
                                                                  std::memory_order_relaxed,
37
4.10k
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
4.10k
            fn(std::forward<Args>(args)...);
40
4.10k
            return fState.store(Done, std::memory_order_release);
41
4.10k
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SubRunContainer.cpp:void SkOnce::operator()<(anonymous namespace)::PathOpSubmitter::submitDraws(SkCanvas*, SkPoint, SkPaint const&) const::$_0>((anonymous namespace)::PathOpSubmitter::submitDraws(SkCanvas*, SkPoint, SkPaint const&) const::$_0&&)
Line
Count
Source
27
2.66k
    void operator()(Fn&& fn, Args&&... args) {
28
2.66k
        auto state = fState.load(std::memory_order_acquire);
29
30
2.66k
        if (state == Done) {
31
128
            return;
32
128
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
2.53k
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
2.53k
                                                                  std::memory_order_relaxed,
37
2.53k
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
2.53k
            fn(std::forward<Args>(args)...);
40
2.53k
            return fState.store(Done, std::memory_order_release);
41
2.53k
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
SubRunContainer.cpp:void SkOnce::operator()<(anonymous namespace)::DrawableOpSubmitter::submitDraws(SkCanvas*, SkPoint, SkPaint const&) const::$_0>((anonymous namespace)::DrawableOpSubmitter::submitDraws(SkCanvas*, SkPoint, SkPaint const&) const::$_0&&)
Line
Count
Source
27
2
    void operator()(Fn&& fn, Args&&... args) {
28
2
        auto state = fState.load(std::memory_order_acquire);
29
30
2
        if (state == Done) {
31
0
            return;
32
0
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
2
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
2
                                                                  std::memory_order_relaxed,
37
2
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
2
            fn(std::forward<Args>(args)...);
40
2
            return fState.store(Done, std::memory_order_release);
41
2
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
TextBlobRedrawCoordinator.cpp:void SkOnce::operator()<SkMessageBus<sktext::gpu::TextBlobRedrawCoordinator::PurgeBlobMessage, unsigned int, true>::Get()::$_0>(SkMessageBus<sktext::gpu::TextBlobRedrawCoordinator::PurgeBlobMessage, unsigned int, true>::Get()::$_0&&)
Line
Count
Source
27
5.61k
    void operator()(Fn&& fn, Args&&... args) {
28
5.61k
        auto state = fState.load(std::memory_order_acquire);
29
30
5.61k
        if (state == Done) {
31
5.60k
            return;
32
5.60k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
1
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
1
                                                                  std::memory_order_relaxed,
37
1
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
1
            fn(std::forward<Args>(args)...);
40
1
            return fState.store(Done, std::memory_order_release);
41
1
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
Unexecuted instantiation: SkCpu.cpp:void SkOnce::operator()<SkCpu::CacheRuntimeFeatures()::$_0>(SkCpu::CacheRuntimeFeatures()::$_0&&)
Unexecuted instantiation: SkDataTable.cpp:void SkOnce::operator()<SkDataTable::MakeEmpty()::$_0>(SkDataTable::MakeEmpty()::$_0&&)
SkPerlinNoiseShaderImpl.cpp:void SkOnce::operator()<SkPerlinNoiseShader::appendStages(SkStageRec const&, SkShaders::MatrixRec const&) const::$_0>(SkPerlinNoiseShader::appendStages(SkStageRec const&, SkShaders::MatrixRec const&) const::$_0&&)
Line
Count
Source
27
116k
    void operator()(Fn&& fn, Args&&... args) {
28
116k
        auto state = fState.load(std::memory_order_acquire);
29
30
116k
        if (state == Done) {
31
107k
            return;
32
107k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
8.83k
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
8.83k
                                                                  std::memory_order_relaxed,
37
8.83k
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
8.83k
            fn(std::forward<Args>(args)...);
40
8.83k
            return fState.store(Done, std::memory_order_release);
41
8.83k
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
GrClientMappedBufferManager.cpp:void SkOnce::operator()<SkMessageBus<skgpu::TClientMappedBufferManager<GrGpuBuffer, GrDirectContext::DirectContextID>::BufferFinishedMessage, GrDirectContext::DirectContextID, false>::Get()::$_0>(SkMessageBus<skgpu::TClientMappedBufferManager<GrGpuBuffer, GrDirectContext::DirectContextID>::BufferFinishedMessage, GrDirectContext::DirectContextID, false>::Get()::$_0&&)
Line
Count
Source
27
5.16k
    void operator()(Fn&& fn, Args&&... args) {
28
5.16k
        auto state = fState.load(std::memory_order_acquire);
29
30
5.16k
        if (state == Done) {
31
5.15k
            return;
32
5.15k
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
1
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
1
                                                                  std::memory_order_relaxed,
37
1
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
1
            fn(std::forward<Args>(args)...);
40
1
            return fState.store(Done, std::memory_order_release);
41
1
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
Unexecuted instantiation: GrGradientShader.cpp:void SkOnce::operator()<make_looping_colorizer(int, SkRGBA4f<(SkAlphaType)2> const*, SkRGBA4f<(SkAlphaType)2> const*, float const*)::$_0>(make_looping_colorizer(int, SkRGBA4f<(SkAlphaType)2> const*, SkRGBA4f<(SkAlphaType)2> const*, float const*)::$_0&&)
GrGradientShader.cpp:void SkOnce::operator()<make_unrolled_colorizer(int, SkRGBA4f<(SkAlphaType)2> const*, SkRGBA4f<(SkAlphaType)2> const*, SkRect, SkRect)::$_0>(make_unrolled_colorizer(int, SkRGBA4f<(SkAlphaType)2> const*, SkRGBA4f<(SkAlphaType)2> const*, SkRect, SkRect)::$_0&&)
Line
Count
Source
27
110
    void operator()(Fn&& fn, Args&&... args) {
28
110
        auto state = fState.load(std::memory_order_acquire);
29
30
110
        if (state == Done) {
31
107
            return;
32
107
        }
33
34
        // If it looks like no one has started calling fn(), try to claim that job.
35
3
        if (state == NotStarted && fState.compare_exchange_strong(state, Claimed,
36
3
                                                                  std::memory_order_relaxed,
37
3
                                                                  std::memory_order_relaxed)) {
38
            // Great!  We'll run fn() then notify the other threads by releasing Done into fState.
39
3
            fn(std::forward<Args>(args)...);
40
3
            return fState.store(Done, std::memory_order_release);
41
3
        }
42
43
        // Some other thread is calling fn().
44
        // We'll just spin here acquiring until it releases Done into fState.
45
0
        SK_POTENTIALLY_BLOCKING_REGION_BEGIN;
46
0
        while (fState.load(std::memory_order_acquire) != Done) { /*spin*/ }
47
0
        SK_POTENTIALLY_BLOCKING_REGION_END;
48
0
    }
Unexecuted instantiation: ClientMappedBufferManager.cpp:void SkOnce::operator()<SkMessageBus<skgpu::TClientMappedBufferManager<skgpu::graphite::Buffer, skgpu::graphite::Context::ContextID>::BufferFinishedMessage, skgpu::graphite::Context::ContextID, false>::Get()::$_0>(SkMessageBus<skgpu::TClientMappedBufferManager<skgpu::graphite::Buffer, skgpu::graphite::Context::ContextID>::BufferFinishedMessage, skgpu::graphite::Context::ContextID, false>::Get()::$_0&&)
Unexecuted instantiation: ProxyCache.cpp:void SkOnce::operator()<SkMessageBus<skgpu::UniqueKeyInvalidatedMsg_Graphite, unsigned int, true>::Get()::$_0>(SkMessageBus<skgpu::UniqueKeyInvalidatedMsg_Graphite, unsigned int, true>::Get()::$_0&&)
Unexecuted instantiation: ParagraphBuilderImpl.cpp:void SkOnce::operator()<skia::textlayout::ParagraphBuilderImpl::ensureUTF16Mapping()::$_0>(skia::textlayout::ParagraphBuilderImpl::ensureUTF16Mapping()::$_0&&)
Unexecuted instantiation: ParagraphImpl.cpp:void SkOnce::operator()<skia::textlayout::ParagraphImpl::ensureUTF16Mapping()::$_0>(skia::textlayout::ParagraphImpl::ensureUTF16Mapping()::$_0&&)
49
50
private:
51
    enum State : uint8_t { NotStarted, Claimed, Done};
52
    std::atomic<uint8_t> fState{NotStarted};
53
};
54
55
#endif  // SkOnce_DEFINED