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