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