Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "core/fileapi/FileReader.h" | 32 #include "core/fileapi/FileReader.h" |
| 33 | 33 |
| 34 #include "bindings/core/v8/ExceptionState.h" | 34 #include "bindings/core/v8/ExceptionState.h" |
| 35 #include "core/dom/CrossThreadTask.h" | 35 #include "core/dom/CrossThreadTask.h" |
| 36 #include "core/dom/Document.h" | |
| 36 #include "core/dom/ExceptionCode.h" | 37 #include "core/dom/ExceptionCode.h" |
| 37 #include "core/dom/ExecutionContext.h" | 38 #include "core/dom/ExecutionContext.h" |
| 38 #include "core/events/ProgressEvent.h" | 39 #include "core/events/ProgressEvent.h" |
| 39 #include "core/fileapi/File.h" | 40 #include "core/fileapi/File.h" |
| 41 #include "core/frame/LocalFrame.h" | |
| 42 #include "core/workers/WorkerClients.h" | |
| 43 #include "core/workers/WorkerGlobalScope.h" | |
| 40 #include "platform/Logging.h" | 44 #include "platform/Logging.h" |
| 45 #include "platform/Supplementable.h" | |
| 41 #include "wtf/ArrayBuffer.h" | 46 #include "wtf/ArrayBuffer.h" |
| 42 #include "wtf/CurrentTime.h" | 47 #include "wtf/CurrentTime.h" |
| 43 #include "wtf/Deque.h" | 48 #include "wtf/Deque.h" |
| 44 #include "wtf/HashSet.h" | 49 #include "wtf/HashSet.h" |
| 45 #include "wtf/ThreadSpecific.h" | 50 #include "wtf/ThreadSpecific.h" |
| 46 #include "wtf/Threading.h" | 51 #include "wtf/Threading.h" |
| 47 #include "wtf/text/CString.h" | 52 #include "wtf/text/CString.h" |
| 48 | 53 |
| 49 namespace WebCore { | 54 namespace WebCore { |
| 50 | 55 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 63 #endif | 68 #endif |
| 64 | 69 |
| 65 } // namespace | 70 } // namespace |
| 66 | 71 |
| 67 // Embedders like chromium limit the number of simultaneous requests to avoid | 72 // Embedders like chromium limit the number of simultaneous requests to avoid |
| 68 // excessive IPC congestion. We limit this to 100 per thread to throttle the | 73 // excessive IPC congestion. We limit this to 100 per thread to throttle the |
| 69 // requests (the value is arbitrarily chosen). | 74 // requests (the value is arbitrarily chosen). |
| 70 static const size_t kMaxOutstandingRequestsPerThread = 100; | 75 static const size_t kMaxOutstandingRequestsPerThread = 100; |
| 71 static const double progressNotificationIntervalMS = 50; | 76 static const double progressNotificationIntervalMS = 50; |
| 72 | 77 |
| 73 class FileReader::ThrottlingController { | 78 class FileReader::ThrottlingController FINAL : public NoBaseWillBeGarbageCollect edFinalized<FileReader::ThrottlingController>, public WillBeHeapSupplement<Local Frame>, public WillBeHeapSupplement<WorkerClients> { |
| 79 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(FileReader::ThrottlingController); | |
| 74 public: | 80 public: |
| 75 ThrottlingController() : m_maxRunningReaders(kMaxOutstandingRequestsPerThrea d) { } | 81 static ThrottlingController* from(ExecutionContext* context) |
| 82 { | |
| 83 if (context->isDocument()) { | |
| 84 Document* document = toDocument(context); | |
| 85 if (!document->frame()) | |
| 86 return 0; | |
| 87 | |
| 88 ThrottlingController* controller = static_cast<ThrottlingController* >(WillBeHeapSupplement<LocalFrame>::from(document->frame(), supplementName())); | |
| 89 if (controller) | |
| 90 return controller; | |
| 91 | |
| 92 controller = new ThrottlingController(); | |
| 93 WillBeHeapSupplement<LocalFrame>::provideTo(*document->frame(), supp lementName(), adoptPtrWillBeNoop(controller)); | |
| 94 return controller; | |
| 95 } | |
| 96 ASSERT(context->isWorkerGlobalScope()); | |
|
haraken
2014/07/16 11:37:26
Also add ASSERT(!isMainThread()).
sof
2014/07/16 11:46:19
Done.
| |
| 97 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); | |
| 98 ThrottlingController* controller = static_cast<ThrottlingController*>(Wi llBeHeapSupplement<WorkerClients>::from(workerGlobalScope->clients(), supplement Name())); | |
| 99 if (controller) | |
| 100 return controller; | |
| 101 | |
| 102 controller = new ThrottlingController(); | |
| 103 WillBeHeapSupplement<WorkerClients>::provideTo(*workerGlobalScope->clien ts(), supplementName(), adoptPtrWillBeNoop(controller)); | |
| 104 return controller; | |
| 105 } | |
| 106 | |
| 76 ~ThrottlingController() { } | 107 ~ThrottlingController() { } |
| 77 | 108 |
| 78 enum FinishReaderType { DoNotRunPendingReaders, RunPendingReaders }; | 109 enum FinishReaderType { DoNotRunPendingReaders, RunPendingReaders }; |
| 79 | 110 |
| 80 void pushReader(FileReader* reader) | 111 void pushReader(FileReader* reader) |
| 81 { | 112 { |
| 82 if (m_pendingReaders.isEmpty() | 113 if (m_pendingReaders.isEmpty() |
| 83 && m_runningReaders.size() < m_maxRunningReaders) { | 114 && m_runningReaders.size() < m_maxRunningReaders) { |
| 84 reader->executePendingRead(); | 115 reader->executePendingRead(); |
| 85 ASSERT(!m_runningReaders.contains(reader)); | 116 ASSERT(!m_runningReaders.contains(reader)); |
| 86 m_runningReaders.add(reader); | 117 m_runningReaders.add(reader); |
| 87 return; | 118 return; |
| 88 } | 119 } |
| 89 m_pendingReaders.append(reader); | 120 m_pendingReaders.append(reader); |
| 90 executeReaders(); | 121 executeReaders(); |
| 91 } | 122 } |
| 92 | 123 |
| 93 FinishReaderType removeReader(FileReader* reader) | 124 FinishReaderType removeReader(FileReader* reader) |
| 94 { | 125 { |
| 95 HashSet<FileReader*>::const_iterator hashIter = m_runningReaders.find(re ader); | 126 WillBeHeapHashSet<RawPtrWillBeMember<FileReader> >::const_iterator hashI ter = m_runningReaders.find(reader); |
| 96 if (hashIter != m_runningReaders.end()) { | 127 if (hashIter != m_runningReaders.end()) { |
| 97 m_runningReaders.remove(hashIter); | 128 m_runningReaders.remove(hashIter); |
| 98 return RunPendingReaders; | 129 return RunPendingReaders; |
| 99 } | 130 } |
| 100 Deque<FileReader*>::const_iterator dequeEnd = m_pendingReaders.end(); | 131 WillBeHeapDeque<RawPtrWillBeMember<FileReader> >::const_iterator dequeEn d = m_pendingReaders.end(); |
| 101 for (Deque<FileReader*>::const_iterator it = m_pendingReaders.begin(); i t != dequeEnd; ++it) { | 132 for (WillBeHeapDeque<RawPtrWillBeMember<FileReader> >::const_iterator it = m_pendingReaders.begin(); it != dequeEnd; ++it) { |
| 102 if (*it == reader) { | 133 if (*it == reader) { |
| 103 m_pendingReaders.remove(it); | 134 m_pendingReaders.remove(it); |
| 104 break; | 135 break; |
| 105 } | 136 } |
| 106 } | 137 } |
| 107 return DoNotRunPendingReaders; | 138 return DoNotRunPendingReaders; |
| 108 } | 139 } |
| 109 | 140 |
| 110 void finishReader(FileReader* reader, FinishReaderType nextStep) | 141 void finishReader(FileReader* reader, FinishReaderType nextStep) |
| 111 { | 142 { |
| 112 if (nextStep == RunPendingReaders) | 143 if (nextStep == RunPendingReaders) |
| 113 executeReaders(); | 144 executeReaders(); |
| 114 } | 145 } |
| 115 | 146 |
| 147 void trace(Visitor* visitor) | |
| 148 { | |
| 149 #if ENABLE(OILPAN) | |
| 150 visitor->trace(m_pendingReaders); | |
| 151 #endif | |
| 152 visitor->trace(m_runningReaders); | |
| 153 WillBeHeapSupplement<LocalFrame>::trace(visitor); | |
| 154 WillBeHeapSupplement<WorkerClients>::trace(visitor); | |
| 155 } | |
| 156 | |
| 116 private: | 157 private: |
| 158 ThrottlingController() | |
| 159 : m_maxRunningReaders(kMaxOutstandingRequestsPerThread) | |
| 160 { | |
| 161 } | |
| 162 | |
| 117 void executeReaders() | 163 void executeReaders() |
| 118 { | 164 { |
| 119 while (m_runningReaders.size() < m_maxRunningReaders) { | 165 while (m_runningReaders.size() < m_maxRunningReaders) { |
| 120 if (m_pendingReaders.isEmpty()) | 166 if (m_pendingReaders.isEmpty()) |
| 121 return; | 167 return; |
| 122 FileReader* reader = m_pendingReaders.takeFirst(); | 168 FileReader* reader = m_pendingReaders.takeFirst(); |
| 123 reader->executePendingRead(); | 169 reader->executePendingRead(); |
| 124 m_runningReaders.add(reader); | 170 m_runningReaders.add(reader); |
| 125 } | 171 } |
| 126 } | 172 } |
| 127 | 173 |
| 174 static const char* supplementName() { return "FileReaderThrottleController"; } | |
|
haraken
2014/07/16 11:37:26
"FileReaderThrottlingController"
sof
2014/07/16 11:46:19
Fixed.
| |
| 175 | |
| 128 const size_t m_maxRunningReaders; | 176 const size_t m_maxRunningReaders; |
| 129 Deque<FileReader*> m_pendingReaders; | 177 WillBeHeapDeque<RawPtrWillBeMember<FileReader> > m_pendingReaders; |
| 130 HashSet<FileReader*> m_runningReaders; | 178 WillBeHeapHashSet<RawPtrWillBeMember<FileReader> > m_runningReaders; |
| 131 }; | 179 }; |
| 132 | 180 |
| 133 PassRefPtrWillBeRawPtr<FileReader> FileReader::create(ExecutionContext* context) | 181 PassRefPtrWillBeRawPtr<FileReader> FileReader::create(ExecutionContext* context) |
| 134 { | 182 { |
| 135 RefPtrWillBeRawPtr<FileReader> fileReader(adoptRefWillBeNoop(new FileReader( context))); | 183 RefPtrWillBeRawPtr<FileReader> fileReader(adoptRefWillBeNoop(new FileReader( context))); |
| 136 fileReader->suspendIfNeeded(); | 184 fileReader->suspendIfNeeded(); |
| 137 return fileReader.release(); | 185 return fileReader.release(); |
| 138 } | 186 } |
| 139 | 187 |
| 140 FileReader::FileReader(ExecutionContext* context) | 188 FileReader::FileReader(ExecutionContext* context) |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 380 dispatchEvent(ProgressEvent::create(type, false, 0, 0)); | 428 dispatchEvent(ProgressEvent::create(type, false, 0, 0)); |
| 381 return; | 429 return; |
| 382 } | 430 } |
| 383 | 431 |
| 384 if (m_loader->totalBytes() >= 0) | 432 if (m_loader->totalBytes() >= 0) |
| 385 dispatchEvent(ProgressEvent::create(type, true, m_loader->bytesLoaded(), m_loader->totalBytes())); | 433 dispatchEvent(ProgressEvent::create(type, true, m_loader->bytesLoaded(), m_loader->totalBytes())); |
| 386 else | 434 else |
| 387 dispatchEvent(ProgressEvent::create(type, false, m_loader->bytesLoaded() , 0)); | 435 dispatchEvent(ProgressEvent::create(type, false, m_loader->bytesLoaded() , 0)); |
| 388 } | 436 } |
| 389 | 437 |
| 390 ThreadSpecific<FileReader::ThrottlingController>& FileReader::throttlingControll er() | 438 FileReader::ThrottlingController* FileReader::throttlingController() |
| 391 { | 439 { |
| 392 AtomicallyInitializedStatic(ThreadSpecific<FileReader::ThrottlingController> *, controller = new ThreadSpecific<FileReader::ThrottlingController>); | 440 return FileReader::ThrottlingController::from(executionContext()); |
| 393 return *controller; | |
| 394 } | 441 } |
| 395 | 442 |
| 396 PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const | 443 PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const |
| 397 { | 444 { |
| 398 if (!m_loader || m_error) | 445 if (!m_loader || m_error) |
| 399 return nullptr; | 446 return nullptr; |
| 400 return m_loader->arrayBufferResult(); | 447 return m_loader->arrayBufferResult(); |
| 401 } | 448 } |
| 402 | 449 |
| 403 String FileReader::stringResult() | 450 String FileReader::stringResult() |
| 404 { | 451 { |
| 405 if (!m_loader || m_error) | 452 if (!m_loader || m_error) |
| 406 return String(); | 453 return String(); |
| 407 return m_loader->stringResult(); | 454 return m_loader->stringResult(); |
| 408 } | 455 } |
| 409 | 456 |
| 410 void FileReader::trace(Visitor* visitor) | 457 void FileReader::trace(Visitor* visitor) |
| 411 { | 458 { |
| 412 visitor->trace(m_error); | 459 visitor->trace(m_error); |
| 413 EventTargetWithInlineData::trace(visitor); | 460 EventTargetWithInlineData::trace(visitor); |
| 414 } | 461 } |
| 415 | 462 |
| 416 } // namespace WebCore | 463 } // namespace WebCore |
| OLD | NEW |