xref: /aosp_15_r20/external/skia/include/private/base/SingleOwner.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef skgpu_SingleOwner_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define skgpu_SingleOwner_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h" // IWYU pragma: keep
12*c8dee2aaSAndroid Build Coastguard Worker 
13*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_DEBUG)
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkMutex.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkThreadAnnotations.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkThreadID.h"
18*c8dee2aaSAndroid Build Coastguard Worker 
19*c8dee2aaSAndroid Build Coastguard Worker #endif
20*c8dee2aaSAndroid Build Coastguard Worker 
21*c8dee2aaSAndroid Build Coastguard Worker namespace skgpu {
22*c8dee2aaSAndroid Build Coastguard Worker 
23*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_DEBUG)
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker #define SKGPU_ASSERT_SINGLE_OWNER(obj) \
26*c8dee2aaSAndroid Build Coastguard Worker     skgpu::SingleOwner::AutoEnforce debug_SingleOwner(obj, __FILE__, __LINE__);
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker // This is a debug tool to verify an object is only being used from one thread at a time.
29*c8dee2aaSAndroid Build Coastguard Worker class SingleOwner {
30*c8dee2aaSAndroid Build Coastguard Worker public:
SingleOwner()31*c8dee2aaSAndroid Build Coastguard Worker      SingleOwner() : fOwner(kIllegalThreadID), fReentranceCount(0) {}
32*c8dee2aaSAndroid Build Coastguard Worker 
33*c8dee2aaSAndroid Build Coastguard Worker      struct AutoEnforce {
AutoEnforceAutoEnforce34*c8dee2aaSAndroid Build Coastguard Worker          AutoEnforce(SingleOwner* so, const char* file, int line)
35*c8dee2aaSAndroid Build Coastguard Worker                 : fFile(file), fLine(line), fSO(so) {
36*c8dee2aaSAndroid Build Coastguard Worker              fSO->enter(file, line);
37*c8dee2aaSAndroid Build Coastguard Worker          }
~AutoEnforceAutoEnforce38*c8dee2aaSAndroid Build Coastguard Worker          ~AutoEnforce() { fSO->exit(fFile, fLine); }
39*c8dee2aaSAndroid Build Coastguard Worker 
40*c8dee2aaSAndroid Build Coastguard Worker          const char* fFile;
41*c8dee2aaSAndroid Build Coastguard Worker          int fLine;
42*c8dee2aaSAndroid Build Coastguard Worker          SingleOwner* fSO;
43*c8dee2aaSAndroid Build Coastguard Worker      };
44*c8dee2aaSAndroid Build Coastguard Worker 
45*c8dee2aaSAndroid Build Coastguard Worker private:
enter(const char * file,int line)46*c8dee2aaSAndroid Build Coastguard Worker      void enter(const char* file, int line) {
47*c8dee2aaSAndroid Build Coastguard Worker          SkAutoMutexExclusive lock(fMutex);
48*c8dee2aaSAndroid Build Coastguard Worker          SkThreadID self = SkGetThreadID();
49*c8dee2aaSAndroid Build Coastguard Worker          SkASSERTF(fOwner == self || fOwner == kIllegalThreadID, "%s:%d Single owner failure.",
50*c8dee2aaSAndroid Build Coastguard Worker                    file, line);
51*c8dee2aaSAndroid Build Coastguard Worker          fReentranceCount++;
52*c8dee2aaSAndroid Build Coastguard Worker          fOwner = self;
53*c8dee2aaSAndroid Build Coastguard Worker      }
54*c8dee2aaSAndroid Build Coastguard Worker 
exit(const char * file,int line)55*c8dee2aaSAndroid Build Coastguard Worker      void exit(const char* file, int line) {
56*c8dee2aaSAndroid Build Coastguard Worker          SkAutoMutexExclusive lock(fMutex);
57*c8dee2aaSAndroid Build Coastguard Worker          SkASSERTF(fOwner == SkGetThreadID(), "%s:%d Single owner failure.", file, line);
58*c8dee2aaSAndroid Build Coastguard Worker          fReentranceCount--;
59*c8dee2aaSAndroid Build Coastguard Worker          if (fReentranceCount == 0) {
60*c8dee2aaSAndroid Build Coastguard Worker              fOwner = kIllegalThreadID;
61*c8dee2aaSAndroid Build Coastguard Worker          }
62*c8dee2aaSAndroid Build Coastguard Worker      }
63*c8dee2aaSAndroid Build Coastguard Worker 
64*c8dee2aaSAndroid Build Coastguard Worker      SkMutex fMutex;
65*c8dee2aaSAndroid Build Coastguard Worker      SkThreadID fOwner    SK_GUARDED_BY(fMutex);
66*c8dee2aaSAndroid Build Coastguard Worker      int fReentranceCount SK_GUARDED_BY(fMutex);
67*c8dee2aaSAndroid Build Coastguard Worker };
68*c8dee2aaSAndroid Build Coastguard Worker #else
69*c8dee2aaSAndroid Build Coastguard Worker #define SKGPU_ASSERT_SINGLE_OWNER(obj)
70*c8dee2aaSAndroid Build Coastguard Worker class SingleOwner {}; // Provide a no-op implementation so we can pass pointers to constructors
71*c8dee2aaSAndroid Build Coastguard Worker #endif
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker } // namespace skgpu
74*c8dee2aaSAndroid Build Coastguard Worker 
75*c8dee2aaSAndroid Build Coastguard Worker #endif
76