Chromium Code Reviews| Index: net/http/http_cache.cc |
| =================================================================== |
| --- net/http/http_cache.cc (revision 56707) |
| +++ net/http/http_cache.cc (working copy) |
| @@ -105,12 +105,16 @@ |
| trans_->io_callback()->Run(result); |
| } |
| - // Notifies the caller about the operation completion. |
| - void DoCallback(int result, disk_cache::Backend* backend) { |
| + // Notifies the caller about the operation completion. Returns true if the |
| + // callback was invoked. |
| + bool DoCallback(int result, disk_cache::Backend* backend) { |
| if (backend_) |
| *backend_ = backend; |
| - if (callback_) |
| + if (callback_) { |
| callback_->Run(result); |
| + return true; |
| + } |
| + return false; |
| } |
| WorkItemOperation operation() { return operation_; } |
| @@ -298,7 +302,8 @@ |
| // deliver the callbacks. |
| BackendCallback* callback = |
| static_cast<BackendCallback*>(pending_op->callback); |
| - callback->Cancel(); |
| + if (callback) |
| + callback->Cancel(); |
| } else { |
| delete pending_op->callback; |
| } |
| @@ -1009,26 +1014,36 @@ |
| WorkItemOperation op = item->operation(); |
| DCHECK_EQ(WI_CREATE_BACKEND, op); |
| - backend_factory_.reset(); // Reclaim memory. |
| + // We don't need the callback anymore. |
| + pending_op->callback = NULL; |
| - if (result == OK) |
| - disk_cache_.reset(temp_backend_); |
| + if (backend_factory_.get()) { |
|
eroman
2010/08/20 18:15:23
Can you add a comment explaining this check is bec
rvargas (doing something else)
2010/08/20 18:47:38
Added:
// We may end up calling OnBackendCreated m
|
| + backend_factory_.reset(); // Reclaim memory. |
| + if (result == OK) |
| + disk_cache_.reset(temp_backend_); |
| + } |
| - item->DoCallback(result, temp_backend_); |
| - |
| - // Notify all callers and delete all pending work items. |
| - while (!pending_op->pending_queue.empty()) { |
| - scoped_ptr<WorkItem> pending_item(pending_op->pending_queue.front()); |
| + if (!pending_op->pending_queue.empty()) { |
| + WorkItem* pending_item = pending_op->pending_queue.front(); |
| pending_op->pending_queue.pop_front(); |
| DCHECK_EQ(WI_CREATE_BACKEND, pending_item->operation()); |
| - // This could be an external caller or a transaction waiting on Start(). |
| - pending_item->DoCallback(result, temp_backend_); |
| - pending_item->NotifyTransaction(result, NULL); |
| + // We want to process a single callback at a time, because the cache may |
| + // go away from the callback. |
| + pending_op->writer = pending_item; |
| + |
| + MessageLoop::current()->PostTask( |
| + FROM_HERE, |
| + task_factory_.NewRunnableMethod(&HttpCache::OnBackendCreated, |
| + result, pending_op)); |
|
eroman
2010/08/20 18:15:23
Won't this leak pending_op if HttpCache gets delet
rvargas (doing something else)
2010/08/20 18:47:38
No, it doesn't. pending_op is part of a list that
eroman
2010/08/20 18:56:38
Ah my bad. LGTM
|
| + } else { |
| + building_backend_ = false; |
| + DeletePendingOp(pending_op); |
| } |
| - DeletePendingOp(pending_op); |
| - building_backend_ = false; |
| + // The cache may be gone when we return from the callback. |
| + if (!item->DoCallback(result, temp_backend_)) |
| + item->NotifyTransaction(result, NULL); |
| } |
| } // namespace net |