Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(506)

Side by Side Diff: src/core/SkLazyPtr.h

Issue 676523002: Add SkTypeface::getBounds() (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/core/SkTypeface.h ('k') | src/core/SkThreadPriv.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2014 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 SkLazyPtr_DEFINED
9 #define SkLazyPtr_DEFINED
10
11 /** Declare a lazily-chosen static pointer (or array of pointers) of type T.
12 *
13 * Example usage:
14 *
15 * Foo* GetSingletonFoo() {
16 * SK_DECLARE_STATIC_LAZY_PTR(Foo, singleton); // Created with SkNEW, dest royed with SkDELETE.
17 * return singleton.get();
18 * }
19 *
20 * These macros take an optional T* (*Create)() and void (*Destroy)(T*) at the end.
21 * If not given, we'll use SkNEW and SkDELETE.
22 * These options are most useful when T doesn't have a public constructor or de structor.
23 * Create comes first, so you may use a custom Create with a default Destroy, b ut not vice versa.
24 *
25 * Foo* CustomCreate() { return ...; }
26 * void CustomDestroy(Foo* ptr) { ... }
27 * Foo* GetSingletonFooWithCustomCleanup() {
28 * SK_DECLARE_STATIC_LAZY_PTR(Foo, singleton, CustomCreate, CustomDestroy);
29 * return singleton.get();
30 * }
31 *
32 * If you have a bunch of related static pointers of the same type, you can
33 * declare an array of lazy pointers together, and we'll pass the index to Crea te().
34 *
35 * Foo* CreateFoo(int i) { return ...; }
36 * Foo* GetCachedFoo(Foo::Enum enumVal) {
37 * SK_DECLARE_STATIC_LAZY_PTR_ARRAY(Foo, Foo::kEnumCount, cachedFoos, Creat eFoo);
38 * return cachedFoos[enumVal];
39 * }
40 *
41 *
42 * You can think of SK_DECLARE_STATIC_LAZY_PTR as a cheaper specialization of
43 * SkOnce. There is no mutex or extra storage used past the pointer itself.
44 *
45 * We may call Create more than once, but all threads will see the same pointer
46 * returned from get(). Any extra calls to Create will be cleaned up.
47 *
48 * These macros must be used in a global scope, not in function scope or as a c lass member.
49 */
50
51 #define SK_DECLARE_STATIC_LAZY_PTR(T, name, ...) \
52 namespace {} static Private::SkStaticLazyPtr<T, ##__VA_ARGS__> name
53
54 #define SK_DECLARE_STATIC_LAZY_PTR_ARRAY(T, name, N, ...) \
55 namespace {} static Private::SkStaticLazyPtrArray<T, N, ##__VA_ARGS__> name
56
57 // namespace {} forces these macros to only be legal in global scopes. Chrome h as thread-safety
58 // problems with them in function-local statics because it uses -fno-threadsafe- statics, and even
59 // in builds with threadsafe statics, those threadsafe statics are just unnecess ary overhead.
60
61 // Everything below here is private implementation details. Don't touch, don't even look.
62
63 #include "SkDynamicAnnotations.h"
64 #include "SkThread.h"
65 #include "SkThreadPriv.h"
66
67 // See FIXME below.
68 class SkFontConfigInterfaceDirect;
69
70 namespace Private {
71
72 // Set *dst to ptr if *dst is NULL. Returns value of *dst, destroying ptr if no t swapped in.
73 // Issues the same memory barriers as sk_atomic_cas: acquire on failure, release on success.
74 template <typename P, void (*Destroy)(P)>
75 static P try_cas(void** dst, P ptr) {
76 P prev = (P)sk_atomic_cas(dst, NULL, ptr);
77
78 if (prev) {
79 // We need an acquire barrier before returning prev, which sk_atomic_cas provided.
80 Destroy(ptr);
81 return prev;
82 } else {
83 // We need a release barrier before returning ptr, which sk_atomic_cas p rovided.
84 return ptr;
85 }
86 }
87
88 template <typename T> T* sk_new() { return SkNEW(T); }
89 template <typename T> void sk_delete(T* ptr) { SkDELETE(ptr); }
90
91 // We're basing these implementations here on this article:
92 // http://preshing.com/20140709/the-purpose-of-memory_order_consume-in-cpp11/
93 //
94 // Because the users of SkLazyPtr and SkLazyPtrArray will read the pointers
95 // _through_ our atomically set pointer, there is a data dependency between our
96 // atomic and the guarded data, and so we only need writer-releases /
97 // reader-consumes memory pairing rather than the more general write-releases /
98 // reader-acquires convention.
99 //
100 // This is nice, because a sk_consume_load is free on all our platforms: x86,
101 // ARM, MIPS. In contrast, sk_acquire_load issues a memory barrier on non-x86.
102
103 // This has no constructor and must be zero-initalized (the macro above does thi s).
104 template <typename T, T* (*Create)() = sk_new<T>, void (*Destroy)(T*) = sk_delet e<T> >
105 class SkStaticLazyPtr {
106 public:
107 T* get() {
108 // If fPtr has already been filled, we need a consume barrier when loadi ng it.
109 // If not, we need a release barrier when setting it. try_cas will do t hat.
110 T* ptr = (T*)sk_consume_load(&fPtr);
111 return ptr ? ptr : try_cas<T*, Destroy>(&fPtr, Create());
112 }
113
114 private:
115 void* fPtr;
116 };
117
118 template <typename T> T* sk_new_arg(int i) { return SkNEW_ARGS(T, (i)); }
119
120 // This has no constructor and must be zero-initalized (the macro above does thi s).
121 template <typename T, int N, T* (*Create)(int) = sk_new_arg<T>, void (*Destroy)( T*) = sk_delete<T> >
122 class SkStaticLazyPtrArray {
123 public:
124 T* operator[](int i) {
125 SkASSERT(i >= 0 && i < N);
126 // If fPtr has already been filled, we need an consume barrier when load ing it.
127 // If not, we need a release barrier when setting it. try_cas will do t hat.
128 T* ptr = (T*)sk_consume_load(&fArray[i]);
129 return ptr ? ptr : try_cas<T*, Destroy>(&fArray[i], Create(i));
130 }
131
132 private:
133 void* fArray[N];
134 };
135
136 } // namespace Private
137
138 // This version is suitable for use as a class member.
139 // It's much the same as above except:
140 // - it has a constructor to zero itself;
141 // - it has a destructor to clean up;
142 // - get() calls SkNew(T) to create the pointer;
143 // - get(functor) calls functor to create the pointer.
144 template <typename T, void (*Destroy)(T*) = Private::sk_delete<T> >
145 class SkLazyPtr : SkNoncopyable {
146 public:
147 SkLazyPtr() : fPtr(NULL) {}
148 ~SkLazyPtr() { if (fPtr) { Destroy((T*)fPtr); } }
149
150 T* get() {
151 T* ptr = (T*)sk_consume_load(&fPtr);
152 return ptr ? ptr : Private::try_cas<T*, Destroy>(&fPtr, SkNEW(T));
153 }
154
155 template <typename Create>
156 T* get(const Create& create) {
157 T* ptr = (T*)sk_consume_load(&fPtr);
158 return ptr ? ptr : Private::try_cas<T*, Destroy>(&fPtr, create());
159 }
160
161 private:
162 void* fPtr;
163 };
164
165
166 #endif//SkLazyPtr_DEFINED
OLDNEW
« no previous file with comments | « include/core/SkTypeface.h ('k') | src/core/SkThreadPriv.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698