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

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

Powered by Google App Engine
This is Rietveld 408576698