summaryrefslogtreecommitdiffstats
path: root/net/http/http_cache.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/http/http_cache.cc')
-rw-r--r--net/http/http_cache.cc52
1 files changed, 35 insertions, 17 deletions
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index 45094fc..383818c 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -105,12 +105,16 @@ class HttpCache::WorkItem {
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 @@ HttpCache::~HttpCache() {
// 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,39 @@ void HttpCache::OnBackendCreated(int result, PendingOp* pending_op) {
WorkItemOperation op = item->operation();
DCHECK_EQ(WI_CREATE_BACKEND, op);
- backend_factory_.reset(); // Reclaim memory.
-
- if (result == OK)
- disk_cache_.reset(temp_backend_);
+ // We don't need the callback anymore.
+ pending_op->callback = NULL;
- item->DoCallback(result, temp_backend_);
+ if (backend_factory_.get()) {
+ // We may end up calling OnBackendCreated multiple times if we have pending
+ // work items. The first call saves the backend and releases the factory,
+ // and the last call clears building_backend_.
+ backend_factory_.reset(); // Reclaim memory.
+ if (result == OK)
+ disk_cache_.reset(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));
+ } 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