Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 WaitingHandle final : public WebDataConsumerHandle { | |
| 24 public: | |
| 25 Result read(void*, size_t, Flags, size_t *readSize) override | |
| 26 { | |
| 27 *readSize = 0; | |
| 28 return ShouldWait; | |
| 29 } | |
| 30 Result beginRead(const void**, Flags, size_t *available) override | |
| 31 { | |
| 32 *available = 0; | |
| 33 return ShouldWait; | |
| 34 } | |
| 35 Result endRead(size_t) override | |
| 36 { | |
| 37 return UnexpectedError; | |
| 38 } | |
| 39 void registerClient(Client*) override { } | |
| 40 void unregisterClient() override { } | |
| 41 }; | |
| 42 | |
| 43 class DoneHandle final : public WebDataConsumerHandle { | |
| 44 public: | |
| 45 Result read(void*, size_t, Flags, size_t *readSize) override | |
| 46 { | |
| 47 *readSize = 0; | |
| 48 return Done; | |
| 49 } | |
| 50 Result beginRead(const void**, Flags, size_t *available) override | |
| 51 { | |
| 52 *available = 0; | |
| 53 return Done; | |
| 54 } | |
| 55 Result endRead(size_t) override | |
| 56 { | |
| 57 return UnexpectedError; | |
| 58 } | |
| 59 void registerClient(Client*) override { } | |
| 60 void unregisterClient() override { } | |
| 61 }; | |
| 62 | |
| 63 } // namespace | |
| 64 | |
| 65 class CompositeDataConsumerHandle::MutexHolder : public ThreadSafeRefCounted<Mut exHolder> { | |
| 66 public: | |
| 67 static PassRefPtr<MutexHolder> create() { return adoptRef(new MutexHolder); } | |
| 68 Mutex& get() { return m_mutex; } | |
| 69 bool isActive() const { return m_isActive; } | |
| 70 void stop() { m_isActive = false; } | |
| 71 | |
| 72 private: | |
| 73 MutexHolder() : m_isActive(true) { } | |
| 74 Mutex m_mutex; | |
| 75 bool m_isActive; | |
| 76 }; | |
| 77 | |
| 78 CompositeDataConsumerHandle::CompositeDataConsumerHandle(PassOwnPtr<WebDataConsu merHandle> handle) | |
| 79 : m_handle(handle), m_mutex(MutexHolder::create()), m_client(nullptr), m_cli entThread(nullptr) { } | |
| 80 | |
| 81 CompositeDataConsumerHandle::~CompositeDataConsumerHandle() | |
| 82 { | |
| 83 // We need this lock in order to avoid race with |updateOnTheRightThread|. | |
| 84 MutexLocker locker(m_mutex->get()); | |
| 85 m_mutex->stop(); | |
| 86 } | |
| 87 | |
| 88 Result CompositeDataConsumerHandle::read(void* data, size_t size, Flags flags, s ize_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.
| |
| 89 { | |
| 90 MutexLocker locker(m_mutex->get()); | |
| 91 return m_handle->read(data, size, flags, readSize); | |
| 92 } | |
| 93 | |
| 94 Result CompositeDataConsumerHandle::beginRead(const void** buffer, Flags flags, size_t* available) | |
| 95 { | |
| 96 MutexLocker locker(m_mutex->get()); | |
| 97 return m_handle->beginRead(buffer, flags, available); | |
| 98 } | |
| 99 | |
| 100 Result CompositeDataConsumerHandle::endRead(size_t readSize) | |
| 101 { | |
| 102 MutexLocker locker(m_mutex->get()); | |
| 103 return m_handle->endRead(readSize); | |
| 104 } | |
| 105 | |
| 106 void CompositeDataConsumerHandle::registerClient(Client* client) | |
| 107 { | |
| 108 MutexLocker locker(m_mutex->get()); | |
| 109 m_client = client; | |
| 110 m_clientThread = Platform::current()->currentThread(); | |
| 111 ASSERT(m_clientThread); | |
| 112 m_handle->registerClient(client); | |
| 113 } | |
| 114 | |
| 115 void CompositeDataConsumerHandle::unregisterClient() | |
| 116 { | |
| 117 MutexLocker locker(m_mutex->get()); | |
| 118 m_client = nullptr; | |
| 119 m_clientThread = nullptr; | |
| 120 m_handle->unregisterClient(); | |
| 121 } | |
| 122 | |
| 123 void CompositeDataConsumerHandle::update(PassOwnPtr<WebDataConsumerHandle> handl e) | |
|
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
| |
| 124 { | |
| 125 MutexLocker locker(m_mutex->get()); | |
| 126 updateInternal(handle); | |
| 127 } | |
| 128 | |
| 129 void CompositeDataConsumerHandle::updateInternal(PassOwnPtr<WebDataConsumerHandl e> 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
| |
| 130 { | |
| 131 if (!m_client) { | |
| 132 m_handle = handle; | |
| 133 return; | |
| 134 } | |
| 135 // We need to transfer the client from the old handle to the new handle | |
| 136 // on the thread on which the client is registered. | |
| 137 if (m_clientThread == Platform::current()->currentThread()) { | |
| 138 // ... and it is the curren thread. | |
|
hiroshige
2015/06/03 08:45:05
nit: current.
yhirano
2015/06/04 05:43:02
Done.
| |
| 139 m_handle->unregisterClient(); | |
| 140 m_handle = handle; | |
| 141 m_handle->registerClient(m_client); | |
| 142 return; | |
| 143 } | |
| 144 // Now we need to post a task to the right thread. | |
| 145 m_clientThread->postTask(FROM_HERE, new Task(threadSafeBind( | |
| 146 &updateOnTheRightThread, AllowCrossThreadAccess(this), handle, m_mutex)) ); | |
| 147 } | |
| 148 | |
| 149 void CompositeDataConsumerHandle::updateOnTheRightThread( | |
| 150 CompositeDataConsumerHandle* that, PassOwnPtr<WebDataConsumerHandle> handle, PassRefPtr<MutexHolder> mutex) | |
| 151 { | |
| 152 MutexLocker locker(mutex->get()); | |
| 153 if (!mutex->isActive()) { | |
| 154 // The handle was already deleted. Do nothing. | |
| 155 return; | |
| 156 } | |
| 157 // |that| is protected by the lock (see the destructor). | |
| 158 that->updateInternal(handle); | |
| 159 } | |
| 160 | |
| 161 PassOwnPtr<WebDataConsumerHandle> CompositeDataConsumerHandle::createWaitingHand le() | |
| 162 { | |
| 163 return adoptPtr(new WaitingHandle); | |
| 164 } | |
| 165 | |
| 166 PassOwnPtr<WebDataConsumerHandle> CompositeDataConsumerHandle::createDoneHandle( ) | |
| 167 { | |
| 168 return adoptPtr(new DoneHandle); | |
| 169 } | |
| 170 | |
| 171 } // namespace blink | |
| OLD | NEW |