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

Side by Side Diff: Source/modules/fetch/CompositeDataConsumerHandle.cpp

Issue 1162043007: Introduce CompositeDataConsumerHandle. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 6 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 #include "config.h"
6 #include "modules/fetch/CompositeDataConsumerHandle.h"
7
8 #include "platform/Task.h"
9 #include "platform/ThreadSafeFunctional.h"
10 #include "public/platform/Platform.h"
11 #include "public/platform/WebThread.h"
12 #include "public/platform/WebTraceLocation.h"
13 #include "wtf/Locker.h"
14 #include "wtf/ThreadSafeRefCounted.h"
15 #include "wtf/ThreadingPrimitives.h"
16
17 namespace blink {
18
19 using Result = WebDataConsumerHandle::Result;
20
21 namespace {
22
23 class RepeatingReader final : public WebDataConsumerHandle::Reader {
24 public:
25 explicit RepeatingReader(Result r) : m_result(r) { }
26 Result read(void*, size_t, WebDataConsumerHandle::Flags, size_t *readSize) o verride
27 {
28 *readSize = 0;
29 return m_result;
30 }
31 Result beginRead(const void**, WebDataConsumerHandle::Flags, size_t *availab le) override
32 {
33 *available = 0;
34 return m_result;
35 }
36 Result endRead(size_t) override
37 {
38 return WebDataConsumerHandle::UnexpectedError;
39 }
40
41 private:
42 const Result m_result;
43 };
44
45 class WaitingHandle final : public WebDataConsumerHandle {
46 private:
47 Reader* obtainReaderInternal(Client*) override { return new RepeatingReader( ShouldWait); }
48 };
49
50 class DoneHandle final : public WebDataConsumerHandle {
51 private:
52 Reader* obtainReaderInternal(Client*) override { return new RepeatingReader( Done); }
53 };
54
55 } // namespace
56
57 class CompositeDataConsumerHandle::ReaderImpl final : public WebDataConsumerHand le::Reader {
58 public:
59 explicit ReaderImpl(PassRefPtr<Context>);
60 ~ReaderImpl() override;
61 Result read(void* data, size_t /* size */, Flags, size_t* readSize) override ;
62 Result beginRead(const void** buffer, Flags, size_t* available) override;
63 Result endRead(size_t readSize) override;
64
65 private:
66 RefPtr<Context> m_context;
67 };
68
69 class CompositeDataConsumerHandle::Context : public ThreadSafeRefCounted<Context > {
70 public:
71 using Token = unsigned;
72 static PassRefPtr<Context> create(PassOwnPtr<WebDataConsumerHandle> handle) { return adoptRef(new Context(handle)); }
73 PassOwnPtr<ReaderImpl> obtainReader(Client* client)
74 {
75 MutexLocker locker(m_mutex);
76 ASSERT(!m_readerThread);
77 ASSERT(!m_reader);
78 ASSERT(!m_client);
79 ++m_token;
80 m_client = client;
81 m_readerThread = Platform::current()->currentThread();
82 m_reader = m_handle->obtainReader(m_client);
83 return adoptPtr(new ReaderImpl(this));
84 }
85 void detachReader()
86 {
hiroshige 2015/06/10 06:55:25 Add ASSERT(!m_isInTwoPhaseRead) and ASSERT(!m_isUp
yhirano 2015/06/10 11:02:43 Done.
87 MutexLocker locker(m_mutex);
88 ASSERT(m_readerThread);
89 ASSERT(m_readerThread->isCurrentThread());
90 ASSERT(m_reader);
hiroshige 2015/06/10 06:55:26 We assume obtainReader() returns non-null pointer
yhirano 2015/06/10 11:02:44 The implementation in WebDataConsumerHandle is not
91 ++m_token;
92 m_reader = nullptr;
93 m_readerThread = nullptr;
94 m_client = nullptr;
95 }
96 void update(PassOwnPtr<WebDataConsumerHandle> handle)
97 {
98 MutexLocker locker(m_mutex);
99 m_handle = handle;
100 if (!m_readerThread) {
101 // There is no reader.
102 return;
103 }
104 ++m_token;
105 updateReaderNoLock(m_token);
106 }
107
108 Result read(void* data, size_t size, Flags flags, size_t* readSize)
109 {
110 ASSERT(m_readerThread && m_readerThread->isCurrentThread());
111 return m_reader->read(data, size, flags, readSize);
112 }
113 Result beginRead(const void** buffer, Flags flags, size_t* available)
114 {
115 ASSERT(m_readerThread && m_readerThread->isCurrentThread());
116 ASSERT(!m_isInTwoPhaseRead);
117 m_isInTwoPhaseRead = true;
118 return m_reader->beginRead(buffer, flags, available);
119 }
120 Result endRead(size_t readSize)
121 {
122 ASSERT(m_readerThread && m_readerThread->isCurrentThread());
123 ASSERT(m_isInTwoPhaseRead);
124 Result r = m_reader->endRead(readSize);
125 m_isInTwoPhaseRead = false;
126 if (m_isUpdateWaitingForEndRead) {
hiroshige 2015/06/10 06:55:25 We need MutexLocker(m_mutex) here, because we shou
yhirano 2015/06/10 11:02:44 Done.
127 m_reader = nullptr;
128 m_reader = m_handle->obtainReader(m_client);
129 m_isUpdateWaitingForEndRead = false;
130 }
131 return r;
132 }
133
134 private:
135 explicit Context(PassOwnPtr<WebDataConsumerHandle> handle)
136 : m_handle(handle)
137 , m_readerThread(nullptr)
138 , m_client(nullptr)
139 , m_token(0)
140 , m_isUpdateWaitingForEndRead(false)
141 , m_isInTwoPhaseRead(false)
142 {
143 }
144 void updateReader(Token token)
145 {
146 MutexLocker locker(m_mutex);
147 updateReaderNoLock(token);
148 }
149 void updateReaderNoLock(Token token)
150 {
151 if (token != m_token) {
152 // This request is not fresh. Ignore it.
153 return;
154 }
155 ASSERT(m_readerThread);
156 ASSERT(m_reader);
157 if (m_readerThread->isCurrentThread()) {
158 if (m_isInTwoPhaseRead) {
159 // We are waiting for the two-phase read completion.
160 m_isUpdateWaitingForEndRead = true;
161 return;
162 }
163 // Unregister the old one, then register the new one.
164 m_reader = nullptr;
165 m_reader = m_handle->obtainReader(m_client);
hiroshige 2015/06/10 06:55:26 Should we post a task for didGetReadable() here be
yhirano 2015/06/10 11:02:43 Done.
166 return;
167 }
168 ++m_token;
169 m_readerThread->postTask(FROM_HERE, new Task(threadSafeBind(&Context::up dateReader, this, m_token)));
170 }
171
172 OwnPtr<Reader> m_reader;
173 OwnPtr<WebDataConsumerHandle> m_handle;
174 // Note: Holding a WebThread raw pointer is not generally safe, but we can
175 // do that in this case because:
176 // 1. Destructing a ReaderImpl when the bound thread ends is a user's
177 // responsibility.
178 // 2. |m_readerThread| will never be used after the associated reader is
179 // detached.
180 WebThread* m_readerThread;
181 Client* m_client;
182 Token m_token;
183 // These boolean values are bound to the reader thread.
184 bool m_isUpdateWaitingForEndRead;
185 bool m_isInTwoPhaseRead;
186 Mutex m_mutex;
187 };
188
189 CompositeDataConsumerHandle::ReaderImpl::ReaderImpl(PassRefPtr<Context> context) : m_context(context) { }
190
191 CompositeDataConsumerHandle::ReaderImpl::~ReaderImpl()
192 {
193 m_context->detachReader();
194 }
195
196 Result CompositeDataConsumerHandle::ReaderImpl::read(void* data, size_t size, Fl ags flags, size_t* readSize)
197 {
198 return m_context->read(data, size, flags, readSize);
199 }
200
201 Result CompositeDataConsumerHandle::ReaderImpl::beginRead(const void** buffer, F lags flags, size_t* available)
202 {
203 return m_context->beginRead(buffer, flags, available);
204 }
205
206 Result CompositeDataConsumerHandle::ReaderImpl::endRead(size_t readSize)
207 {
208 return m_context->endRead(readSize);
209 }
210
211 CompositeDataConsumerHandle::CompositeDataConsumerHandle(PassOwnPtr<WebDataConsu merHandle> handle)
212 : m_context(Context::create(handle)) { }
213
214 CompositeDataConsumerHandle::~CompositeDataConsumerHandle() { }
215
216 WebDataConsumerHandle::Reader* CompositeDataConsumerHandle::obtainReaderInternal (Client* client)
217 {
218 return m_context->obtainReader(client).leakPtr();
219 }
220
221 void CompositeDataConsumerHandle::update(PassOwnPtr<WebDataConsumerHandle> handl e)
222 {
223 ASSERT(handle);
224 m_context->update(handle);
225 }
226
227 PassOwnPtr<WebDataConsumerHandle> CompositeDataConsumerHandle::createWaitingHand le()
228 {
229 return adoptPtr(new WaitingHandle);
230 }
231
232 PassOwnPtr<WebDataConsumerHandle> CompositeDataConsumerHandle::createDoneHandle( )
233 {
234 return adoptPtr(new DoneHandle);
235 }
236
237 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698