1 #include "SkTLS.h" 2 3 // enable to help debug TLS storage 4 //#define SK_TRACE_TLS_LIFETIME 5 6 7 #ifdef SK_TRACE_TLS_LIFETIME 8 #include "SkThread.h" 9 static int32_t gTLSRecCount; 10 #endif 11 12 struct SkTLSRec { 13 SkTLSRec* fNext; 14 void* fData; 15 SkTLS::CreateProc fCreateProc; 16 SkTLS::DeleteProc fDeleteProc; 17 18 #ifdef SK_TRACE_TLS_LIFETIME SkTLSRecSkTLSRec19 SkTLSRec() { 20 int n = sk_atomic_inc(&gTLSRecCount); 21 SkDebugf(" SkTLSRec[%d]\n", n); 22 } 23 #endif 24 ~SkTLSRecSkTLSRec25 ~SkTLSRec() { 26 if (fDeleteProc) { 27 fDeleteProc(fData); 28 } 29 // else we leak fData, or it will be managed by the caller 30 31 #ifdef SK_TRACE_TLS_LIFETIME 32 int n = sk_atomic_dec(&gTLSRecCount); 33 SkDebugf("~SkTLSRec[%d]\n", n - 1); 34 #endif 35 } 36 }; 37 Destructor(void * ptr)38void SkTLS::Destructor(void* ptr) { 39 #ifdef SK_TRACE_TLS_LIFETIME 40 SkDebugf("SkTLS::Destructor(%p)\n", ptr); 41 #endif 42 43 SkTLSRec* rec = (SkTLSRec*)ptr; 44 do { 45 SkTLSRec* next = rec->fNext; 46 SkDELETE(rec); 47 rec = next; 48 } while (rec); 49 } 50 Get(CreateProc createProc,DeleteProc deleteProc)51void* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) { 52 if (NULL == createProc) { 53 return NULL; 54 } 55 56 void* ptr = SkTLS::PlatformGetSpecific(true); 57 58 if (ptr) { 59 const SkTLSRec* rec = (const SkTLSRec*)ptr; 60 do { 61 if (rec->fCreateProc == createProc) { 62 SkASSERT(rec->fDeleteProc == deleteProc); 63 return rec->fData; 64 } 65 } while ((rec = rec->fNext) != NULL); 66 // not found, so create a new one 67 } 68 69 // add a new head of our change 70 SkTLSRec* rec = new SkTLSRec; 71 rec->fNext = (SkTLSRec*)ptr; 72 73 SkTLS::PlatformSetSpecific(rec); 74 75 rec->fData = createProc(); 76 rec->fCreateProc = createProc; 77 rec->fDeleteProc = deleteProc; 78 return rec->fData; 79 } 80 Find(CreateProc createProc)81void* SkTLS::Find(CreateProc createProc) { 82 if (NULL == createProc) { 83 return NULL; 84 } 85 86 void* ptr = SkTLS::PlatformGetSpecific(false); 87 88 if (ptr) { 89 const SkTLSRec* rec = (const SkTLSRec*)ptr; 90 do { 91 if (rec->fCreateProc == createProc) { 92 return rec->fData; 93 } 94 } while ((rec = rec->fNext) != NULL); 95 } 96 return NULL; 97 } 98 Delete(CreateProc createProc)99void SkTLS::Delete(CreateProc createProc) { 100 if (NULL == createProc) { 101 return; 102 } 103 104 void* ptr = SkTLS::PlatformGetSpecific(false); 105 106 SkTLSRec* curr = (SkTLSRec*)ptr; 107 SkTLSRec* prev = NULL; 108 while (curr) { 109 SkTLSRec* next = curr->fNext; 110 if (curr->fCreateProc == createProc) { 111 if (prev) { 112 prev->fNext = next; 113 } else { 114 // we have a new head of our chain 115 SkTLS::PlatformSetSpecific(next); 116 } 117 SkDELETE(curr); 118 break; 119 } 120 prev = curr; 121 curr = next; 122 } 123 } 124