 Chromium Code Reviews
 Chromium Code Reviews Issue 395143002:
  Make FileReader's throttle controller a supplement.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/blink.git@master
    
  
    Issue 395143002:
  Make FileReader's throttle controller a supplement.  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/blink.git@master| 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 |