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