| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "modules/fetch/CompositeDataConsumerHandle.h" | 5 #include "modules/fetch/CompositeDataConsumerHandle.h" |
| 6 | 6 |
| 7 #include "platform/CrossThreadFunctional.h" | 7 #include "platform/CrossThreadFunctional.h" |
| 8 #include "public/platform/Platform.h" | 8 #include "public/platform/Platform.h" |
| 9 #include "public/platform/WebTaskRunner.h" | 9 #include "public/platform/WebTaskRunner.h" |
| 10 #include "public/platform/WebThread.h" | 10 #include "public/platform/WebThread.h" |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 private: | 30 private: |
| 31 RefPtr<Context> m_context; | 31 RefPtr<Context> m_context; |
| 32 }; | 32 }; |
| 33 | 33 |
| 34 class CompositeDataConsumerHandle::Context final : public ThreadSafeRefCounted<C
ontext> { | 34 class CompositeDataConsumerHandle::Context final : public ThreadSafeRefCounted<C
ontext> { |
| 35 public: | 35 public: |
| 36 using Token = unsigned; | 36 using Token = unsigned; |
| 37 static PassRefPtr<Context> create(std::unique_ptr<WebDataConsumerHandle> han
dle) { return adoptRef(new Context(std::move(handle))); } | 37 static PassRefPtr<Context> create(std::unique_ptr<WebDataConsumerHandle> han
dle) { return adoptRef(new Context(std::move(handle))); } |
| 38 ~Context() | 38 ~Context() |
| 39 { | 39 { |
| 40 DCHECK(!m_readerThread); | |
| 41 DCHECK(!m_reader); | 40 DCHECK(!m_reader); |
| 42 DCHECK(!m_client); | 41 DCHECK(!m_client); |
| 43 } | 42 } |
| 44 std::unique_ptr<ReaderImpl> obtainReader(Client* client) | 43 std::unique_ptr<ReaderImpl> obtainReader(Client* client) |
| 45 { | 44 { |
| 46 MutexLocker locker(m_mutex); | 45 MutexLocker locker(m_mutex); |
| 47 DCHECK(!m_readerThread); | 46 DCHECK(!m_readerTaskRunner); |
| 48 DCHECK(!m_reader); | 47 DCHECK(!m_reader); |
| 49 DCHECK(!m_client); | 48 DCHECK(!m_client); |
| 50 ++m_token; | 49 ++m_token; |
| 51 m_client = client; | 50 m_client = client; |
| 52 m_readerThread = Platform::current()->currentThread(); | 51 if (client) |
| 52 m_readerTaskRunner = client->getTaskRunner()->clone(); |
| 53 else |
| 54 m_readerTaskRunner = Platform::current()->currentThread()->getWebTas
kRunner()->clone(); |
| 53 m_reader = m_handle->obtainReader(m_client); | 55 m_reader = m_handle->obtainReader(m_client); |
| 54 return wrapUnique(new ReaderImpl(this)); | 56 return wrapUnique(new ReaderImpl(this)); |
| 55 } | 57 } |
| 56 void detachReader() | 58 void detachReader() |
| 57 { | 59 { |
| 58 MutexLocker locker(m_mutex); | 60 MutexLocker locker(m_mutex); |
| 59 DCHECK(m_readerThread); | 61 DCHECK(m_readerTaskRunner); |
| 60 DCHECK(m_readerThread->isCurrentThread()); | 62 DCHECK(m_readerTaskRunner->runsTasksOnCurrentThread()); |
| 61 DCHECK(m_reader); | 63 DCHECK(m_reader); |
| 62 DCHECK(!m_isInTwoPhaseRead); | 64 DCHECK(!m_isInTwoPhaseRead); |
| 63 DCHECK(!m_isUpdateWaitingForEndRead); | 65 DCHECK(!m_isUpdateWaitingForEndRead); |
| 64 ++m_token; | 66 ++m_token; |
| 65 m_reader = nullptr; | 67 m_reader = nullptr; |
| 66 m_readerThread = nullptr; | 68 m_readerTaskRunner = nullptr; |
| 67 m_client = nullptr; | 69 m_client = nullptr; |
| 68 } | 70 } |
| 69 void update(std::unique_ptr<WebDataConsumerHandle> handle) | 71 void update(std::unique_ptr<WebDataConsumerHandle> handle) |
| 70 { | 72 { |
| 71 MutexLocker locker(m_mutex); | 73 MutexLocker locker(m_mutex); |
| 72 m_handle = std::move(handle); | 74 m_handle = std::move(handle); |
| 73 if (!m_readerThread) { | 75 if (!m_readerTaskRunner) { |
| 74 // There is no reader. | 76 // There is no reader. |
| 75 return; | 77 return; |
| 76 } | 78 } |
| 77 ++m_token; | 79 ++m_token; |
| 78 updateReaderNoLock(m_token); | 80 updateReaderNoLock(m_token); |
| 79 } | 81 } |
| 80 | 82 |
| 81 Result read(void* data, size_t size, Flags flags, size_t* readSize) | 83 Result read(void* data, size_t size, Flags flags, size_t* readSize) |
| 82 { | 84 { |
| 83 DCHECK(m_readerThread && m_readerThread->isCurrentThread()); | 85 DCHECK(m_readerTaskRunner); |
| 86 DCHECK(m_readerTaskRunner->runsTasksOnCurrentThread()); |
| 84 return m_reader->read(data, size, flags, readSize); | 87 return m_reader->read(data, size, flags, readSize); |
| 85 } | 88 } |
| 86 Result beginRead(const void** buffer, Flags flags, size_t* available) | 89 Result beginRead(const void** buffer, Flags flags, size_t* available) |
| 87 { | 90 { |
| 88 DCHECK(m_readerThread && m_readerThread->isCurrentThread()); | 91 DCHECK(m_readerTaskRunner); |
| 92 DCHECK(m_readerTaskRunner->runsTasksOnCurrentThread()); |
| 89 DCHECK(!m_isInTwoPhaseRead); | 93 DCHECK(!m_isInTwoPhaseRead); |
| 90 Result r = m_reader->beginRead(buffer, flags, available); | 94 Result r = m_reader->beginRead(buffer, flags, available); |
| 91 m_isInTwoPhaseRead = (r == Ok); | 95 m_isInTwoPhaseRead = (r == Ok); |
| 92 return r; | 96 return r; |
| 93 } | 97 } |
| 94 Result endRead(size_t readSize) | 98 Result endRead(size_t readSize) |
| 95 { | 99 { |
| 96 DCHECK(m_readerThread && m_readerThread->isCurrentThread()); | 100 DCHECK(m_readerTaskRunner); |
| 101 DCHECK(m_readerTaskRunner->runsTasksOnCurrentThread()); |
| 97 DCHECK(m_isInTwoPhaseRead); | 102 DCHECK(m_isInTwoPhaseRead); |
| 98 Result r = m_reader->endRead(readSize); | 103 Result r = m_reader->endRead(readSize); |
| 99 m_isInTwoPhaseRead = false; | 104 m_isInTwoPhaseRead = false; |
| 100 if (m_isUpdateWaitingForEndRead) { | 105 if (m_isUpdateWaitingForEndRead) { |
| 101 // We need this lock to access |m_handle|. | 106 // We need this lock to access |m_handle|. |
| 102 MutexLocker locker(m_mutex); | 107 MutexLocker locker(m_mutex); |
| 103 m_reader = nullptr; | 108 m_reader = nullptr; |
| 104 m_reader = m_handle->obtainReader(m_client); | 109 m_reader = m_handle->obtainReader(m_client); |
| 105 m_isUpdateWaitingForEndRead = false; | 110 m_isUpdateWaitingForEndRead = false; |
| 106 } | 111 } |
| 107 return r; | 112 return r; |
| 108 } | 113 } |
| 109 | 114 |
| 110 private: | 115 private: |
| 111 explicit Context(std::unique_ptr<WebDataConsumerHandle> handle) | 116 Context(std::unique_ptr<WebDataConsumerHandle> handle) |
| 112 : m_handle(std::move(handle)) | 117 : m_handle(std::move(handle)) |
| 113 , m_readerThread(nullptr) | 118 , m_readerTaskRunner(nullptr) |
| 114 , m_client(nullptr) | 119 , m_client(nullptr) |
| 115 , m_token(0) | 120 , m_token(0) |
| 116 , m_isUpdateWaitingForEndRead(false) | 121 , m_isUpdateWaitingForEndRead(false) |
| 117 , m_isInTwoPhaseRead(false) | 122 , m_isInTwoPhaseRead(false) |
| 118 { | 123 { |
| 119 } | 124 } |
| 120 void updateReader(Token token) | 125 void updateReader(Token token) |
| 121 { | 126 { |
| 122 MutexLocker locker(m_mutex); | 127 MutexLocker locker(m_mutex); |
| 123 updateReaderNoLock(token); | 128 updateReaderNoLock(token); |
| 124 } | 129 } |
| 125 void updateReaderNoLock(Token token) | 130 void updateReaderNoLock(Token token) |
| 126 { | 131 { |
| 127 if (token != m_token) { | 132 if (token != m_token) { |
| 128 // This request is not fresh. Ignore it. | 133 // This request is not fresh. Ignore it. |
| 129 return; | 134 return; |
| 130 } | 135 } |
| 131 DCHECK(m_readerThread); | 136 DCHECK(m_readerTaskRunner); |
| 132 DCHECK(m_reader); | 137 DCHECK(m_reader); |
| 133 if (m_readerThread->isCurrentThread()) { | 138 if (m_readerTaskRunner->runsTasksOnCurrentThread()) { |
| 134 if (m_isInTwoPhaseRead) { | 139 if (m_isInTwoPhaseRead) { |
| 135 // We are waiting for the two-phase read completion. | 140 // We are waiting for the two-phase read completion. |
| 136 m_isUpdateWaitingForEndRead = true; | 141 m_isUpdateWaitingForEndRead = true; |
| 137 return; | 142 return; |
| 138 } | 143 } |
| 139 // Unregister the old one, then register the new one. | 144 // Unregister the old one, then register the new one. |
| 140 m_reader = nullptr; | 145 m_reader = nullptr; |
| 141 m_reader = m_handle->obtainReader(m_client); | 146 m_reader = m_handle->obtainReader(m_client); |
| 142 return; | 147 return; |
| 143 } | 148 } |
| 144 ++m_token; | 149 ++m_token; |
| 145 m_readerThread->getWebTaskRunner()->postTask(BLINK_FROM_HERE, crossThrea
dBind(&Context::updateReader, wrapPassRefPtr(this), m_token)); | 150 m_readerTaskRunner->postTask(BLINK_FROM_HERE, crossThreadBind(&Context::
updateReader, wrapPassRefPtr(this), m_token)); |
| 146 } | 151 } |
| 147 | 152 |
| 148 std::unique_ptr<Reader> m_reader; | 153 std::unique_ptr<Reader> m_reader; |
| 149 std::unique_ptr<WebDataConsumerHandle> m_handle; | 154 std::unique_ptr<WebDataConsumerHandle> m_handle; |
| 150 // Note: Holding a WebThread raw pointer is not generally safe, but we can | 155 std::unique_ptr<WebTaskRunner> m_readerTaskRunner; |
| 151 // do that in this case because: | |
| 152 // 1. Destructing a ReaderImpl when the bound thread ends is a user's | |
| 153 // responsibility. | |
| 154 // 2. |m_readerThread| will never be used after the associated reader is | |
| 155 // detached. | |
| 156 WebThread* m_readerThread; | |
| 157 Client* m_client; | 156 Client* m_client; |
| 158 Token m_token; | 157 Token m_token; |
| 159 // These boolean values are bound to the reader thread. | 158 // These boolean values are bound to the reader thread. |
| 160 bool m_isUpdateWaitingForEndRead; | 159 bool m_isUpdateWaitingForEndRead; |
| 161 bool m_isInTwoPhaseRead; | 160 bool m_isInTwoPhaseRead; |
| 162 Mutex m_mutex; | 161 Mutex m_mutex; |
| 163 }; | 162 }; |
| 164 | 163 |
| 165 CompositeDataConsumerHandle::ReaderImpl::ReaderImpl(PassRefPtr<Context> context)
: m_context(context) { } | 164 CompositeDataConsumerHandle::ReaderImpl::ReaderImpl(PassRefPtr<Context> context)
: m_context(context) { } |
| 166 | 165 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 210 } | 209 } |
| 211 | 210 |
| 212 CompositeDataConsumerHandle::~CompositeDataConsumerHandle() { } | 211 CompositeDataConsumerHandle::~CompositeDataConsumerHandle() { } |
| 213 | 212 |
| 214 std::unique_ptr<WebDataConsumerHandle::Reader> CompositeDataConsumerHandle::obta
inReader(Client* client) | 213 std::unique_ptr<WebDataConsumerHandle::Reader> CompositeDataConsumerHandle::obta
inReader(Client* client) |
| 215 { | 214 { |
| 216 return m_context->obtainReader(client); | 215 return m_context->obtainReader(client); |
| 217 } | 216 } |
| 218 | 217 |
| 219 } // namespace blink | 218 } // namespace blink |
| OLD | NEW |