| OLD | NEW | 
|---|
| 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  Loading... | 
| 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  Loading... | 
| 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 | 
| OLD | NEW | 
|---|