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

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

Issue 381143002: Use a consume load in SkLazyPtr. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: compiler barrier Created 6 years, 5 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 | « no previous file | src/ports/SkBarriers_arm.h » ('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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 return prev; 81 return prev;
82 } else { 82 } else {
83 // We need a release barrier before returning ptr, which sk_atomic_cas p rovided. 83 // We need a release barrier before returning ptr, which sk_atomic_cas p rovided.
84 return ptr; 84 return ptr;
85 } 85 }
86 } 86 }
87 87
88 template <typename T> T* sk_new() { return SkNEW(T); } 88 template <typename T> T* sk_new() { return SkNEW(T); }
89 template <typename T> void sk_delete(T* ptr) { SkDELETE(ptr); } 89 template <typename T> void sk_delete(T* ptr) { SkDELETE(ptr); }
90 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
91 // 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).
92 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> >
93 class SkLazyPtr { 105 class SkLazyPtr {
94 public: 106 public:
95 T* get() { 107 T* get() {
96 // If fPtr has already been filled, we need an acquire barrier when load ing it. 108 // If fPtr has already been filled, we need a consume barrier when loadi ng it.
97 // 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.
98 T* ptr = (T*)sk_acquire_load(&fPtr); 110 T* ptr = (T*)sk_consume_load(&fPtr);
99 return ptr ? ptr : try_cas<T*, Destroy>(&fPtr, Create()); 111 return ptr ? ptr : try_cas<T*, Destroy>(&fPtr, Create());
100 } 112 }
101 113
102 #ifdef SK_DEVELOPER 114 #ifdef SK_DEVELOPER
103 // FIXME: We know we leak refs on some classes. For now, let them leak. 115 // FIXME: We know we leak refs on some classes. For now, let them leak.
104 void cleanup(SkFontConfigInterfaceDirect*) {} 116 void cleanup(SkFontConfigInterfaceDirect*) {}
105 template <typename U> void cleanup(U* ptr) { Destroy(ptr); } 117 template <typename U> void cleanup(U* ptr) { Destroy(ptr); }
106 118
107 ~SkLazyPtr() { 119 ~SkLazyPtr() {
108 this->cleanup((T*)fPtr); 120 this->cleanup((T*)fPtr);
109 fPtr = NULL; 121 fPtr = NULL;
110 } 122 }
111 #endif 123 #endif
112 124
113 private: 125 private:
114 void* fPtr; 126 void* fPtr;
115 }; 127 };
116 128
117 template <typename T> T* sk_new_arg(int i) { return SkNEW_ARGS(T, (i)); } 129 template <typename T> T* sk_new_arg(int i) { return SkNEW_ARGS(T, (i)); }
118 130
119 // This has no constructor and must be zero-initalized (the macro above does thi s). 131 // This has no constructor and must be zero-initalized (the macro above does thi s).
120 template <typename T, int N, T* (*Create)(int) = sk_new_arg<T>, void (*Destroy)( T*) = sk_delete<T> > 132 template <typename T, int N, T* (*Create)(int) = sk_new_arg<T>, void (*Destroy)( T*) = sk_delete<T> >
121 class SkLazyPtrArray { 133 class SkLazyPtrArray {
122 public: 134 public:
123 T* operator[](int i) { 135 T* operator[](int i) {
124 SkASSERT(i >= 0 && i < N); 136 SkASSERT(i >= 0 && i < N);
125 // If fPtr has already been filled, we need an acquire barrier when load ing it. 137 // If fPtr has already been filled, we need an consume barrier when load ing it.
126 // If not, we need a release barrier when setting it. try_cas will do t hat. 138 // If not, we need a release barrier when setting it. try_cas will do t hat.
127 T* ptr = (T*)sk_acquire_load(&fArray[i]); 139 T* ptr = (T*)sk_consume_load(&fArray[i]);
128 return ptr ? ptr : try_cas<T*, Destroy>(&fArray[i], Create(i)); 140 return ptr ? ptr : try_cas<T*, Destroy>(&fArray[i], Create(i));
129 } 141 }
130 142
131 #ifdef SK_DEVELOPER 143 #ifdef SK_DEVELOPER
132 ~SkLazyPtrArray() { 144 ~SkLazyPtrArray() {
133 for (int i = 0; i < N; i++) { 145 for (int i = 0; i < N; i++) {
134 Destroy((T*)fArray[i]); 146 Destroy((T*)fArray[i]);
135 fArray[i] = NULL; 147 fArray[i] = NULL;
136 } 148 }
137 } 149 }
138 #endif 150 #endif
139 151
140 private: 152 private:
141 void* fArray[N]; 153 void* fArray[N];
142 }; 154 };
143 155
144 } // namespace Private 156 } // namespace Private
145 157
146 #endif//SkLazyPtr_DEFINED 158 #endif//SkLazyPtr_DEFINED
OLDNEW
« no previous file with comments | « no previous file | src/ports/SkBarriers_arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698