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 #ifndef SkTLS_DEFINED
9 #define SkTLS_DEFINED
10 
11 #include "SkTypes.h"
12 
13 /**
14  *  Maintains a per-thread cache, using a CreateProc as the key into that cache.
15  */
16 class SkTLS {
17 public:
18     typedef void* (*CreateProc)();
19     typedef void  (*DeleteProc)(void*);
20 
21     /**
22      *  If Get() has previously been called with this CreateProc, then this
23      *  returns its cached data, otherwise it returns nullptr. The CreateProc is
24      *  never invoked in Find, it is only used as a key for searching the
25      *  cache.
26      */
27     static void* Find(CreateProc);
28 
29     /**
30      *  Return the cached data that was returned by the CreateProc. This proc
31      *  is only called the first time Get is called, and there after it is
32      *  cached (per-thread), using the CreateProc as a key to look it up.
33      *
34      *  When this thread, or Delete is called, the cached data is removed, and
35      *  if a DeleteProc was specified, it is passed the pointer to the cached
36      *  data.
37      */
38     static void* Get(CreateProc, DeleteProc);
39 
40     /**
41      *  Remove (optionally calling the DeleteProc if it was specificed in Get)
42      *  the cached data associated with this CreateProc. If no associated cached
43      *  data is found, do nothing.
44      */
45     static void Delete(CreateProc);
46 
47 private:
48     // Our implementation requires only 1 TLS slot, as we manage multiple values
49     // ourselves in a list, with the platform specific value as our head.
50 
51     /**
52      *  Implemented by the platform, to return the value of our (one) slot per-thread
53      *
54      *  If forceCreateTheSlot is true, then we must have created the "slot" for
55      *  our TLS, even though we know that the return value will be nullptr in that
56      *  case (i.e. no-slot and first-time-slot both return nullptr). This ensures
57      *  that after calling GetSpecific, we know that we can legally call
58      *  SetSpecific.
59      *
60      *  If forceCreateTheSlot is false, then the impl can either create the
61      *  slot or not.
62      */
63     static void* PlatformGetSpecific(bool forceCreateTheSlot);
64 
65     /**
66      *  Implemented by the platform, to set the value for our (one) slot per-thread
67      *
68      *  The implementation can rely on GetSpecific(true) having been previously
69      *  called before SetSpecific is called.
70      */
71     static void  PlatformSetSpecific(void*);
72 
73 public:
74     /**
75      *  Will delete our internal list. To be called by the platform if/when its
76      *  TLS slot is deleted (often at thread shutdown).
77      *
78      *  Public *only* for the platform's use, not to be called by a client.
79      */
80     static void Destructor(void* ptr);
81 };
82 
83 #endif
84