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

Unified 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, 7 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 side-by-side diff with in-line comments
Download patch
Index: Source/modules/fetch/CompositeDataConsumerHandle.cpp
diff --git a/Source/modules/fetch/CompositeDataConsumerHandle.cpp b/Source/modules/fetch/CompositeDataConsumerHandle.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f34e002df689590acbd33ec4ccc2042a250b3d8b
--- /dev/null
+++ b/Source/modules/fetch/CompositeDataConsumerHandle.cpp
@@ -0,0 +1,171 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "modules/fetch/CompositeDataConsumerHandle.h"
+
+#include "platform/Task.h"
+#include "platform/ThreadSafeFunctional.h"
+#include "public/platform/Platform.h"
+#include "public/platform/WebThread.h"
+#include "public/platform/WebTraceLocation.h"
+#include "wtf/Locker.h"
+#include "wtf/ThreadSafeRefCounted.h"
+#include "wtf/ThreadingPrimitives.h"
+
+namespace blink {
+
+using Result = WebDataConsumerHandle::Result;
+
+namespace {
+
+class WaitingHandle final : public WebDataConsumerHandle {
+public:
+ Result read(void*, size_t, Flags, size_t *readSize) override
+ {
+ *readSize = 0;
+ return ShouldWait;
+ }
+ Result beginRead(const void**, Flags, size_t *available) override
+ {
+ *available = 0;
+ return ShouldWait;
+ }
+ Result endRead(size_t) override
+ {
+ return UnexpectedError;
+ }
+ void registerClient(Client*) override { }
+ void unregisterClient() override { }
+};
+
+class DoneHandle final : public WebDataConsumerHandle {
+public:
+ Result read(void*, size_t, Flags, size_t *readSize) override
+ {
+ *readSize = 0;
+ return Done;
+ }
+ Result beginRead(const void**, Flags, size_t *available) override
+ {
+ *available = 0;
+ return Done;
+ }
+ Result endRead(size_t) override
+ {
+ return UnexpectedError;
+ }
+ void registerClient(Client*) override { }
+ void unregisterClient() override { }
+};
+
+} // namespace
+
+class CompositeDataConsumerHandle::MutexHolder : public ThreadSafeRefCounted<MutexHolder> {
+public:
+ static PassRefPtr<MutexHolder> create() { return adoptRef(new MutexHolder); }
+ Mutex& get() { return m_mutex; }
+ bool isActive() const { return m_isActive; }
+ void stop() { m_isActive = false; }
+
+private:
+ MutexHolder() : m_isActive(true) { }
+ Mutex m_mutex;
+ bool m_isActive;
+};
+
+CompositeDataConsumerHandle::CompositeDataConsumerHandle(PassOwnPtr<WebDataConsumerHandle> handle)
+ : m_handle(handle), m_mutex(MutexHolder::create()), m_client(nullptr), m_clientThread(nullptr) { }
+
+CompositeDataConsumerHandle::~CompositeDataConsumerHandle()
+{
+ // We need this lock in order to avoid race with |updateOnTheRightThread|.
+ MutexLocker locker(m_mutex->get());
+ m_mutex->stop();
+}
+
+Result CompositeDataConsumerHandle::read(void* data, size_t size, Flags flags, size_t* readSize)
hiroshige 2015/06/03 08:45:05 How about adding ASSERT(!m_client || m_clientThrea
yhirano 2015/06/04 05:43:02 Done.
+{
+ MutexLocker locker(m_mutex->get());
+ return m_handle->read(data, size, flags, readSize);
+}
+
+Result CompositeDataConsumerHandle::beginRead(const void** buffer, Flags flags, size_t* available)
+{
+ MutexLocker locker(m_mutex->get());
+ return m_handle->beginRead(buffer, flags, available);
+}
+
+Result CompositeDataConsumerHandle::endRead(size_t readSize)
+{
+ MutexLocker locker(m_mutex->get());
+ return m_handle->endRead(readSize);
+}
+
+void CompositeDataConsumerHandle::registerClient(Client* client)
+{
+ MutexLocker locker(m_mutex->get());
+ m_client = client;
+ m_clientThread = Platform::current()->currentThread();
+ ASSERT(m_clientThread);
+ m_handle->registerClient(client);
+}
+
+void CompositeDataConsumerHandle::unregisterClient()
+{
+ MutexLocker locker(m_mutex->get());
+ m_client = nullptr;
+ m_clientThread = nullptr;
+ m_handle->unregisterClient();
+}
+
+void CompositeDataConsumerHandle::update(PassOwnPtr<WebDataConsumerHandle> handle)
hiroshige 2015/06/03 10:35:56 Multiple calls to update() might be executed out-o
yhirano 2015/06/04 05:43:02 You're right, thanks. I fixed the problem by intro
+{
+ MutexLocker locker(m_mutex->get());
+ updateInternal(handle);
+}
+
+void CompositeDataConsumerHandle::updateInternal(PassOwnPtr<WebDataConsumerHandle> handle)
hiroshige 2015/06/03 08:45:05 I think |handle| shouldn't have any client here, r
yhirano 2015/06/04 05:43:02 Yes. Added a comment on the header. I cannot put a
+{
+ if (!m_client) {
+ m_handle = handle;
+ return;
+ }
+ // We need to transfer the client from the old handle to the new handle
+ // on the thread on which the client is registered.
+ if (m_clientThread == Platform::current()->currentThread()) {
+ // ... and it is the curren thread.
hiroshige 2015/06/03 08:45:05 nit: current.
yhirano 2015/06/04 05:43:02 Done.
+ m_handle->unregisterClient();
+ m_handle = handle;
+ m_handle->registerClient(m_client);
+ return;
+ }
+ // Now we need to post a task to the right thread.
+ m_clientThread->postTask(FROM_HERE, new Task(threadSafeBind(
+ &updateOnTheRightThread, AllowCrossThreadAccess(this), handle, m_mutex)));
+}
+
+void CompositeDataConsumerHandle::updateOnTheRightThread(
+ CompositeDataConsumerHandle* that, PassOwnPtr<WebDataConsumerHandle> handle, PassRefPtr<MutexHolder> mutex)
+{
+ MutexLocker locker(mutex->get());
+ if (!mutex->isActive()) {
+ // The handle was already deleted. Do nothing.
+ return;
+ }
+ // |that| is protected by the lock (see the destructor).
+ that->updateInternal(handle);
+}
+
+PassOwnPtr<WebDataConsumerHandle> CompositeDataConsumerHandle::createWaitingHandle()
+{
+ return adoptPtr(new WaitingHandle);
+}
+
+PassOwnPtr<WebDataConsumerHandle> CompositeDataConsumerHandle::createDoneHandle()
+{
+ return adoptPtr(new DoneHandle);
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698