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

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

Issue 2342233002: Remove Fetch[Blob|FormData]ConsumerHandle (Closed)
Patch Set: rebase Created 4 years, 3 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
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/ExecutionContext.h"
10 #include "core/dom/ExecutionContextTask.h"
11 #include "public/platform/WebTraceLocation.h"
12 #include "wtf/Locker.h"
13 #include "wtf/PassRefPtr.h"
14 #include "wtf/PtrUtil.h"
15 #include "wtf/RefPtr.h"
16 #include "wtf/ThreadingPrimitives.h"
17 #include <memory>
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 std::unique_ptr<CrossThreadHolder<T>> create(ExecutionContext* execut ionContext, std::unique_ptr<T> obj)
37 {
38 ASSERT(executionContext->isContextThread());
39 return wrapUnique(new CrossThreadHolder(executionContext, std::move(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(std::unique_ptr<WTF::Function<void(T*, ExecutionContext*), WTF ::CrossThreadAffinity>> task)
50 {
51 MutexLocker locker(m_mutex->mutex());
52 if (!m_bridge) {
53 // The bridge has already disappeared.
54 return;
55 }
56 m_bridge->getExecutionContext()->postTask(BLINK_FROM_HERE, createCrossTh readTask(&Bridge::runTask, wrapCrossThreadPersistent(m_bridge.get()), passed(std ::move(task))));
57 }
58
59 ~CrossThreadHolder()
60 {
61 MutexLocker locker(m_mutex->mutex());
62 clearInternal();
63 }
64
65 private:
66 // Object graph:
67 // +------+ +-----------------+
68 // T <-unique_ptr- |Bridge| ---------*-------------> |CrossThreadHolder|
69 // | | <-CrossThreadPersistent- | |
70 // +------+ +-----------------+
71 // | |
72 // +--RefPtr--> MutexWrapper <--RefPtr--+
73 // The CrossThreadPersistent<T>/T* 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 USING_GARBAGE_COLLECTED_MIXIN(Bridge);
95 public:
96 Bridge(ExecutionContext* executionContext, std::unique_ptr<T> obj, PassR efPtr<MutexWrapper> mutex, CrossThreadHolder* holder)
97 : ActiveDOMObject(executionContext)
98 , m_obj(std::move(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(std::unique_ptr<WTF::Function<void(T*, ExecutionContext*), WTF::CrossThreadAffinity>> task)
123 {
124 ASSERT(getExecutionContext()->isContextThread());
125 if (m_obj)
126 (*task)(m_obj.get(), getExecutionContext());
127 }
128
129 private:
130 // ActiveDOMObject
131 void stop() override
132 {
133 ASSERT(getExecutionContext()->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.reset();
145 }
146
147
148 std::unique_ptr<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, std::unique_ptr<T> obj )
163 : m_mutex(MutexWrapper::create())
164 , m_bridge(new Bridge(executionContext, std::move(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

Powered by Google App Engine
This is Rietveld 408576698