diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-04-23 12:51:32 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-04-23 12:51:32 +0000 |
commit | e6f7d6821fa3cd836e0af6596d8a15e961ebd2e3 (patch) | |
tree | 16cbdde75c8ac2e53656a7c20c39ab002a34ad26 /src | |
parent | fa1755f12c011a474ed6b75d7ae79f127a29b7e8 (diff) |
add experimental tls (for font cache eventually)
git-svn-id: http://skia.googlecode.com/svn/trunk@3748 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkTLS.h | 36 | ||||
-rw-r--r-- | src/ports/SkThread_pthread.cpp | 80 |
2 files changed, 116 insertions, 0 deletions
diff --git a/src/core/SkTLS.h b/src/core/SkTLS.h new file mode 100644 index 0000000000..86886f0080 --- /dev/null +++ b/src/core/SkTLS.h @@ -0,0 +1,36 @@ +// +// SkTLS.h +// +// +// Created by Mike Reed on 4/21/12. +// Copyright (c) 2012 __MyCompanyName__. All rights reserved. +// + +#ifndef SkTLS_DEFINED +#define SkTLS_DEFINED + +#include "SkTypes.h" + +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 + * never invoked in Find, it is only used as a key for searching the + * cache. + */ + static void* Find(CreateProc); +}; + +#endif diff --git a/src/ports/SkThread_pthread.cpp b/src/ports/SkThread_pthread.cpp index 4750d4f2c4..87606e2ca7 100644 --- a/src/ports/SkThread_pthread.cpp +++ b/src/ports/SkThread_pthread.cpp @@ -149,3 +149,83 @@ void SkMutex::release() { } #endif // !SK_USE_POSIX_THREADS + +/////////////////////////////////////////////////////////////////////////////// + +#include "SkTLS.h" + +struct SkTLSRec { + SkTLSRec* fNext; + void* fData; + SkTLS::CreateProc fCreateProc; + SkTLS::DeleteProc fDeleteProc; +}; + +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; + rec = next; + } while (NULL != rec); +} + +static pthread_key_t gSkTLSKey; +static pthread_once_t gSkTLSKey_Once = PTHREAD_ONCE_INIT; + +static void sk_tls_make_key() { + (void)pthread_key_create(&gSkTLSKey, sk_tls_destructor); +} + +void* SkTLS::Get(CreateProc createProc, DeleteProc deleteProc) { + if (NULL == createProc) { + return NULL; + } + + (void)pthread_once(&gSkTLSKey_Once, sk_tls_make_key); + void* ptr = pthread_getspecific(gSkTLSKey); + + 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; + (void)pthread_setspecific(gSkTLSKey, rec); + + rec->fData = createProc(); + rec->fCreateProc = createProc; + rec->fDeleteProc = deleteProc; + return rec->fData; +} + +void* SkTLS::Find(CreateProc createProc) { + if (NULL == createProc) { + return NULL; + } + + (void)pthread_once(&gSkTLSKey_Once, sk_tls_make_key); + void* ptr = pthread_getspecific(gSkTLSKey); + + if (ptr) { + const SkTLSRec* rec = (const SkTLSRec*)ptr; + do { + if (rec->fCreateProc == createProc) { + return rec->fData; + } + } while ((rec = rec->fNext) != NULL); + } + return NULL; +} + |