Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: content/browser/download/byte_stream.cc

Issue 10074001: Initial implementation of the ByteStream refactor. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Checkpoint and merge to LKGR. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/download/byte_stream.h"
6
7 #include "base/bind.h"
8 #include "base/location.h"
9
10 namespace content {
11
12 ByteStream::ByteStream()
13 : buffer_size_(kDefaultBufferSize),
14 data_size_(0),
15 is_complete_(false),
16 source_status_(DOWNLOAD_INTERRUPT_REASON_NONE),
17 empty_percentage_(0),
18 full_percentage_(0),
19 num_source_callbacks_(0),
20 num_sink_callbacks_(0),
21 bytes_read_(0),
22 buffers_read_(0){ }
23
24 void ByteStream::SetBufferSize(size_t buffer_size) {
25 buffer_size_ = buffer_size;
26 }
27
28 bool ByteStream::AddData(scoped_refptr<net::IOBuffer> buffer,
29 size_t byte_count) {
30 base::Time now(base::Time::Now());
31 base::AutoLock auto_lock(lock_);
32
33 if (data_size_ == 0 && byte_count > 0)
34 last_non_empty_time_ = now;
35
36 if (data_size_ <= (full_percentage_ * buffer_size_) / 100 &&
37 data_size_ + byte_count > (full_percentage_ * buffer_size_) / 100) {
38 // We only want to track time from empty to next signal; anything
39 // beyond that is the sink's problem.
40 if (!last_non_empty_time_.is_null()) {
41 sink_trigger_wait_time_ += (now - last_non_empty_time_);
42 last_non_empty_time_ = base::Time();
43 }
44 if (sink_task_runner_.get() != NULL) {
45 // Nothing that actually touches the data on this object can be
46 // executed until we drop the lock, so it's ok to
47 // dispatch this before we actually add the data.
48 sink_task_runner_->PostTask(
49 FROM_HERE, base::Bind(&content::ByteStream::RunSinkCallback,
50 this, sink_task_runner_));
51 num_sink_callbacks_++;
52 }
53 }
54
55 // Take manual (not enforced by compiler via scoped_*) ownership of data.
56 contents_.push_back(std::make_pair(buffer, byte_count));
57 data_size_ += byte_count;
58 return (data_size_ <= buffer_size_);
59 }
60
61 void ByteStream::SourceComplete(DownloadInterruptReason status) {
62 base::AutoLock auto_lock(lock_);
63
64 is_complete_ = true;
65 source_status_ = status;
66 // If data_size_ is over our full percentage, a callback has already
67 // been posted.
68 if (data_size_ <= (full_percentage_ * buffer_size_) / 100 &&
69 sink_task_runner_.get() != NULL) {
70 sink_task_runner_->PostTask(
71 FROM_HERE, base::Bind(&content::ByteStream::RunSinkCallback,
72 this, sink_task_runner_));
73 }
74 }
75
76 bool ByteStream::IsFull() const {
77 base::AutoLock auto_lock(lock_);
78
79 return (data_size_ > buffer_size_);
80 }
81
82 void ByteStream::RegisterSourceCallback(
83 scoped_refptr<base::TaskRunner> source_task_runner,
84 ByteStreamCallback source_callback,
85 int empty_percentage) {
86 DCHECK_LE(0, empty_percentage);
87 DCHECK_GE(100, empty_percentage);
88
89 base::AutoLock auto_lock(lock_);
90
91 source_task_runner_ = source_task_runner;
92 source_callback_ = source_callback;
93 empty_percentage_ = empty_percentage;
94 }
95
96 ByteStream::StreamState ByteStream::GetData(scoped_refptr<net::IOBuffer>* data,
97 size_t* length) {
98 base::Time now(base::Time::Now());
99 base::AutoLock auto_lock(lock_);
100
101 if (contents_.empty()) {
102 if (is_complete_)
103 return STREAM_COMPLETE;
104 return STREAM_EMPTY;
105 }
106
107 if (data_size_ >= buffer_size_ &&
108 data_size_ - contents_.front().second < buffer_size_)
109 last_non_full_time_ = now;
110
111 size_t byte_boundary = (buffer_size_ * (100 - empty_percentage_)) / 100;
112 if (data_size_ > byte_boundary &&
113 data_size_ - contents_.front().second <= byte_boundary) {
114 if (!last_non_full_time_.is_null()) {
115 source_trigger_wait_time_ += (now - last_non_full_time_);
116 last_non_full_time_ = base::Time();
117 }
118 if (source_task_runner_.get() != NULL) {
119 // Nothing that actually touches the data on this object can be
120 // executed until we drop the lock, so it's ok to
121 // dispatch this before we actually take the data.
122 source_task_runner_->PostTask(FROM_HERE, base::Bind(
123 &content::ByteStream::RunSourceCallback, this, source_task_runner_));
124 num_source_callbacks_++;
125 }
126 }
127
128 *data = contents_.front().first;
129 *length = contents_.front().second;
130 contents_.pop_front();
131 data_size_ -= *length;
132 bytes_read_ += *length;
133 buffers_read_++;
134 return STREAM_HAS_DATA;
135 }
136
137 DownloadInterruptReason ByteStream::GetSourceResult () const {
138 base::AutoLock auto_lock(lock_);
139
140 DCHECK(is_complete_);
141
142 return source_status_;
143 }
144
145 void ByteStream::RegisterSinkCallback(
146 scoped_refptr<base::TaskRunner> sink_task_runner,
147 ByteStreamCallback sink_callback,
148 int full_percentage) {
149 DCHECK_LE(0, full_percentage);
150 DCHECK_GE(100, full_percentage);
151
152 base::AutoLock auto_lock(lock_);
153
154 sink_task_runner_ = sink_task_runner;
155 sink_callback_ = sink_callback;
156 full_percentage_ = full_percentage;
157 }
158
159 ByteStream::~ByteStream() {
160 }
161
162 void ByteStream::RunSourceCallback(
163 scoped_refptr<base::TaskRunner> target_runner) {
164 base::Closure callback;
165 {
166 base::AutoLock auto_lock(lock_);
167
168 // If the target_runner has been updated, that implies an access to
169 // the class, so we can drop this request on the floor. (The
170 // alternative would be to forward it on to the new task runner.)
171 if (target_runner.get() != source_task_runner_.get())
172 return;
173
174 if (source_callback_.is_null())
175 return;
176
177 callback = source_callback_;
178 }
179
180 // Run unlocked to allow caller to call back into us.
181 callback.Run();
182 }
183
184 void ByteStream::RunSinkCallback(
185 scoped_refptr<base::TaskRunner> target_runner) {
186 base::Closure callback;
187 {
188 base::AutoLock auto_lock(lock_);
189
190 // If the target_runner has been updated, that implies an access to
191 // the class, so we can drop this request on the floor. (The
192 // alternative would be to forward it on to the new task runner.)
193 if (target_runner.get() != sink_task_runner_.get())
194 return;
195
196 if (sink_callback_.is_null())
197 return;
198
199 callback = sink_callback_;
200 }
201
202 // Run unlocked to allow caller to call back into us.
203 callback.Run();
204 }
205
206 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/download/byte_stream.h ('k') | content/browser/download/byte_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698