e16efc1882
git-svn-id: http://skia.googlecode.com/svn/trunk@7406 2bbb7eff-a529-9590-31e7-b0007b416f81
124 lines
2.8 KiB
C++
Executable File
124 lines
2.8 KiB
C++
Executable File
#include "SkTLS.h"
|
|
|
|
// enable to help debug TLS storage
|
|
//#define SK_TRACE_TLS_LIFETIME
|
|
|
|
|
|
#ifdef SK_TRACE_TLS_LIFETIME
|
|
#include "SkThread.h"
|
|
static int32_t gTLSRecCount;
|
|
#endif
|
|
|
|
struct SkTLSRec {
|
|
SkTLSRec* fNext;
|
|
void* fData;
|
|
SkTLS::CreateProc fCreateProc;
|
|
SkTLS::DeleteProc fDeleteProc;
|
|
|
|
#ifdef SK_TRACE_TLS_LIFETIME
|
|
SkTLSRec() {
|
|
int n = sk_atomic_inc(&gTLSRecCount);
|
|
SkDebugf(" SkTLSRec[%d]\n", n);
|
|
}
|
|
#endif
|
|
|
|
~SkTLSRec() {
|
|
if (fDeleteProc) {
|
|
fDeleteProc(fData);
|
|
}
|
|
// else we leak fData, or it will be managed by the caller
|
|
|
|
#ifdef SK_TRACE_TLS_LIFETIME
|
|
int n = sk_atomic_dec(&gTLSRecCount);
|
|
SkDebugf("~SkTLSRec[%d]\n", n - 1);
|
|
#endif
|
|
}
|
|
};
|
|
|
|
void SkTLS::Destructor(void* ptr) {
|
|
#ifdef SK_TRACE_TLS_LIFETIME
|
|
SkDebugf("SkTLS::Destructor(%p)\n", ptr);
|
|
#endif
|
|
|
|
SkTLSRec* rec = (SkTLSRec*)ptr;
|
|
do {
|
|
SkTLSRec* next = rec->fNext;
|
|
SkDELETE(rec);
|
|
rec = next;
|
|
} while (NULL != rec);
|
|
}
|
|
|
|
void* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) {
|
|
if (NULL == createProc) {
|
|
return NULL;
|
|
}
|
|
|
|
void* ptr = SkTLS::PlatformGetSpecific(true);
|
|
|
|
if (ptr) {
|
|
const SkTLSRec* rec = (const SkTLSRec*)ptr;
|
|
do {
|
|
if (rec->fCreateProc == createProc) {
|
|
SkASSERT(rec->fDeleteProc == deleteProc);
|
|
return rec->fData;
|
|
}
|
|
} while ((rec = rec->fNext) != NULL);
|
|
// not found, so create a new one
|
|
}
|
|
|
|
// add a new head of our change
|
|
SkTLSRec* rec = new SkTLSRec;
|
|
rec->fNext = (SkTLSRec*)ptr;
|
|
|
|
SkTLS::PlatformSetSpecific(rec);
|
|
|
|
rec->fData = createProc();
|
|
rec->fCreateProc = createProc;
|
|
rec->fDeleteProc = deleteProc;
|
|
return rec->fData;
|
|
}
|
|
|
|
void* SkTLS::Find(CreateProc createProc) {
|
|
if (NULL == createProc) {
|
|
return NULL;
|
|
}
|
|
|
|
void* ptr = SkTLS::PlatformGetSpecific(false);
|
|
|
|
if (ptr) {
|
|
const SkTLSRec* rec = (const SkTLSRec*)ptr;
|
|
do {
|
|
if (rec->fCreateProc == createProc) {
|
|
return rec->fData;
|
|
}
|
|
} while ((rec = rec->fNext) != NULL);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void SkTLS::Delete(CreateProc createProc) {
|
|
if (NULL == createProc) {
|
|
return;
|
|
}
|
|
|
|
void* ptr = SkTLS::PlatformGetSpecific(false);
|
|
|
|
SkTLSRec* curr = (SkTLSRec*)ptr;
|
|
SkTLSRec* prev = NULL;
|
|
while (curr) {
|
|
SkTLSRec* next = curr->fNext;
|
|
if (curr->fCreateProc == createProc) {
|
|
if (prev) {
|
|
prev->fNext = next;
|
|
} else {
|
|
// we have a new head of our chain
|
|
SkTLS::PlatformSetSpecific(next);
|
|
}
|
|
SkDELETE(curr);
|
|
break;
|
|
}
|
|
prev = curr;
|
|
curr = next;
|
|
}
|
|
}
|