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