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