blob: e32a6b4918043cd85e1f786424dd9852d38323a0 [file] [log] [blame]
[email protected]4739f702012-03-20 23:15:101// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]fb2622f2010-07-13 18:00:562// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]c2c5cfc2014-03-03 16:35:285#include "net/disk_cache/blockfile/in_flight_io.h"
[email protected]fb2622f2010-07-13 18:00:566
[email protected]940d11f2011-10-20 00:27:157#include "base/bind.h"
[email protected]c62dd9d2011-09-21 18:05:418#include "base/location.h"
[email protected]81e549a2014-08-21 04:19:559#include "base/single_thread_task_runner.h"
10#include "base/task_runner.h"
[email protected]3a7b66d2012-04-26 16:34:1611#include "base/threading/thread_restrictions.h"
gabf767595f2016-05-11 18:50:3512#include "base/threading/thread_task_runner_handle.h"
[email protected]fb2622f2010-07-13 18:00:5613
14namespace disk_cache {
15
[email protected]d4799a32010-09-28 22:54:5816BackgroundIO::BackgroundIO(InFlightIO* controller)
gab07efd102016-06-02 13:33:1717 : result_(-1),
18 io_completed_(base::WaitableEvent::ResetPolicy::MANUAL,
19 base::WaitableEvent::InitialState::NOT_SIGNALED),
20 controller_(controller) {}
[email protected]d4799a32010-09-28 22:54:5821
[email protected]fb2622f2010-07-13 18:00:5622// Runs on the primary thread.
23void BackgroundIO::OnIOSignalled() {
24 if (controller_)
25 controller_->InvokeCallback(this, false);
26}
27
28void BackgroundIO::Cancel() {
[email protected]4739f702012-03-20 23:15:1029 // controller_ may be in use from the background thread at this time.
30 base::AutoLock lock(controller_lock_);
[email protected]fb2622f2010-07-13 18:00:5631 DCHECK(controller_);
32 controller_ = NULL;
33}
34
Chris Watkins68b15032017-12-01 03:07:1335BackgroundIO::~BackgroundIO() = default;
[email protected]fb2622f2010-07-13 18:00:5636
37// ---------------------------------------------------------------------------
38
[email protected]d4799a32010-09-28 22:54:5839InFlightIO::InFlightIO()
[email protected]81e549a2014-08-21 04:19:5540 : callback_task_runner_(base::ThreadTaskRunnerHandle::Get()),
pkasting83ae339b2016-05-23 22:37:3641 running_(false) {}
[email protected]d4799a32010-09-28 22:54:5842
Chris Watkins68b15032017-12-01 03:07:1343InFlightIO::~InFlightIO() = default;
[email protected]d4799a32010-09-28 22:54:5844
[email protected]4739f702012-03-20 23:15:1045// Runs on the background thread.
46void BackgroundIO::NotifyController() {
47 base::AutoLock lock(controller_lock_);
48 if (controller_)
49 controller_->OnIOComplete(this);
50}
51
[email protected]fb2622f2010-07-13 18:00:5652void InFlightIO::WaitForPendingIO() {
53 while (!io_list_.empty()) {
54 // Block the current thread until all pending IO completes.
jdoerrie22a91d8b92018-10-05 08:43:2655 auto it = io_list_.begin();
[email protected]90499482013-06-01 00:39:5056 InvokeCallback(it->get(), true);
[email protected]fb2622f2010-07-13 18:00:5657 }
58}
59
[email protected]4739f702012-03-20 23:15:1060void InFlightIO::DropPendingIO() {
61 while (!io_list_.empty()) {
jdoerrie22a91d8b92018-10-05 08:43:2662 auto it = io_list_.begin();
[email protected]90499482013-06-01 00:39:5063 BackgroundIO* operation = it->get();
[email protected]4739f702012-03-20 23:15:1064 operation->Cancel();
65 DCHECK(io_list_.find(operation) != io_list_.end());
kylecharda69d882017-10-04 05:49:5266 io_list_.erase(base::WrapRefCounted(operation));
[email protected]4739f702012-03-20 23:15:1067 }
68}
69
peary2aeac77802017-06-01 04:11:1670// Runs in a background sequence.
[email protected]fb2622f2010-07-13 18:00:5671void InFlightIO::OnIOComplete(BackgroundIO* operation) {
pkasting83ae339b2016-05-23 22:37:3672#if DCHECK_IS_ON()
peary2aeac77802017-06-01 04:11:1673 if (callback_task_runner_->RunsTasksInCurrentSequence()) {
[email protected]fb2622f2010-07-13 18:00:5674 DCHECK(single_thread_ || !running_);
75 single_thread_ = true;
76 }
[email protected]fb2622f2010-07-13 18:00:5677#endif
78
[email protected]81e549a2014-08-21 04:19:5579 callback_task_runner_->PostTask(
kylecharf4fe5172019-02-15 18:53:4980 FROM_HERE, base::BindOnce(&BackgroundIO::OnIOSignalled, operation));
[email protected]fb2622f2010-07-13 18:00:5681 operation->io_completed()->Signal();
82}
83
84// Runs on the primary thread.
85void InFlightIO::InvokeCallback(BackgroundIO* operation, bool cancel_task) {
[email protected]3a7b66d2012-04-26 16:34:1686 {
87 // http://crbug.com/74623
Etienne Pierre-doray22c3f922018-11-12 23:54:1088 base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
[email protected]3a7b66d2012-04-26 16:34:1689 operation->io_completed()->Wait();
90 }
[email protected]ec14a182011-06-21 00:27:5491 running_ = true;
[email protected]fb2622f2010-07-13 18:00:5692
93 if (cancel_task)
94 operation->Cancel();
95
96 // Make sure that we remove the operation from the list before invoking the
97 // callback (so that a subsequent cancel does not invoke the callback again).
98 DCHECK(io_list_.find(operation) != io_list_.end());
[email protected]15f5db62012-03-23 22:14:2499 DCHECK(!operation->HasOneRef());
kylecharda69d882017-10-04 05:49:52100 io_list_.erase(base::WrapRefCounted(operation));
[email protected]fb2622f2010-07-13 18:00:56101 OnOperationComplete(operation, cancel_task);
102}
103
104// Runs on the primary thread.
105void InFlightIO::OnOperationPosted(BackgroundIO* operation) {
peary2aeac77802017-06-01 04:11:16106 DCHECK(callback_task_runner_->RunsTasksInCurrentSequence());
kylecharda69d882017-10-04 05:49:52107 io_list_.insert(base::WrapRefCounted(operation));
[email protected]fb2622f2010-07-13 18:00:56108}
109
110} // namespace disk_cache