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

Side by Side Diff: include/private/SkOncePtr.h

Issue 1359733002: Make mutex semaphore based. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: fix mutex leak Created 5 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 | « include/ports/SkMutex_win.h ('k') | include/private/SkSemaphore.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 2015 Google Inc. 2 * Copyright 2015 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 SkOncePtr_DEFINED 8 #ifndef SkOncePtr_DEFINED
9 #define SkOncePtr_DEFINED 9 #define SkOncePtr_DEFINED
10 10
11 #include "SkAtomics.h" 11 #include "SkAtomics.h"
12 #include "SkUniquePtr.h" 12 #include "SkUniquePtr.h"
13 13
14 template <typename T> class SkBaseOncePtr; 14 template <typename T> class SkBaseOncePtr;
15 15
16 // Use this to create a global static pointer that's intialized exactly once whe n you call get(). 16 // Use this to create a global static pointer that's intialized exactly once whe n you call get().
17 #define SK_DECLARE_STATIC_ONCE_PTR(type, name) namespace {} static SkBaseOncePtr <type> name 17 #define SK_DECLARE_STATIC_ONCE_PTR(type, name) namespace {} static SkBaseOncePtr <type> name;
18 18
19 // Use this for a local or member pointer that's initialized exactly once when y ou call get(). 19 // Use this for a local or member pointer that's initialized exactly once when y ou call get().
20 template <typename T, typename Delete = skstd::default_delete<T>> 20 template <typename T, typename Delete = skstd::default_delete<T>>
21 class SkOncePtr : SkNoncopyable { 21 class SkOncePtr : SkNoncopyable {
22 public: 22 public:
23 SkOncePtr() { sk_bzero(this, sizeof(*this)); } 23 SkOncePtr() { sk_bzero(this, sizeof(*this)); }
24 ~SkOncePtr() { 24 ~SkOncePtr() {
25 if (T* ptr = (T*)*this) { 25 if (T* ptr = (T*)*this) {
26 Delete()(ptr); 26 Delete()(ptr);
27 } 27 }
(...skipping 26 matching lines...) Expand all
54 } 54 }
55 */ 55 */
56 56
57 // Implementation details below here! No peeking! 57 // Implementation details below here! No peeking!
58 58
59 template <typename T> 59 template <typename T>
60 class SkBaseOncePtr { 60 class SkBaseOncePtr {
61 public: 61 public:
62 template <typename F> 62 template <typename F>
63 T* get(const F& f) const { 63 T* get(const F& f) const {
64 uintptr_t state = fState.load(sk_memory_order_acquire); 64 uintptr_t state = sk_atomic_load(&fState, sk_memory_order_acquire);
65 if (state < 2) { 65 if (state < 2) {
66 if (state == 0) { 66 if (state == 0) {
67 // It looks like no one has tried to create our pointer yet. 67 // It looks like no one has tried to create our pointer yet.
68 // We try to claim that task by atomically swapping our state fr om '0' to '1'. 68 // We try to claim that task by atomically swapping our state fr om '0' to '1'.
69 if (fState.compare_exchange(&state, 1, sk_memory_order_relaxed, 69 if (sk_atomic_compare_exchange(
70 sk_memory_order_relaxed)) { 70 &fState, &state, (uintptr_t)1, sk_memory_order_relaxed, sk_m emory_order_relaxed)) {
71 // We've claimed it. Create our pointer and store it into f State. 71 // We've claimed it. Create our pointer and store it into f State.
72 state = (uintptr_t)f(); 72 state = (uintptr_t)f();
73 SkASSERT(state > 1); 73 SkASSERT(state > 1);
74 fState.store(state, sk_memory_order_release); 74 sk_atomic_store(&fState, state, sk_memory_order_release);
75 } else { 75 } else {
76 // Someone else claimed it. 76 // Someone else claimed it.
77 // We fall through to the spin loop just below to wait for t hem to finish. 77 // We fall through to the spin loop just below to wait for t hem to finish.
78 } 78 }
79 } 79 }
80 80
81 while (state == 1) { 81 while (state == 1) {
82 // State '1' is our busy-but-not-done state. 82 // State '1' is our busy-but-not-done state.
83 // Some other thread has claimed the job of creating our pointer . 83 // Some other thread has claimed the job of creating our pointer .
84 // We just need to wait for it to finish. 84 // We just need to wait for it to finish.
85 state = fState.load(sk_memory_order_acquire); 85 state = sk_atomic_load(&fState, sk_memory_order_acquire);
86 } 86 }
87 87
88 // We shouldn't be able to get here without having created our point er. 88 // We shouldn't be able to get here without having created our point er.
89 SkASSERT(state > 1); 89 SkASSERT(state > 1);
90 } 90 }
91 return (T*)state; 91 return (T*)state;
92 } 92 }
93 93
94 operator T*() const { 94 operator T*() const {
95 auto state = fState.load(sk_memory_order_acquire); 95 auto state = sk_atomic_load(&fState, sk_memory_order_acquire);
96 return state < 2 ? nullptr : (T*)state; 96 return state < 2 ? nullptr : (T*)state;
97 // TODO: If state == 1 spin until it's not? 97 // TODO: If state == 1 spin until it's not?
98 } 98 }
99 99
100 private:
101 // fState == 0 --> we have not created our ptr yet 100 // fState == 0 --> we have not created our ptr yet
102 // fState == 1 --> someone is in the middle of creating our ptr 101 // fState == 1 --> someone is in the middle of creating our ptr
103 // else --> (T*)fState is our ptr 102 // else --> (T*)fState is our ptr
104 mutable SkAtomic<uintptr_t> fState; 103 mutable uintptr_t fState;
105 }; 104 };
106 105
107 #endif//SkOncePtr_DEFINED 106 #endif//SkOncePtr_DEFINED
OLDNEW
« no previous file with comments | « include/ports/SkMutex_win.h ('k') | include/private/SkSemaphore.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698