OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CrossThreadHolder_h | 5 #ifndef CrossThreadHolder_h |
6 #define CrossThreadHolder_h | 6 #define CrossThreadHolder_h |
7 | 7 |
8 #include "core/dom/ActiveDOMObject.h" | 8 #include "core/dom/ActiveDOMObject.h" |
9 #include "core/dom/CrossThreadTask.h" | 9 #include "core/dom/CrossThreadTask.h" |
10 #include "core/dom/ExecutionContext.h" | 10 #include "core/dom/ExecutionContext.h" |
11 #include "public/platform/WebTraceLocation.h" | 11 #include "public/platform/WebTraceLocation.h" |
12 #include "wtf/Locker.h" | 12 #include "wtf/Locker.h" |
| 13 #include "wtf/OwnPtr.h" |
| 14 #include "wtf/PassOwnPtr.h" |
13 #include "wtf/PassRefPtr.h" | 15 #include "wtf/PassRefPtr.h" |
14 #include "wtf/PtrUtil.h" | |
15 #include "wtf/RefPtr.h" | 16 #include "wtf/RefPtr.h" |
16 #include "wtf/ThreadingPrimitives.h" | 17 #include "wtf/ThreadingPrimitives.h" |
17 #include <memory> | |
18 | 18 |
19 namespace blink { | 19 namespace blink { |
20 | 20 |
21 // CrossThreadHolder<T> provides cross-thread access to |obj| of class T | 21 // CrossThreadHolder<T> provides cross-thread access to |obj| of class T |
22 // bound to the thread of |executionContext| where |obj| is created. | 22 // bound to the thread of |executionContext| where |obj| is created. |
23 // - CrossThreadHolder<T> can be passed across threads. | 23 // - CrossThreadHolder<T> can be passed across threads. |
24 // - |obj|'s methods are called on the thread of |executionContext| | 24 // - |obj|'s methods are called on the thread of |executionContext| |
25 // via CrossThreadHolder<T>::postTask(). | 25 // via CrossThreadHolder<T>::postTask(). |
26 // - |obj| is destructed on the thread of |executionContext| | 26 // - |obj| is destructed on the thread of |executionContext| |
27 // when |executionContext| is stopped or | 27 // when |executionContext| is stopped or |
28 // CrossThreadHolder is destructed (earlier of them). | 28 // CrossThreadHolder is destructed (earlier of them). |
29 // Note: |obj|'s destruction can be slightly after CrossThreadHolder. | 29 // Note: |obj|'s destruction can be slightly after CrossThreadHolder. |
30 template<typename T> | 30 template<typename T> |
31 class CrossThreadHolder final { | 31 class CrossThreadHolder final { |
32 public: | 32 public: |
33 // Must be called on the thread where |obj| is created | 33 // Must be called on the thread where |obj| is created |
34 // (== the thread of |executionContext|). | 34 // (== the thread of |executionContext|). |
35 // The current thread must be attached to Oilpan. | 35 // The current thread must be attached to Oilpan. |
36 static std::unique_ptr<CrossThreadHolder<T>> create(ExecutionContext* execut
ionContext, std::unique_ptr<T> obj) | 36 static PassOwnPtr<CrossThreadHolder<T>> create(ExecutionContext* executionCo
ntext, PassOwnPtr<T> obj) |
37 { | 37 { |
38 ASSERT(executionContext->isContextThread()); | 38 ASSERT(executionContext->isContextThread()); |
39 return wrapUnique(new CrossThreadHolder(executionContext, std::move(obj)
)); | 39 return adoptPtr(new CrossThreadHolder(executionContext, std::move(obj)))
; |
40 } | 40 } |
41 | 41 |
42 // Can be called from any thread. | 42 // Can be called from any thread. |
43 // Executes |task| with |obj| and |executionContext| on the thread of | 43 // Executes |task| with |obj| and |executionContext| on the thread of |
44 // |executionContext|. | 44 // |executionContext|. |
45 // NOTE: |task| might be silently ignored (i.e. not executed) and | 45 // NOTE: |task| might be silently ignored (i.e. not executed) and |
46 // destructed (possibly on the calling thread or on the thread of | 46 // destructed (possibly on the calling thread or on the thread of |
47 // |executionContext|) when |executionContext| is stopped or | 47 // |executionContext|) when |executionContext| is stopped or |
48 // CrossThreadHolder is destructed. | 48 // CrossThreadHolder is destructed. |
49 void postTask(std::unique_ptr<WTF::Function<void(T*, ExecutionContext*), WTF
::CrossThreadAffinity>> task) | 49 void postTask(std::unique_ptr<WTF::Function<void(T*, ExecutionContext*), WTF
::CrossThreadAffinity>> task) |
50 { | 50 { |
51 MutexLocker locker(m_mutex->mutex()); | 51 MutexLocker locker(m_mutex->mutex()); |
52 if (!m_bridge) { | 52 if (!m_bridge) { |
53 // The bridge has already disappeared. | 53 // The bridge has already disappeared. |
54 return; | 54 return; |
55 } | 55 } |
56 m_bridge->getExecutionContext()->postTask(BLINK_FROM_HERE, createCrossTh
readTask(&Bridge::runTask, wrapCrossThreadPersistent(m_bridge.get()), passed(std
::move(task)))); | 56 m_bridge->getExecutionContext()->postTask(BLINK_FROM_HERE, createCrossTh
readTask(&Bridge::runTask, wrapCrossThreadPersistent(m_bridge.get()), passed(std
::move(task)))); |
57 } | 57 } |
58 | 58 |
59 ~CrossThreadHolder() | 59 ~CrossThreadHolder() |
60 { | 60 { |
61 MutexLocker locker(m_mutex->mutex()); | 61 MutexLocker locker(m_mutex->mutex()); |
62 clearInternal(); | 62 clearInternal(); |
63 } | 63 } |
64 | 64 |
65 private: | 65 private: |
66 // Object graph: | 66 // Object graph: |
67 // +------+ +-----------------+ | 67 // +------+ +-----------------+ |
68 // T <-std::unique_ptr- |Bridge| ---------*-------------> |CrossThreadHo
lder| | 68 // T <-OwnPtr- |Bridge| ---------*-------------> |CrossThreadHolder| |
69 // | | <-CrossThreadPersistent- | | | 69 // | | <-CrossThreadPersistent- | | |
70 // +------+ +-----------------+ | 70 // +------+ +-----------------+ |
71 // | | | 71 // | | |
72 // +--RefPtr--> MutexWrapper <--RefPtr--+ | 72 // +--RefPtr--> MutexWrapper <--RefPtr--+ |
73 // The CrossThreadPersistent<T>/T* between CrossThreadHolder and Bridge | 73 // The CrossThreadPersistent<T>/T* between CrossThreadHolder and Bridge |
74 // are protected by MutexWrapper | 74 // are protected by MutexWrapper |
75 // and cleared when CrossThreadHolder::clearInternal() is called, i.e.: | 75 // and cleared when CrossThreadHolder::clearInternal() is called, i.e.: |
76 // [1] when |executionContext| is stopped, or | 76 // [1] when |executionContext| is stopped, or |
77 // [2] when CrossThreadHolder is destructed. | 77 // [2] when CrossThreadHolder is destructed. |
78 // Then Bridge is shortly garbage collected and T is destructed. | 78 // Then Bridge is shortly garbage collected and T is destructed. |
79 | 79 |
80 class MutexWrapper : public ThreadSafeRefCounted<MutexWrapper> { | 80 class MutexWrapper : public ThreadSafeRefCounted<MutexWrapper> { |
81 public: | 81 public: |
82 static PassRefPtr<MutexWrapper> create() { return adoptRef(new MutexWrap
per()); } | 82 static PassRefPtr<MutexWrapper> create() { return adoptRef(new MutexWrap
per()); } |
83 Mutex& mutex() { return m_mutex; } | 83 Mutex& mutex() { return m_mutex; } |
84 private: | 84 private: |
85 MutexWrapper() = default; | 85 MutexWrapper() = default; |
86 Mutex m_mutex; | 86 Mutex m_mutex; |
87 }; | 87 }; |
88 | 88 |
89 // All methods except for clearInternal() | 89 // All methods except for clearInternal() |
90 // must be called on |executionContext|'s thread. | 90 // must be called on |executionContext|'s thread. |
91 class Bridge | 91 class Bridge |
92 : public GarbageCollectedFinalized<Bridge> | 92 : public GarbageCollectedFinalized<Bridge> |
93 , public ActiveDOMObject { | 93 , public ActiveDOMObject { |
94 USING_GARBAGE_COLLECTED_MIXIN(Bridge); | 94 USING_GARBAGE_COLLECTED_MIXIN(Bridge); |
95 public: | 95 public: |
96 Bridge(ExecutionContext* executionContext, std::unique_ptr<T> obj, PassR
efPtr<MutexWrapper> mutex, CrossThreadHolder* holder) | 96 Bridge(ExecutionContext* executionContext, PassOwnPtr<T> obj, PassRefPtr
<MutexWrapper> mutex, CrossThreadHolder* holder) |
97 : ActiveDOMObject(executionContext) | 97 : ActiveDOMObject(executionContext) |
98 , m_obj(std::move(obj)) | 98 , m_obj(std::move(obj)) |
99 , m_mutex(mutex) | 99 , m_mutex(mutex) |
100 , m_holder(holder) | 100 , m_holder(holder) |
101 { | 101 { |
102 suspendIfNeeded(); | 102 suspendIfNeeded(); |
103 } | 103 } |
104 | 104 |
105 DEFINE_INLINE_TRACE() | 105 DEFINE_INLINE_TRACE() |
106 { | 106 { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 ASSERT(!m_holder); | 138 ASSERT(!m_holder); |
139 } | 139 } |
140 | 140 |
141 // We have to destruct |*m_obj| here because destructing |*m_obj| | 141 // We have to destruct |*m_obj| here because destructing |*m_obj| |
142 // in ~Bridge() might be too late when |executionContext| is | 142 // in ~Bridge() might be too late when |executionContext| is |
143 // stopped. | 143 // stopped. |
144 m_obj.reset(); | 144 m_obj.reset(); |
145 } | 145 } |
146 | 146 |
147 | 147 |
148 std::unique_ptr<T> m_obj; | 148 OwnPtr<T> m_obj; |
149 // All accesses to |m_holder| must be protected by |m_mutex|. | 149 // All accesses to |m_holder| must be protected by |m_mutex|. |
150 RefPtr<MutexWrapper> m_mutex; | 150 RefPtr<MutexWrapper> m_mutex; |
151 CrossThreadHolder* m_holder; | 151 CrossThreadHolder* m_holder; |
152 }; | 152 }; |
153 | 153 |
154 // Must be protected by |m_mutex|. | 154 // Must be protected by |m_mutex|. |
155 void clearInternal() | 155 void clearInternal() |
156 { | 156 { |
157 if (m_bridge) | 157 if (m_bridge) |
158 m_bridge->clearInternal(); | 158 m_bridge->clearInternal(); |
159 m_bridge.clear(); | 159 m_bridge.clear(); |
160 } | 160 } |
161 | 161 |
162 CrossThreadHolder(ExecutionContext* executionContext, std::unique_ptr<T> obj
) | 162 CrossThreadHolder(ExecutionContext* executionContext, PassOwnPtr<T> obj) |
163 : m_mutex(MutexWrapper::create()) | 163 : m_mutex(MutexWrapper::create()) |
164 , m_bridge(new Bridge(executionContext, std::move(obj), m_mutex, this)) | 164 , m_bridge(new Bridge(executionContext, std::move(obj), m_mutex, this)) |
165 { | 165 { |
166 } | 166 } |
167 | 167 |
168 RefPtr<MutexWrapper> m_mutex; | 168 RefPtr<MutexWrapper> m_mutex; |
169 // |m_bridge| is protected by |m_mutex|. | 169 // |m_bridge| is protected by |m_mutex|. |
170 // |m_bridge| is cleared before the thread that allocated |*m_bridge| | 170 // |m_bridge| is cleared before the thread that allocated |*m_bridge| |
171 // is stopped. | 171 // is stopped. |
172 CrossThreadPersistent<Bridge> m_bridge; | 172 CrossThreadPersistent<Bridge> m_bridge; |
173 }; | 173 }; |
174 | 174 |
175 } // namespace blink | 175 } // namespace blink |
176 | 176 |
177 #endif // CrossThreadHolder_h | 177 #endif // CrossThreadHolder_h |
OLD | NEW |