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

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

Issue 653183006: SkLazyPtr suitable as a local or class member. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: namespace Created 6 years, 2 months 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 | « gyp/tests.gypi ('k') | tests/LazyPtr.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #ifndef SkLazyPtr_DEFINED 8 #ifndef SkLazyPtr_DEFINED
9 #define SkLazyPtr_DEFINED 9 #define SkLazyPtr_DEFINED
10 10
11 /** Declare a lazily-chosen static pointer (or array of pointers) of type F. 11 /** Declare a lazily-chosen static pointer (or array of pointers) of type T.
12 * 12 *
13 * Example usage: 13 * Example usage:
14 * 14 *
15 * Foo* GetSingletonFoo() { 15 * Foo* GetSingletonFoo() {
16 * SK_DECLARE_STATIC_LAZY_PTR(Foo, singleton); // Created with SkNEW, dest royed with SkDELETE. 16 * SK_DECLARE_STATIC_LAZY_PTR(Foo, singleton); // Created with SkNEW, dest royed with SkDELETE.
17 * return singleton.get(); 17 * return singleton.get();
18 * } 18 * }
19 * 19 *
20 * These macros take an optional T* (*Create)() and void (*Destroy)(T*) at the end. 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. 21 * If not given, we'll use SkNEW and SkDELETE.
(...skipping 20 matching lines...) Expand all
42 * You can think of SK_DECLARE_STATIC_LAZY_PTR as a cheaper specialization of 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. 43 * SkOnce. There is no mutex or extra storage used past the pointer itself.
44 * 44 *
45 * We may call Create more than once, but all threads will see the same pointer 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. 46 * returned from get(). Any extra calls to Create will be cleaned up.
47 * 47 *
48 * These macros must be used in a global scope, not in function scope or as a c lass member. 48 * These macros must be used in a global scope, not in function scope or as a c lass member.
49 */ 49 */
50 50
51 #define SK_DECLARE_STATIC_LAZY_PTR(T, name, ...) \ 51 #define SK_DECLARE_STATIC_LAZY_PTR(T, name, ...) \
52 namespace {} static Private::SkLazyPtr<T, ##__VA_ARGS__> name 52 namespace {} static Private::SkLazyPtrBase<T, ##__VA_ARGS__> name
53 53
54 #define SK_DECLARE_STATIC_LAZY_PTR_ARRAY(T, name, N, ...) \ 54 #define SK_DECLARE_STATIC_LAZY_PTR_ARRAY(T, name, N, ...) \
55 namespace {} static Private::SkLazyPtrArray<T, N, ##__VA_ARGS__> name 55 namespace {} static Private::SkLazyPtrArray<T, N, ##__VA_ARGS__> name
56 56
57 // namespace {} forces these macros to only be legal in global scopes. Chrome h as thread-safety 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 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. 59 // in builds with threadsafe statics, those threadsafe statics are just unnecess ary overhead.
60 60
61
62 // Everything below here is private implementation details. Don't touch, don't even look. 61 // Everything below here is private implementation details. Don't touch, don't even look.
63 62
64 #include "SkDynamicAnnotations.h" 63 #include "SkDynamicAnnotations.h"
65 #include "SkThread.h" 64 #include "SkThread.h"
66 #include "SkThreadPriv.h" 65 #include "SkThreadPriv.h"
67 66
68 // See FIXME below. 67 // See FIXME below.
69 class SkFontConfigInterfaceDirect; 68 class SkFontConfigInterfaceDirect;
70 69
71 namespace Private { 70 namespace Private {
(...skipping 24 matching lines...) Expand all
96 // _through_ our atomically set pointer, there is a data dependency between our 95 // _through_ our atomically set pointer, there is a data dependency between our
97 // atomic and the guarded data, and so we only need writer-releases / 96 // atomic and the guarded data, and so we only need writer-releases /
98 // reader-consumes memory pairing rather than the more general write-releases / 97 // reader-consumes memory pairing rather than the more general write-releases /
99 // reader-acquires convention. 98 // reader-acquires convention.
100 // 99 //
101 // This is nice, because a sk_consume_load is free on all our platforms: x86, 100 // This is nice, because a sk_consume_load is free on all our platforms: x86,
102 // ARM, MIPS. In contrast, sk_acquire_load issues a memory barrier on non-x86. 101 // ARM, MIPS. In contrast, sk_acquire_load issues a memory barrier on non-x86.
103 102
104 // This has no constructor and must be zero-initalized (the macro above does thi s). 103 // This has no constructor and must be zero-initalized (the macro above does thi s).
105 template <typename T, T* (*Create)() = sk_new<T>, void (*Destroy)(T*) = sk_delet e<T> > 104 template <typename T, T* (*Create)() = sk_new<T>, void (*Destroy)(T*) = sk_delet e<T> >
106 class SkLazyPtr { 105 class SkLazyPtrBase {
107 public: 106 public:
108 T* get() { 107 T* get() {
109 // If fPtr has already been filled, we need a consume barrier when loadi ng it. 108 // If fPtr has already been filled, we need a consume barrier when loadi ng it.
110 // If not, we need a release barrier when setting it. try_cas will do t hat. 109 // If not, we need a release barrier when setting it. try_cas will do t hat.
111 T* ptr = (T*)sk_consume_load(&fPtr); 110 T* ptr = (T*)sk_consume_load(&fPtr);
112 return ptr ? ptr : try_cas<T*, Destroy>(&fPtr, Create()); 111 return ptr ? ptr : try_cas<T*, Destroy>(&fPtr, Create());
113 } 112 }
114 113
115 private: 114 protected:
116 void* fPtr; 115 void* fPtr;
117 }; 116 };
118 117
119 template <typename T> T* sk_new_arg(int i) { return SkNEW_ARGS(T, (i)); } 118 template <typename T> T* sk_new_arg(int i) { return SkNEW_ARGS(T, (i)); }
120 119
121 // This has no constructor and must be zero-initalized (the macro above does thi s). 120 // This has no constructor and must be zero-initalized (the macro above does thi s).
122 template <typename T, int N, T* (*Create)(int) = sk_new_arg<T>, void (*Destroy)( T*) = sk_delete<T> > 121 template <typename T, int N, T* (*Create)(int) = sk_new_arg<T>, void (*Destroy)( T*) = sk_delete<T> >
123 class SkLazyPtrArray { 122 class SkLazyPtrArray {
124 public: 123 public:
125 T* operator[](int i) { 124 T* operator[](int i) {
126 SkASSERT(i >= 0 && i < N); 125 SkASSERT(i >= 0 && i < N);
127 // If fPtr has already been filled, we need an consume barrier when load ing it. 126 // If fPtr has already been filled, we need an consume barrier when load ing it.
128 // If not, we need a release barrier when setting it. try_cas will do t hat. 127 // If not, we need a release barrier when setting it. try_cas will do t hat.
129 T* ptr = (T*)sk_consume_load(&fArray[i]); 128 T* ptr = (T*)sk_consume_load(&fArray[i]);
130 return ptr ? ptr : try_cas<T*, Destroy>(&fArray[i], Create(i)); 129 return ptr ? ptr : try_cas<T*, Destroy>(&fArray[i], Create(i));
131 } 130 }
132 131
133 private: 132 private:
134 void* fArray[N]; 133 void* fArray[N];
135 }; 134 };
136 135
137 } // namespace Private 136 } // namespace Private
138 137
138 // This version is suitable for use as a class member.
139 // It's the same as above except it has a constructor to zero itself and a destr uctor to clean up.
140 template <typename T,
141 T* (*Create)() = Private::sk_new<T>,
142 void (*Destroy)(T*) = Private::sk_delete<T> >
143 class SkLazyPtr : public Private::SkLazyPtrBase<T, Create, Destroy> {
144 public:
145 SkLazyPtr() { INHERITED::fPtr = NULL; }
146 ~SkLazyPtr() { if (INHERITED::fPtr) { Destroy((T*)INHERITED::fPtr); } }
147 private:
148 typedef Private::SkLazyPtrBase<T, Create, Destroy> INHERITED;
149 };
150
151
139 #endif//SkLazyPtr_DEFINED 152 #endif//SkLazyPtr_DEFINED
OLDNEW
« no previous file with comments | « gyp/tests.gypi ('k') | tests/LazyPtr.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698