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