add SkTLS::Delete

git-svn-id: http://skia.googlecode.com/svn/trunk@3752 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2012-04-23 15:49:45 +00:00
parent 098370137f
commit ae1b6b61ce
2 changed files with 57 additions and 13 deletions

View File

@ -11,19 +11,14 @@
#include "SkTypes.h"
/**
* Maintains a per-thread cache, using a CreateProc as the key into that cache.
*/
class SkTLS {
public:
typedef void* (*CreateProc)();
typedef void (*DeleteProc)(void*);
/**
* Create proc is called once per thread, and its return value is cached
* and returned by this call, treating the proc as a key. When this thread
* exists, if DeleteProc is not NULL, it is called and passed the value
* that was returned by CreateProc.
*/
static void* Get(CreateProc, DeleteProc);
/**
* If Get() has previously been called with this CreateProc, then this
* returns its cached data, otherwise it returns NULL. The CreateProc is
@ -31,6 +26,24 @@ public:
* cache.
*/
static void* Find(CreateProc);
/**
* Return the cached data that was returned by the CreateProc. This proc
* is only called the first time Get is called, and there after it is
* cached (per-thread), using the CreateProc as a key to look it up.
*
* When this thread, or Delete is called, the cached data is removed, and
* if a DeleteProc was specified, it is passed the pointer to the cached
* data.
*/
static void* Get(CreateProc, DeleteProc);
/**
* Remove (optionally calling the DeleteProc if it was specificed in Get)
* the cached data associated with this CreateProc. If no associated cached
* data is found, do nothing.
*/
static void Delete(CreateProc);
};
#endif

View File

@ -159,16 +159,20 @@ struct SkTLSRec {
void* fData;
SkTLS::CreateProc fCreateProc;
SkTLS::DeleteProc fDeleteProc;
~SkTLSRec() {
if (fDeleteProc) {
fDeleteProc(fData);
}
// else we leak fData, or it will be managed by the caller
}
};
static void sk_tls_destructor(void* ptr) {
SkTLSRec* rec = (SkTLSRec*)ptr;
do {
SkTLSRec* next = rec->fNext;
if (rec->fDeleteProc) {
rec->fDeleteProc(rec->fData);
}
delete rec;
SkDELETE(rec);
rec = next;
} while (NULL != rec);
}
@ -229,3 +233,30 @@ void* SkTLS::Find(CreateProc createProc) {
return NULL;
}
void SkTLS::Delete(CreateProc createProc) {
if (NULL == createProc) {
return;
}
(void)pthread_once(&gSkTLSKey_Once, sk_tls_make_key);
void* ptr = pthread_getspecific(gSkTLSKey);
SkTLSRec* curr = (const SkTLSRec*)ptr;
SkTLSRec* prev = NULL;
while (curr) {
SkTLSRec* next = curr->fNext;
if (rec->fCreateProc == createProc) {
if (prev) {
prev->fNext = next;
} else {
// we have a new head of our chain
(void)pthread_setspecific(gSkTLSKey, next);
}
SkDELETE(curr);
break;
}
prev = curr;
curr = next;
}
}