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

Side by Side Diff: Source/modules/fetch/CrossThreadHolder.h

Issue 1281273004: Move CrossThreadHolder to CrossThreadHolder.h (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: final Created 5 years, 4 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 | Source/modules/fetch/FetchBlobDataConsumerHandle.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #ifndef CrossThreadHolder_h
6 #define CrossThreadHolder_h
7
8 #include "core/dom/ActiveDOMObject.h"
9 #include "core/dom/CrossThreadTask.h"
10 #include "core/dom/ExecutionContext.h"
11 #include "public/platform/WebTraceLocation.h"
12 #include "wtf/Locker.h"
13 #include "wtf/OwnPtr.h"
14 #include "wtf/PassOwnPtr.h"
15 #include "wtf/PassRefPtr.h"
16 #include "wtf/RefPtr.h"
17 #include "wtf/ThreadingPrimitives.h"
18
19 namespace blink {
20
21 // CrossThreadHolder<T> provides cross-thread access to |obj| of class T
22 // bound to the thread of |executionContext| where |obj| is created.
23 // - CrossThreadHolder<T> can be passed across threads.
24 // - |obj|'s methods are called on the thread of |executionContext|
25 // via CrossThreadHolder<T>::postTask().
26 // - |obj| is destructed on the thread of |executionContext|
27 // when |executionContext| is stopped or
28 // CrossThreadHolder is destructed (earlier of them).
29 // Note: |obj|'s destruction can be slightly after CrossThreadHolder.
30 template<typename T>
31 class CrossThreadHolder final {
32 public:
33 // Must be called on the thread where |obj| is created
34 // (== the thread of |executionContext|).
35 // The current thread must be attached to Oilpan.
36 static PassOwnPtr<CrossThreadHolder<T>> create(ExecutionContext* executionCo ntext, PassOwnPtr<T> obj)
37 {
38 ASSERT(executionContext->isContextThread());
39 return adoptPtr(new CrossThreadHolder(executionContext, obj));
40 }
41
42 // Can be called from any thread.
43 // Executes |task| with |obj| and |executionContext| on the thread of
44 // |executionContext|.
45 // NOTE: |task| might be silently ignored (i.e. not executed) and
46 // destructed (possibly on the calling thread or on the thread of
47 // |executionContext|) when |executionContext| is stopped or
48 // CrossThreadHolder is destructed.
49 void postTask(PassOwnPtr<WTF::Function<void(T*, ExecutionContext*)>> task)
50 {
51 MutexLocker locker(m_mutex->mutex());
52 if (!m_bridge) {
53 // The bridge has already disappeared.
54 return;
55 }
56 m_bridge->executionContext()->postTask(FROM_HERE, createCrossThreadTask( &Bridge::runTask, m_bridge.get(), task));
57 }
58
59 ~CrossThreadHolder()
60 {
61 MutexLocker locker(m_mutex->mutex());
62 clearInternal();
63 }
64
65 private:
66 // Object graph:
67 // +------+ +-----------------+
68 // T <-OwnPtr- |Bridge| ---------RawPtr--------> |CrossThreadHolder|
69 // | | <-CrossThreadPersistent- | |
70 // +------+ +-----------------+
71 // | |
72 // +--RefPtr--> MutexWrapper <--RefPtr--+
73 // The CrossThreadPersistent/RawPtr between CrossThreadHolder and Bridge
74 // are protected by MutexWrapper
75 // and cleared when CrossThreadHolder::clearInternal() is called, i.e.:
76 // [1] when |executionContext| is stopped, or
77 // [2] when CrossThreadHolder is destructed.
78 // Then Bridge is shortly garbage collected and T is destructed.
79
80 class MutexWrapper : public ThreadSafeRefCounted<MutexWrapper> {
81 public:
82 static PassRefPtr<MutexWrapper> create() { return adoptRef(new MutexWrap per()); }
83 Mutex& mutex() { return m_mutex; }
84 private:
85 MutexWrapper() = default;
86 Mutex m_mutex;
87 };
88
89 // All methods except for clearInternal()
90 // must be called on |executionContext|'s thread.
91 class Bridge
92 : public GarbageCollectedFinalized<Bridge>
93 , public ActiveDOMObject {
94 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(Bridge);
95 public:
96 Bridge(ExecutionContext* executionContext, PassOwnPtr<T> obj, PassRefPtr <MutexWrapper> mutex, CrossThreadHolder* holder)
97 : ActiveDOMObject(executionContext)
98 , m_obj(obj)
99 , m_mutex(mutex)
100 , m_holder(holder)
101 {
102 suspendIfNeeded();
103 }
104
105 DEFINE_INLINE_TRACE()
106 {
107 ActiveDOMObject::trace(visitor);
108 }
109
110 T* getObject() const { return m_obj.get(); }
111
112 // Must be protected by |m_mutex|.
113 // Is called from CrossThreadHolder::clearInternal() and
114 // can be called on any thread.
115 void clearInternal()
116 {
117 // We don't clear |m_obj| here to destruct |m_obj| on the thread
118 // of |executionContext|.
119 m_holder = nullptr;
120 }
121
122 void runTask(PassOwnPtr<WTF::Function<void(T*, ExecutionContext*)>> task )
123 {
124 ASSERT(executionContext()->isContextThread());
125 if (m_obj)
126 (*task)(m_obj.get(), executionContext());
127 }
128
129 private:
130 // ActiveDOMObject
131 void stop() override
132 {
133 ASSERT(executionContext()->isContextThread());
134 {
135 MutexLocker locker(m_mutex->mutex());
136 if (m_holder)
137 m_holder->clearInternal();
138 ASSERT(!m_holder);
139 }
140
141 // We have to destruct |*m_obj| here because destructing |*m_obj|
142 // in ~Bridge() might be too late when |executionContext| is
143 // stopped.
144 m_obj.clear();
145 }
146
147
148 OwnPtr<T> m_obj;
149 // All accesses to |m_holder| must be protected by |m_mutex|.
150 RefPtr<MutexWrapper> m_mutex;
151 CrossThreadHolder* m_holder;
152 };
153
154 // Must be protected by |m_mutex|.
155 void clearInternal()
156 {
157 if (m_bridge)
158 m_bridge->clearInternal();
159 m_bridge.clear();
160 }
161
162 CrossThreadHolder(ExecutionContext* executionContext, PassOwnPtr<T> obj)
163 : m_mutex(MutexWrapper::create())
164 , m_bridge(new Bridge(executionContext, obj, m_mutex, this))
165 {
166 }
167
168 RefPtr<MutexWrapper> m_mutex;
169 // |m_bridge| is protected by |m_mutex|.
170 // |m_bridge| is cleared before the thread that allocated |*m_bridge|
171 // is stopped.
172 CrossThreadPersistent<Bridge> m_bridge;
173 };
174
175 } // namespace blink
176
177 #endif // CrossThreadHolder_h
OLDNEW
« no previous file with comments | « no previous file | Source/modules/fetch/FetchBlobDataConsumerHandle.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698