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

Side by Side Diff: components/cronet/android/cronet_bidirectional_stream_adapter.cc

Issue 1969893002: Remove unnecessary array allocation in cronet_bidirectional_stream_adapter.cc (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: self review Created 4 years, 7 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
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cronet_bidirectional_stream_adapter.h" 5 #include "cronet_bidirectional_stream_adapter.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 template <typename JavaArrayType> 42 template <typename JavaArrayType>
43 size_t SafeGetArrayLength(JNIEnv* env, JavaArrayType jarray) { 43 size_t SafeGetArrayLength(JNIEnv* env, JavaArrayType jarray) {
44 DCHECK(jarray); 44 DCHECK(jarray);
45 jsize length = env->GetArrayLength(jarray); 45 jsize length = env->GetArrayLength(jarray);
46 DCHECK_GE(length, 0) << "Invalid array length: " << length; 46 DCHECK_GE(length, 0) << "Invalid array length: " << length;
47 return static_cast<size_t>(std::max(0, length)); 47 return static_cast<size_t>(std::max(0, length));
48 } 48 }
49 49
50 } // namespace 50 } // namespace
51 51
52 PendingWriteData::PendingWriteData(JNIEnv* env,
53 jobjectArray jwrite_buffer_list,
54 jintArray jwrite_buffer_pos_list,
55 jintArray jwrite_buffer_limit_list,
56 jboolean jwrite_end_of_stream) {
57 this->jwrite_buffer_list.Reset(env, jwrite_buffer_list);
58 this->jwrite_buffer_pos_list.Reset(env, jwrite_buffer_pos_list);
59 this->jwrite_buffer_limit_list.Reset(env, jwrite_buffer_limit_list);
60 this->jwrite_end_of_stream = jwrite_end_of_stream;
61 }
62
63 PendingWriteData::~PendingWriteData() {
64 // Reset global references.
65 this->jwrite_buffer_list.Reset();
mef 2016/05/13 15:12:58 nit: you don't need this->
xunjieli 2016/05/13 15:35:21 Done.
66 this->jwrite_buffer_pos_list.Reset();
67 this->jwrite_buffer_limit_list.Reset();
68 }
69
52 static jlong CreateBidirectionalStream( 70 static jlong CreateBidirectionalStream(
53 JNIEnv* env, 71 JNIEnv* env,
54 const base::android::JavaParamRef<jobject>& jbidi_stream, 72 const base::android::JavaParamRef<jobject>& jbidi_stream,
55 jlong jurl_request_context_adapter, 73 jlong jurl_request_context_adapter,
56 jboolean jdisable_auto_flush) { 74 jboolean jdisable_auto_flush) {
57 CronetURLRequestContextAdapter* context_adapter = 75 CronetURLRequestContextAdapter* context_adapter =
58 reinterpret_cast<CronetURLRequestContextAdapter*>( 76 reinterpret_cast<CronetURLRequestContextAdapter*>(
59 jurl_request_context_adapter); 77 jurl_request_context_adapter);
60 DCHECK(context_adapter); 78 DCHECK(context_adapter);
61 79
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 jboolean jend_of_stream) { 175 jboolean jend_of_stream) {
158 size_t buffers_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); 176 size_t buffers_array_size = SafeGetArrayLength(env, jbyte_buffers.obj());
159 size_t pos_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); 177 size_t pos_array_size = SafeGetArrayLength(env, jbyte_buffers.obj());
160 size_t limit_array_size = SafeGetArrayLength(env, jbyte_buffers.obj()); 178 size_t limit_array_size = SafeGetArrayLength(env, jbyte_buffers.obj());
161 if (buffers_array_size != pos_array_size || 179 if (buffers_array_size != pos_array_size ||
162 buffers_array_size != limit_array_size) { 180 buffers_array_size != limit_array_size) {
163 DLOG(ERROR) << "Illegal arguments."; 181 DLOG(ERROR) << "Illegal arguments.";
164 return JNI_FALSE; 182 return JNI_FALSE;
165 } 183 }
166 184
167 IOBufferWithByteBufferList buffers; 185 std::unique_ptr<PendingWriteData> pending_write_data;
186 pending_write_data.reset(
187 new PendingWriteData(env, jbyte_buffers.obj(), jbyte_buffers_pos.obj(),
188 jbyte_buffers_limit.obj(), jend_of_stream));
168 for (size_t i = 0; i < buffers_array_size; ++i) { 189 for (size_t i = 0; i < buffers_array_size; ++i) {
169 ScopedJavaLocalRef<jobject> jbuffer( 190 ScopedJavaLocalRef<jobject> jbuffer(
170 env, env->GetObjectArrayElement(jbyte_buffers, i)); 191 env, env->GetObjectArrayElement(
192 pending_write_data->jwrite_buffer_list.obj(), i));
171 void* data = env->GetDirectBufferAddress(jbuffer.obj()); 193 void* data = env->GetDirectBufferAddress(jbuffer.obj());
172 if (!data) 194 if (!data)
173 return JNI_FALSE; 195 return JNI_FALSE;
174 jint pos; 196 jint pos;
175 env->GetIntArrayRegion(jbyte_buffers_pos.obj(), i, 1, &pos); 197 env->GetIntArrayRegion(pending_write_data->jwrite_buffer_pos_list.obj(), i,
198 1, &pos);
176 jint limit; 199 jint limit;
177 env->GetIntArrayRegion(jbyte_buffers_limit.obj(), i, 1, &limit); 200 env->GetIntArrayRegion(pending_write_data->jwrite_buffer_limit_list.obj(),
201 i, 1, &limit);
178 DCHECK_LE(pos, limit); 202 DCHECK_LE(pos, limit);
179 scoped_refptr<IOBufferWithByteBuffer> write_buffer( 203 scoped_refptr<net::WrappedIOBuffer> write_buffer(
180 new IOBufferWithByteBuffer( 204 new net::WrappedIOBuffer(static_cast<char*>(data) + pos));
mef 2016/05/13 15:12:58 Can we keep using IOBufferWithByteBuffer here? Yes
xunjieli 2016/05/13 15:35:22 But we have the same check on line 193. Isn't the
mef 2016/05/16 13:54:17 My concern was that Java objects could theoretical
xunjieli 2016/05/16 14:12:28 Done.
181 env, base::android::JavaParamRef<jobject>(env, jbuffer.Release()), 205 pending_write_data->write_buffer_list.push_back(write_buffer);
182 data, pos, limit)); 206 pending_write_data->write_buffer_len_list.push_back(limit - pos);
183 buffers.push_back(write_buffer);
184 } 207 }
208
185 context_->PostTaskToNetworkThread( 209 context_->PostTaskToNetworkThread(
186 FROM_HERE, 210 FROM_HERE,
187 base::Bind(&CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread, 211 base::Bind(&CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread,
188 base::Unretained(this), buffers, jend_of_stream)); 212 base::Unretained(this),
189 213 base::Passed(std::move(pending_write_data))));
190 return JNI_TRUE; 214 return JNI_TRUE;
191 } 215 }
192 216
193 void CronetBidirectionalStreamAdapter::Destroy( 217 void CronetBidirectionalStreamAdapter::Destroy(
194 JNIEnv* env, 218 JNIEnv* env,
195 const base::android::JavaParamRef<jobject>& jcaller, 219 const base::android::JavaParamRef<jobject>& jcaller,
196 jboolean jsend_on_canceled) { 220 jboolean jsend_on_canceled) {
197 // Destroy could be called from any thread, including network thread (if 221 // Destroy could be called from any thread, including network thread (if
198 // posting task to executor throws an exception), but is posted, so |this| 222 // posting task to executor throws an exception), but is posted, so |this|
199 // is valid until calling task is complete. Destroy() is always called from 223 // is valid until calling task is complete. Destroy() is always called from
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 env, owner_.obj(), read_buffer_->byte_buffer(), bytes_read, 271 env, owner_.obj(), read_buffer_->byte_buffer(), bytes_read,
248 read_buffer_->initial_position(), read_buffer_->initial_limit(), 272 read_buffer_->initial_position(), read_buffer_->initial_limit(),
249 bidi_stream_->GetTotalReceivedBytes()); 273 bidi_stream_->GetTotalReceivedBytes());
250 // Free the read buffer. This lets the Java ByteBuffer be freed, if the 274 // Free the read buffer. This lets the Java ByteBuffer be freed, if the
251 // embedder releases it, too. 275 // embedder releases it, too.
252 read_buffer_ = nullptr; 276 read_buffer_ = nullptr;
253 } 277 }
254 278
255 void CronetBidirectionalStreamAdapter::OnDataSent() { 279 void CronetBidirectionalStreamAdapter::OnDataSent() {
256 DCHECK(context_->IsOnNetworkThread()); 280 DCHECK(context_->IsOnNetworkThread());
257 DCHECK(!write_buffer_list_.empty()); 281 DCHECK(pending_write_data_);
258 282
259 JNIEnv* env = base::android::AttachCurrentThread(); 283 JNIEnv* env = base::android::AttachCurrentThread();
260 base::android::ScopedJavaLocalRef<jclass> byte_buffer_clazz(
261 env, env->FindClass("java/nio/ByteBuffer"));
262 size_t size = write_buffer_list_.size();
263 jobjectArray jbuffer_array =
264 env->NewObjectArray(size, byte_buffer_clazz.obj(), NULL);
265 base::android::CheckException(env);
266 std::vector<int> initial_positions;
267 std::vector<int> initial_limits;
268 for (size_t i = 0; i < size; ++i) {
269 env->SetObjectArrayElement(jbuffer_array, i,
270 write_buffer_list_[i]->byte_buffer());
271 initial_positions.push_back(write_buffer_list_[i]->initial_position());
272 initial_limits.push_back(write_buffer_list_[i]->initial_limit());
273 }
274 ScopedJavaLocalRef<jobjectArray> jbuffers(env, jbuffer_array);
275 ScopedJavaLocalRef<jintArray> jinitial_positions =
276 base::android::ToJavaIntArray(env, initial_positions);
277 ScopedJavaLocalRef<jintArray> jinitial_limits =
278 base::android::ToJavaIntArray(env, initial_limits);
mef 2016/05/13 15:12:58 yay!
279 // Call into Java. 284 // Call into Java.
280 cronet::Java_CronetBidirectionalStream_onWritevCompleted( 285 cronet::Java_CronetBidirectionalStream_onWritevCompleted(
281 env, owner_.obj(), jbuffers.obj(), jinitial_positions.obj(), 286 env, owner_.obj(), pending_write_data_->jwrite_buffer_list.obj(),
282 jinitial_limits.obj(), write_end_of_stream_); 287 pending_write_data_->jwrite_buffer_pos_list.obj(),
283 // Free the write buffers. This lets the Java ByteBuffer be freed, if the 288 pending_write_data_->jwrite_buffer_limit_list.obj(),
289 pending_write_data_->jwrite_end_of_stream);
290 // Free the java objects. This lets the Java ByteBuffers be freed, if the
284 // embedder releases it, too. 291 // embedder releases it, too.
285 write_buffer_list_.clear(); 292 pending_write_data_.reset();
286 } 293 }
287 294
288 void CronetBidirectionalStreamAdapter::OnTrailersReceived( 295 void CronetBidirectionalStreamAdapter::OnTrailersReceived(
289 const net::SpdyHeaderBlock& response_trailers) { 296 const net::SpdyHeaderBlock& response_trailers) {
290 DCHECK(context_->IsOnNetworkThread()); 297 DCHECK(context_->IsOnNetworkThread());
291 JNIEnv* env = base::android::AttachCurrentThread(); 298 JNIEnv* env = base::android::AttachCurrentThread();
292 cronet::Java_CronetBidirectionalStream_onResponseTrailersReceived( 299 cronet::Java_CronetBidirectionalStream_onResponseTrailersReceived(
293 env, owner_.obj(), GetHeadersArray(env, response_trailers).obj()); 300 env, owner_.obj(), GetHeadersArray(env, response_trailers).obj());
294 } 301 }
295 302
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 return; 340 return;
334 341
335 if (bytes_read < 0) { 342 if (bytes_read < 0) {
336 OnFailed(bytes_read); 343 OnFailed(bytes_read);
337 return; 344 return;
338 } 345 }
339 OnDataRead(bytes_read); 346 OnDataRead(bytes_read);
340 } 347 }
341 348
342 void CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread( 349 void CronetBidirectionalStreamAdapter::WritevDataOnNetworkThread(
343 const IOBufferWithByteBufferList& write_buffer_list, 350 std::unique_ptr<PendingWriteData> pending_write_data) {
344 bool end_of_stream) {
345 DCHECK(context_->IsOnNetworkThread()); 351 DCHECK(context_->IsOnNetworkThread());
346 DCHECK(write_buffer_list_.empty()); 352 DCHECK(pending_write_data);
347 DCHECK(!write_buffer_list.empty()); 353 DCHECK(!pending_write_data_);
348 DCHECK(!write_end_of_stream_); 354 DCHECK(!write_end_of_stream_);
349 355
350 if (stream_failed_) { 356 if (stream_failed_) {
351 // If stream failed between the time when WritevData is invoked and 357 // If stream failed between the time when WritevData is invoked and
352 // WritevDataOnNetworkThread is executed, do not call into |bidi_stream_| 358 // WritevDataOnNetworkThread is executed, do not call into |bidi_stream_|
353 // since the underlying stream might have been destroyed. Do not invoke 359 // since the underlying stream might have been destroyed. Do not invoke
354 // Java callback either, since onError is posted when |stream_failed_| is 360 // Java callback either, since onError is posted when |stream_failed_| is
355 // set to true. 361 // set to true.
356 return; 362 return;
357 } 363 }
358 364
365 bool end_of_stream = pending_write_data->jwrite_end_of_stream == JNI_TRUE;
366 if (pending_write_data->write_buffer_list.size() == 1) {
367 bidi_stream_->SendData(pending_write_data->write_buffer_list[0],
368 pending_write_data->write_buffer_len_list[0],
369 end_of_stream);
370 } else {
371 bidi_stream_->SendvData(pending_write_data->write_buffer_list,
372 pending_write_data->write_buffer_len_list,
373 end_of_stream);
374 }
375
359 write_end_of_stream_ = end_of_stream; 376 write_end_of_stream_ = end_of_stream;
360 std::vector<net::IOBuffer*> buffers; 377 pending_write_data_ = std::move(pending_write_data);
mef 2016/05/13 15:12:58 should we assign this before calling SendData? IIR
xunjieli 2016/05/16 14:12:28 Done.
361 std::vector<int> lengths;
362 for (const auto& buffer : write_buffer_list) {
363 write_buffer_list_.push_back(buffer);
364 buffers.push_back(buffer.get());
365 lengths.push_back(buffer->initial_limit() - buffer->initial_position());
366 }
367 if (buffers.size() == 1) {
368 bidi_stream_->SendData(buffers[0], lengths[0], end_of_stream);
369 } else {
370 bidi_stream_->SendvData(buffers, lengths, end_of_stream);
371 }
372 } 378 }
373 379
374 void CronetBidirectionalStreamAdapter::DestroyOnNetworkThread( 380 void CronetBidirectionalStreamAdapter::DestroyOnNetworkThread(
375 bool send_on_canceled) { 381 bool send_on_canceled) {
376 DCHECK(context_->IsOnNetworkThread()); 382 DCHECK(context_->IsOnNetworkThread());
377 if (send_on_canceled) { 383 if (send_on_canceled) {
378 JNIEnv* env = base::android::AttachCurrentThread(); 384 JNIEnv* env = base::android::AttachCurrentThread();
379 cronet::Java_CronetBidirectionalStream_onCanceled(env, owner_.obj()); 385 cronet::Java_CronetBidirectionalStream_onCanceled(env, owner_.obj());
380 } 386 }
381 delete this; 387 delete this;
382 } 388 }
383 389
384 base::android::ScopedJavaLocalRef<jobjectArray> 390 base::android::ScopedJavaLocalRef<jobjectArray>
385 CronetBidirectionalStreamAdapter::GetHeadersArray( 391 CronetBidirectionalStreamAdapter::GetHeadersArray(
386 JNIEnv* env, 392 JNIEnv* env,
387 const net::SpdyHeaderBlock& header_block) { 393 const net::SpdyHeaderBlock& header_block) {
388 DCHECK(context_->IsOnNetworkThread()); 394 DCHECK(context_->IsOnNetworkThread());
389 395
390 std::vector<std::string> headers; 396 std::vector<std::string> headers;
391 for (const auto& header : header_block) { 397 for (const auto& header : header_block) {
392 headers.push_back(header.first.as_string()); 398 headers.push_back(header.first.as_string());
393 headers.push_back(header.second.as_string()); 399 headers.push_back(header.second.as_string());
394 } 400 }
395 return base::android::ToJavaArrayOfStrings(env, headers); 401 return base::android::ToJavaArrayOfStrings(env, headers);
396 } 402 }
397 403
398 } // namespace cronet 404 } // namespace cronet
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698