1 /* 2 * Copyright 2012 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 #include "SkTLS.h" 9 10 struct SkTLSRec { 11 SkTLSRec* fNext; 12 void* fData; 13 SkTLS::CreateProc fCreateProc; 14 SkTLS::DeleteProc fDeleteProc; 15 16 ~SkTLSRec() { 17 if (fDeleteProc) { 18 fDeleteProc(fData); 19 } 20 // else we leak fData, or it will be managed by the caller 21 } 22 }; 23 24 void SkTLS::Destructor(void* ptr) { 25 SkTLSRec* rec = (SkTLSRec*)ptr; 26 do { 27 SkTLSRec* next = rec->fNext; 28 delete rec; 29 rec = next; 30 } while (rec); 31 } 32 33 void* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) { 34 if (nullptr == createProc) { 35 return nullptr; 36 } 37 38 void* ptr = SkTLS::PlatformGetSpecific(true); 39 40 if (ptr) { 41 const SkTLSRec* rec = (const SkTLSRec*)ptr; 42 do { 43 if (rec->fCreateProc == createProc) { 44 SkASSERT(rec->fDeleteProc == deleteProc); 45 return rec->fData; 46 } 47 } while ((rec = rec->fNext) != nullptr); 48 // not found, so create a new one 49 } 50 51 // add a new head of our change 52 SkTLSRec* rec = new SkTLSRec; 53 rec->fNext = (SkTLSRec*)ptr; 54 55 SkTLS::PlatformSetSpecific(rec); 56 57 rec->fData = createProc(); 58 rec->fCreateProc = createProc; 59 rec->fDeleteProc = deleteProc; 60 return rec->fData; 61 } 62 63 void* SkTLS::Find(CreateProc createProc) { 64 if (nullptr == createProc) { 65 return nullptr; 66 } 67 68 void* ptr = SkTLS::PlatformGetSpecific(false); 69 70 if (ptr) { 71 const SkTLSRec* rec = (const SkTLSRec*)ptr; 72 do { 73 if (rec->fCreateProc == createProc) { 74 return rec->fData; 75 } 76 } while ((rec = rec->fNext) != nullptr); 77 } 78 return nullptr; 79 } 80 81 void SkTLS::Delete(CreateProc createProc) { 82 if (nullptr == createProc) { 83 return; 84 } 85 86 void* ptr = SkTLS::PlatformGetSpecific(false); 87 88 SkTLSRec* curr = (SkTLSRec*)ptr; 89 SkTLSRec* prev = nullptr; 90 while (curr) { 91 SkTLSRec* next = curr->fNext; 92 if (curr->fCreateProc == createProc) { 93 if (prev) { 94 prev->fNext = next; 95 } else { 96 // we have a new head of our chain 97 SkTLS::PlatformSetSpecific(next); 98 } 99 delete curr; 100 break; 101 } 102 prev = curr; 103 curr = next; 104 } 105 } 106