您的位置:首页 > 其它

谷歌浏览器的源码分析(30)

2008-11-05 22:51 417 查看
上次说到函数WinHttpReadData[/b]接收数据到缓冲区里,那么这些数据又是怎么样传送给下一步处理的呢?带着这个问题,我们来分析下面这段代码,如下:

#001 void HttpTransactionWinHttp::HandleStatusCallback(DWORD status,

#002 DWORD_PTR result,

#003 DWORD error,

#004 DWORD secure_failure) {

#005 int rv = ERR_FAILED;

#006

#007 switch (status) {

#008 case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR:

#009 rv = DidReceiveError(error, secure_failure);

#010 break;

......

#027

#028 if (rv == ERR_IO_PENDING) {

#029 session_callback_->AddRef(); // balanced when callback runs.

#030 } else if (callback_) {

#031 DoCallback(rv);[/b]

#032 }

#033 }

通过上面的函数可以看到,当数据接收完成后,就会调用DoCallback[/b]函数处理接收到的数据。DoCallback[/b]函数的代码如下:

#001 void HttpTransactionWinHttp::DoCallback(int rv) {

#002 DCHECK(rv != ERR_IO_PENDING);

#003 DCHECK(callback_);

#004

#005 // since Run may result in Read being called, clear callback_ up front.

#006 CompletionCallback* c = callback_;[/b]

#007 callback_ = NULL;[/b]

#008 c->Run(rv);[/b]

#009 }

看到这里又是一个回调函数c->Run[/b]的通知,它是调用开始创建这个连接时设置的回调对象。如果是HTTP请求,那么这个请求回调函数是对象URLRequestHttpJob里的函数,也就是调用URLRequestHttpJob::OnReadCompleted函数,这个函数是当数据接收完成,或接收失败,或者接收还没有完成时都会调用。这个函数代码如下:

#001 void URLRequestHttpJob::OnReadCompleted(int result) {

#002 read_in_progress_ = false;

#003

这里是接收数据完成。

#004 if (result == 0) {

#005 NotifyDone(URLRequestStatus());

#006 } else if (result < 0) {

这里是接收数据出错划。

#007 NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));

#008 } else {

这里是接收数据还没有完成。

#009 // Clear the IO_PENDING status

#010 SetStatus(URLRequestStatus());

#011 }

#012

#013 NotifyReadComplete(result);

#014 }

当上面读取数据完成时,就开始把接收到数据通过类ResourceDispatcherHost来发送出去,而类ResourceDispatcherHost发送数据的方式比较特别,它不是通过消息把整块数据用命名管道发送的,而是通过共享内存的方式让另一个进程来读取数据,这样达到速度快的特点,可见可多米处理处理考虑的都是速度,它的代码如下:

#001 bool OnReadCompleted(int request_id, int* bytes_read) {

#002 if (!*bytes_read)

#003 return true;

#004 DCHECK(read_buffer_.get());

#005

#006 if (!rdh_->WillSendData(render_process_host_id_, request_id)) {

#007 // We should not send this data now, we have too many pending requests.

#008 return true;

#009 }

#010

这里创建共享内存。

#011 SharedMemoryHandle handle;

#012 if (!read_buffer_->GiveToProcess(render_process_, &handle)) {

#013 // We wrongfully incremented the pending data count. Fake an ACK message

#014 // to fix this. We can't move this call above the WillSendData because

#015 // it's killing our read_buffer_, and we don't want that when we pause

#016 // the request.

#017 rdh_->OnDataReceivedACK(render_process_host_id_, request_id);

#018 return false;

#019 }

#020

把共享内存通过管道消息发送给渲染进程。

#021 receiver_->Send(new ViewMsg_Resource_DataReceived(

#022 routing_id_, request_id, handle, *bytes_read));

#023

#024 return true;

#025 }

#026

共享内存是使用Windows API函数CreateFileMapping来创建内存共享文件实现的,具体实现方法请参考类SharedMemory的实现。这里既然把消息通过管道发送出去了,那么在另一个线程里肯定就处理的这个消息,下一次再来分析那部份代码。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: