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

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 Reader* reader() { return m_reader.get(); }
74 PassOwnPtr<ReaderImpl> obtainReader(Client* client)
75 {
76 MutexLocker locker(m_mutex);
77 ++m_token;
hiroshige 2015/06/09 05:37:16 Assert that there is no reader (e.g. |!m_reader|).
yhirano 2015/06/09 06:30:52 Done.
78 m_client = client;
79 m_readerThread = Platform::current()->currentThread();
80 m_reader = m_handle->obtainReader(m_client);
81 return adoptPtr(new ReaderImpl(this));
82 }
83 void detachReader()
84 {
85 MutexLocker locker(m_mutex);
hiroshige 2015/06/09 05:37:15 Assert that m_readerThread is the current thread.
yhirano 2015/06/09 06:30:52 Done.
86 ++m_token;
87 m_reader = nullptr;
88 m_readerThread = nullptr;
89 m_client = nullptr;
90 }
91 void update(PassOwnPtr<WebDataConsumerHandle> handle)
92 {
93 MutexLocker locker(m_mutex);
94 m_handle = handle;
95 if (!m_readerThread) {
96 // There is no reader.
97 return;
98 }
99 ++m_token;
100 updateReaderNoLock(m_token);
101 }
102
103 private:
104 explicit Context(PassOwnPtr<WebDataConsumerHandle> handle)
105 : m_handle(handle)
106 , m_readerThread(nullptr)
107 , m_client(nullptr)
108 , m_token(0)
109 {
110 }
111 void updateReader(Token token)
112 {
113 MutexLocker locker(m_mutex);
114 updateReaderNoLock(token);
115 }
116 void updateReaderNoLock(Token token)
117 {
118 if (token != m_token) {
119 // This request is not fresh. Ignore it.
120 return;
121 }
122 ASSERT(m_readerThread);
123 ASSERT(m_reader);
124 if (m_readerThread->isCurrentThread()) {
125 // Unregister the old one, then register the new one.
126 m_reader = nullptr;
127 m_reader = m_handle->obtainReader(m_client);
128 return;
129 }
130 ++m_token;
131 m_readerThread->postTask(FROM_HERE, new Task(threadSafeBind(&Context::up dateReader, this, m_token)));
hiroshige 2015/06/09 05:37:15 |this| might destructed before this task is execut
hiroshige 2015/06/09 05:47:10 Correction: The current code is fine. CrossThreadC
132 }
133
134 OwnPtr<Reader> m_reader;
135 OwnPtr<WebDataConsumerHandle> m_handle;
136 // Note: Holding a WebThread raw pointer is not generally safe, but we can
137 // do that in this case because:
138 // 1. Destructing a ReaderImpl when the bound thread ends is a user's
139 // responsibility.
140 // 2. |m_readerThread| will never be used after the associated reader is
141 // detached.
142 WebThread* m_readerThread;
143 Client* m_client;
144 Token m_token;
145 Mutex m_mutex;
146 };
147
148 CompositeDataConsumerHandle::ReaderImpl::ReaderImpl(PassRefPtr<Context> context) : m_context(context) { }
149
150 CompositeDataConsumerHandle::ReaderImpl::~ReaderImpl()
151 {
152 m_context->detachReader();
153 }
154
155 Result CompositeDataConsumerHandle::ReaderImpl::read(void* data, size_t size, Fl ags flags, size_t* readSize)
156 {
157 return m_context->reader()->read(data, size, flags, readSize);
158 }
159
160 Result CompositeDataConsumerHandle::ReaderImpl::beginRead(const void** buffer, F lags flags, size_t* available)
161 {
162 return m_context->reader()->beginRead(buffer, flags, available);
163 }
164
165 Result CompositeDataConsumerHandle::ReaderImpl::endRead(size_t readSize)
166 {
167 return m_context->reader()->endRead(readSize);
168 }
169
170 CompositeDataConsumerHandle::CompositeDataConsumerHandle(PassOwnPtr<WebDataConsu merHandle> handle)
171 : m_context(Context::create(handle)) { }
172
173 CompositeDataConsumerHandle::~CompositeDataConsumerHandle() { }
174
175 WebDataConsumerHandle::Reader* CompositeDataConsumerHandle::obtainReaderInternal (Client* client)
176 {
177 return m_context->obtainReader(client).leakPtr();
178 }
179
180 void CompositeDataConsumerHandle::update(PassOwnPtr<WebDataConsumerHandle> handl e)
181 {
182 m_context->update(handle);
183 }
184
185 PassOwnPtr<WebDataConsumerHandle> CompositeDataConsumerHandle::createWaitingHand le()
186 {
187 return adoptPtr(new WaitingHandle);
188 }
189
190 PassOwnPtr<WebDataConsumerHandle> CompositeDataConsumerHandle::createDoneHandle( )
191 {
192 return adoptPtr(new DoneHandle);
193 }
194
195 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698