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 |