1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/disk_cache/in_flight_io.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h"
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace disk_cache {
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
113345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickBackgroundIO::BackgroundIO(InFlightIO* controller)
123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : controller_(controller), result_(-1), io_completed_(true, false) {
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Runs on the primary thread.
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackgroundIO::OnIOSignalled() {
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (controller_)
18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    controller_->InvokeCallback(this, false);
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackgroundIO::Cancel() {
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(controller_);
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  controller_ = NULL;
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickBackgroundIO::~BackgroundIO() {}
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Runs on the background thread.
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BackgroundIO::NotifyController() {
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  controller_->OnIOComplete(this);
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ---------------------------------------------------------------------------
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
353345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickInFlightIO::InFlightIO()
363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    : callback_thread_(base::MessageLoopProxy::CreateForCurrentThread()),
373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      running_(false), single_thread_(false) {
383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
403345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickInFlightIO::~InFlightIO() {
413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid InFlightIO::WaitForPendingIO() {
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (!io_list_.empty()) {
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Block the current thread until all pending IO completes.
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    IOList::iterator it = io_list_.begin();
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    InvokeCallback(*it, true);
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Runs on a background thread.
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid InFlightIO::OnIOComplete(BackgroundIO* operation) {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifndef NDEBUG
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (callback_thread_->BelongsToCurrentThread()) {
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK(single_thread_ || !running_);
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    single_thread_ = true;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  running_ = true;
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  callback_thread_->PostTask(FROM_HERE,
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             NewRunnableMethod(operation,
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                               &BackgroundIO::OnIOSignalled));
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  operation->io_completed()->Signal();
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Runs on the primary thread.
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid InFlightIO::InvokeCallback(BackgroundIO* operation, bool cancel_task) {
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  operation->io_completed()->Wait();
70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cancel_task)
72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    operation->Cancel();
73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure that we remove the operation from the list before invoking the
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // callback (so that a subsequent cancel does not invoke the callback again).
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(io_list_.find(operation) != io_list_.end());
77513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  io_list_.erase(make_scoped_refptr(operation));
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  OnOperationComplete(operation, cancel_task);
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Runs on the primary thread.
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid InFlightIO::OnOperationPosted(BackgroundIO* operation) {
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(callback_thread_->BelongsToCurrentThread());
84513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  io_list_.insert(make_scoped_refptr(operation));
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace disk_cache
88