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

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

Issue 669783002: SkLazyPtr follow ups (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: no static 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
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
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::SkLazyPtrBase<T, ##__VA_ARGS__> name 52 namespace {} static Private::SkStaticLazyPtr<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::SkStaticLazyPtrArray<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 // 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.
62 62
63 #include "SkDynamicAnnotations.h" 63 #include "SkDynamicAnnotations.h"
64 #include "SkThread.h" 64 #include "SkThread.h"
65 #include "SkThreadPriv.h" 65 #include "SkThreadPriv.h"
(...skipping 29 matching lines...) Expand all
95 // _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
96 // 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 /
97 // reader-consumes memory pairing rather than the more general write-releases / 97 // reader-consumes memory pairing rather than the more general write-releases /
98 // reader-acquires convention. 98 // reader-acquires convention.
99 // 99 //
100 // 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,
101 // 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.
102 102
103 // 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).
104 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> >
105 class SkLazyPtrBase { 105 class SkStaticLazyPtr {
106 public: 106 public:
107 T* get() { 107 T* get() {
108 // 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.
109 // 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.
110 T* ptr = (T*)sk_consume_load(&fPtr); 110 T* ptr = (T*)sk_consume_load(&fPtr);
111 return ptr ? ptr : try_cas<T*, Destroy>(&fPtr, Create()); 111 return ptr ? ptr : try_cas<T*, Destroy>(&fPtr, Create());
112 } 112 }
113 113
114 protected: 114 private:
115 void* fPtr; 115 void* fPtr;
116 }; 116 };
117 117
118 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)); }
119 119
120 // 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).
121 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> >
122 class SkLazyPtrArray { 122 class SkStaticLazyPtrArray {
123 public: 123 public:
124 T* operator[](int i) { 124 T* operator[](int i) {
125 SkASSERT(i >= 0 && i < N); 125 SkASSERT(i >= 0 && i < N);
126 // 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.
127 // 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.
128 T* ptr = (T*)sk_consume_load(&fArray[i]); 128 T* ptr = (T*)sk_consume_load(&fArray[i]);
129 return ptr ? ptr : try_cas<T*, Destroy>(&fArray[i], Create(i)); 129 return ptr ? ptr : try_cas<T*, Destroy>(&fArray[i], Create(i));
130 } 130 }
131 131
132 private: 132 private:
133 void* fArray[N]; 133 void* fArray[N];
134 }; 134 };
135 135
136 } // namespace Private 136 } // namespace Private
137 137
138 // This version is suitable for use as a class member. 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. 139 // It's much the same as above except:
140 template <typename T, 140 // - it has a constructor to zero itself;
141 T* (*Create)() = Private::sk_new<T>, 141 // - it has a destructor to clean up;
142 void (*Destroy)(T*) = Private::sk_delete<T> > 142 // - get() calls SkNew(T) to create the pointer;
143 class SkLazyPtr : public Private::SkLazyPtrBase<T, Create, Destroy> { 143 // - get(functor) calls functor to create the pointer.
144 template <typename T, void (*Destroy)(T*) = Private::sk_delete<T> >
145 class SkLazyPtr : SkNoncopyable {
144 public: 146 public:
145 SkLazyPtr() { INHERITED::fPtr = NULL; } 147 SkLazyPtr() : fPtr(NULL) {}
146 ~SkLazyPtr() { if (INHERITED::fPtr) { Destroy((T*)INHERITED::fPtr); } } 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
147 private: 161 private:
148 typedef Private::SkLazyPtrBase<T, Create, Destroy> INHERITED; 162 void* fPtr;
149 }; 163 };
150 164
151 165
152 #endif//SkLazyPtr_DEFINED 166 #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