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(!isMainThread()); |
| 97 ASSERT(context->isWorkerGlobalScope()); |
| 98 WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context); |
| 99 ThrottlingController* controller = static_cast<ThrottlingController*>(Wi
llBeHeapSupplement<WorkerClients>::from(workerGlobalScope->clients(), supplement
Name())); |
| 100 if (controller) |
| 101 return controller; |
| 102 |
| 103 controller = new ThrottlingController(); |
| 104 WillBeHeapSupplement<WorkerClients>::provideTo(*workerGlobalScope->clien
ts(), supplementName(), adoptPtrWillBeNoop(controller)); |
| 105 return controller; |
| 106 } |
| 107 |
76 ~ThrottlingController() { } | 108 ~ThrottlingController() { } |
77 | 109 |
78 enum FinishReaderType { DoNotRunPendingReaders, RunPendingReaders }; | 110 enum FinishReaderType { DoNotRunPendingReaders, RunPendingReaders }; |
79 | 111 |
80 void pushReader(FileReader* reader) | 112 void pushReader(FileReader* reader) |
81 { | 113 { |
82 if (m_pendingReaders.isEmpty() | 114 if (m_pendingReaders.isEmpty() |
83 && m_runningReaders.size() < m_maxRunningReaders) { | 115 && m_runningReaders.size() < m_maxRunningReaders) { |
84 reader->executePendingRead(); | 116 reader->executePendingRead(); |
85 ASSERT(!m_runningReaders.contains(reader)); | 117 ASSERT(!m_runningReaders.contains(reader)); |
86 m_runningReaders.add(reader); | 118 m_runningReaders.add(reader); |
87 return; | 119 return; |
88 } | 120 } |
89 m_pendingReaders.append(reader); | 121 m_pendingReaders.append(reader); |
90 executeReaders(); | 122 executeReaders(); |
91 } | 123 } |
92 | 124 |
93 FinishReaderType removeReader(FileReader* reader) | 125 FinishReaderType removeReader(FileReader* reader) |
94 { | 126 { |
95 HashSet<FileReader*>::const_iterator hashIter = m_runningReaders.find(re
ader); | 127 WillBeHeapHashSet<RawPtrWillBeMember<FileReader> >::const_iterator hashI
ter = m_runningReaders.find(reader); |
96 if (hashIter != m_runningReaders.end()) { | 128 if (hashIter != m_runningReaders.end()) { |
97 m_runningReaders.remove(hashIter); | 129 m_runningReaders.remove(hashIter); |
98 return RunPendingReaders; | 130 return RunPendingReaders; |
99 } | 131 } |
100 Deque<FileReader*>::const_iterator dequeEnd = m_pendingReaders.end(); | 132 WillBeHeapDeque<RawPtrWillBeMember<FileReader> >::const_iterator dequeEn
d = m_pendingReaders.end(); |
101 for (Deque<FileReader*>::const_iterator it = m_pendingReaders.begin(); i
t != dequeEnd; ++it) { | 133 for (WillBeHeapDeque<RawPtrWillBeMember<FileReader> >::const_iterator it
= m_pendingReaders.begin(); it != dequeEnd; ++it) { |
102 if (*it == reader) { | 134 if (*it == reader) { |
103 m_pendingReaders.remove(it); | 135 m_pendingReaders.remove(it); |
104 break; | 136 break; |
105 } | 137 } |
106 } | 138 } |
107 return DoNotRunPendingReaders; | 139 return DoNotRunPendingReaders; |
108 } | 140 } |
109 | 141 |
110 void finishReader(FileReader* reader, FinishReaderType nextStep) | 142 void finishReader(FileReader* reader, FinishReaderType nextStep) |
111 { | 143 { |
112 if (nextStep == RunPendingReaders) | 144 if (nextStep == RunPendingReaders) |
113 executeReaders(); | 145 executeReaders(); |
114 } | 146 } |
115 | 147 |
| 148 void trace(Visitor* visitor) |
| 149 { |
| 150 #if ENABLE(OILPAN) |
| 151 visitor->trace(m_pendingReaders); |
| 152 #endif |
| 153 visitor->trace(m_runningReaders); |
| 154 WillBeHeapSupplement<LocalFrame>::trace(visitor); |
| 155 WillBeHeapSupplement<WorkerClients>::trace(visitor); |
| 156 } |
| 157 |
116 private: | 158 private: |
| 159 ThrottlingController() |
| 160 : m_maxRunningReaders(kMaxOutstandingRequestsPerThread) |
| 161 { |
| 162 } |
| 163 |
117 void executeReaders() | 164 void executeReaders() |
118 { | 165 { |
119 while (m_runningReaders.size() < m_maxRunningReaders) { | 166 while (m_runningReaders.size() < m_maxRunningReaders) { |
120 if (m_pendingReaders.isEmpty()) | 167 if (m_pendingReaders.isEmpty()) |
121 return; | 168 return; |
122 FileReader* reader = m_pendingReaders.takeFirst(); | 169 FileReader* reader = m_pendingReaders.takeFirst(); |
123 reader->executePendingRead(); | 170 reader->executePendingRead(); |
124 m_runningReaders.add(reader); | 171 m_runningReaders.add(reader); |
125 } | 172 } |
126 } | 173 } |
127 | 174 |
| 175 static const char* supplementName() { return "FileReaderThrottlingController
"; } |
| 176 |
128 const size_t m_maxRunningReaders; | 177 const size_t m_maxRunningReaders; |
129 Deque<FileReader*> m_pendingReaders; | 178 WillBeHeapDeque<RawPtrWillBeMember<FileReader> > m_pendingReaders; |
130 HashSet<FileReader*> m_runningReaders; | 179 WillBeHeapHashSet<RawPtrWillBeMember<FileReader> > m_runningReaders; |
131 }; | 180 }; |
132 | 181 |
133 PassRefPtrWillBeRawPtr<FileReader> FileReader::create(ExecutionContext* context) | 182 PassRefPtrWillBeRawPtr<FileReader> FileReader::create(ExecutionContext* context) |
134 { | 183 { |
135 RefPtrWillBeRawPtr<FileReader> fileReader(adoptRefWillBeNoop(new FileReader(
context))); | 184 RefPtrWillBeRawPtr<FileReader> fileReader(adoptRefWillBeNoop(new FileReader(
context))); |
136 fileReader->suspendIfNeeded(); | 185 fileReader->suspendIfNeeded(); |
137 return fileReader.release(); | 186 return fileReader.release(); |
138 } | 187 } |
139 | 188 |
140 FileReader::FileReader(ExecutionContext* context) | 189 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)); | 429 dispatchEvent(ProgressEvent::create(type, false, 0, 0)); |
381 return; | 430 return; |
382 } | 431 } |
383 | 432 |
384 if (m_loader->totalBytes() >= 0) | 433 if (m_loader->totalBytes() >= 0) |
385 dispatchEvent(ProgressEvent::create(type, true, m_loader->bytesLoaded(),
m_loader->totalBytes())); | 434 dispatchEvent(ProgressEvent::create(type, true, m_loader->bytesLoaded(),
m_loader->totalBytes())); |
386 else | 435 else |
387 dispatchEvent(ProgressEvent::create(type, false, m_loader->bytesLoaded()
, 0)); | 436 dispatchEvent(ProgressEvent::create(type, false, m_loader->bytesLoaded()
, 0)); |
388 } | 437 } |
389 | 438 |
390 ThreadSpecific<FileReader::ThrottlingController>& FileReader::throttlingControll
er() | 439 FileReader::ThrottlingController* FileReader::throttlingController() |
391 { | 440 { |
392 AtomicallyInitializedStatic(ThreadSpecific<FileReader::ThrottlingController>
*, controller = new ThreadSpecific<FileReader::ThrottlingController>); | 441 return FileReader::ThrottlingController::from(executionContext()); |
393 return *controller; | |
394 } | 442 } |
395 | 443 |
396 PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const | 444 PassRefPtr<ArrayBuffer> FileReader::arrayBufferResult() const |
397 { | 445 { |
398 if (!m_loader || m_error) | 446 if (!m_loader || m_error) |
399 return nullptr; | 447 return nullptr; |
400 return m_loader->arrayBufferResult(); | 448 return m_loader->arrayBufferResult(); |
401 } | 449 } |
402 | 450 |
403 String FileReader::stringResult() | 451 String FileReader::stringResult() |
404 { | 452 { |
405 if (!m_loader || m_error) | 453 if (!m_loader || m_error) |
406 return String(); | 454 return String(); |
407 return m_loader->stringResult(); | 455 return m_loader->stringResult(); |
408 } | 456 } |
409 | 457 |
410 void FileReader::trace(Visitor* visitor) | 458 void FileReader::trace(Visitor* visitor) |
411 { | 459 { |
412 visitor->trace(m_error); | 460 visitor->trace(m_error); |
413 EventTargetWithInlineData::trace(visitor); | 461 EventTargetWithInlineData::trace(visitor); |
414 } | 462 } |
415 | 463 |
416 } // namespace WebCore | 464 } // namespace WebCore |
OLD | NEW |