blob: 980f68512b48fe53d1f3dc4bd65040855cc7552f [file] [log] [blame]
[email protected]cb507622012-03-23 16:17:061// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]76d7f722011-10-10 17:22:412// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/dns/serial_worker.h"
6
Eric Orth8ec1b8e2021-10-11 19:33:477#include <memory>
Eric Orth88a6aaa2021-10-19 17:20:568#include <utility>
Eric Orth8ec1b8e2021-10-11 19:33:479
[email protected]76d7f722011-10-10 17:22:4110#include "base/bind.h"
Eric Orth88a6aaa2021-10-19 17:20:5611#include "base/callback.h"
Hans Wennborg0924470b2020-04-27 21:08:0512#include "base/check_op.h"
[email protected]76d7f722011-10-10 17:22:4113#include "base/location.h"
Hans Wennborg0924470b2020-04-27 21:08:0514#include "base/notreached.h"
Gabriel Charette44db1422018-08-06 11:19:3315#include "base/task/post_task.h"
Gabriel Charetted5c656c2020-02-26 16:35:2216#include "base/task/thread_pool.h"
Robbie McElrath31391ba2018-11-15 02:04:5017#include "base/threading/sequenced_task_runner_handle.h"
gabf767595f2016-05-11 18:50:3518#include "base/threading/thread_task_runner_handle.h"
[email protected]76d7f722011-10-10 17:22:4119
20namespace net {
21
Eric Orth8ec1b8e2021-10-11 19:33:4722namespace {
23std::unique_ptr<SerialWorker::WorkItem> DoWork(
24 std::unique_ptr<SerialWorker::WorkItem> work_item) {
25 DCHECK(work_item);
26 work_item->DoWork();
27 return work_item;
28}
29} // namespace
30
Eric Orth88a6aaa2021-10-19 17:20:5631void SerialWorker::WorkItem::FollowupWork(base::OnceClosure closure) {
32 std::move(closure).Run();
33}
34
Eric Orth8ec1b8e2021-10-11 19:33:4735SerialWorker::SerialWorker() : state_(State::kIdle) {}
[email protected]76d7f722011-10-10 17:22:4136
Chris Watkins68b15032017-12-01 03:07:1337SerialWorker::~SerialWorker() = default;
[email protected]76d7f722011-10-10 17:22:4138
39void SerialWorker::WorkNow() {
Francois Doraybecd1ef72017-09-25 20:58:4540 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]76d7f722011-10-10 17:22:4141 switch (state_) {
Peter Kastingd039b772021-08-18 00:06:2042 case State::kIdle:
Erik Andersonc243d712021-07-30 00:13:4143 // We are posting weak pointer to OnWorkJobFinished to avoid leak when
Sami Kyostila0b4314e2019-07-31 20:47:1744 // PostTaskAndReply fails to post task back to the original
Leonid Kaplan24c51bc2018-09-04 13:23:1645 // task runner. In this case the callback is not destroyed, and the
46 // weak reference allows SerialWorker instance to be deleted.
Eric Orth8ec1b8e2021-10-11 19:33:4747 base::ThreadPool::PostTaskAndReplyWithResult(
Gabriel Charetted5c656c2020-02-26 16:35:2248 FROM_HERE,
49 {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
Eric Orth8ec1b8e2021-10-11 19:33:4750 base::BindOnce(&DoWork, CreateWorkItem()),
Eric Orth88a6aaa2021-10-19 17:20:5651 base::BindOnce(&SerialWorker::OnDoWorkFinished, AsWeakPtr()));
Peter Kastingd039b772021-08-18 00:06:2052 state_ = State::kWorking;
[email protected]76d7f722011-10-10 17:22:4153 return;
Peter Kastingd039b772021-08-18 00:06:2054 case State::kWorking:
Eric Orth8ec1b8e2021-10-11 19:33:4755 // Remember to re-read after `DoWork()` finishes.
Peter Kastingd039b772021-08-18 00:06:2056 state_ = State::kPending;
[email protected]76d7f722011-10-10 17:22:4157 return;
Peter Kastingd039b772021-08-18 00:06:2058 case State::kCancelled:
59 case State::kPending:
[email protected]76d7f722011-10-10 17:22:4160 return;
[email protected]76d7f722011-10-10 17:22:4161 }
62}
63
64void SerialWorker::Cancel() {
Francois Doraybecd1ef72017-09-25 20:58:4565 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Peter Kastingd039b772021-08-18 00:06:2066 state_ = State::kCancelled;
[email protected]76d7f722011-10-10 17:22:4167}
Erik Andersonc243d712021-07-30 00:13:4168
Eric Orth88a6aaa2021-10-19 17:20:5669void SerialWorker::OnDoWorkFinished(std::unique_ptr<WorkItem> work_item) {
70 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
71
72 switch (state_) {
73 case State::kCancelled:
74 return;
75 case State::kWorking: {
76 WorkItem* work_item_ptr = work_item.get();
77 work_item_ptr->FollowupWork(
78 base::BindOnce(&SerialWorker::OnFollowupWorkFinished,
79 weak_factory_.GetWeakPtr(), std::move(work_item)));
80 return;
81 }
82 case State::kPending: {
83 RerunWork(std::move(work_item));
84 return;
85 }
86 default:
87 NOTREACHED() << "Unexpected state " << static_cast<int>(state_);
88 }
89}
90
91void SerialWorker::OnFollowupWorkFinished(std::unique_ptr<WorkItem> work_item) {
Francois Doraybecd1ef72017-09-25 20:58:4592 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
[email protected]76d7f722011-10-10 17:22:4193 switch (state_) {
Peter Kastingd039b772021-08-18 00:06:2094 case State::kCancelled:
[email protected]76d7f722011-10-10 17:22:4195 return;
Peter Kastingd039b772021-08-18 00:06:2096 case State::kWorking:
97 state_ = State::kIdle;
Eric Orth8ec1b8e2021-10-11 19:33:4798 OnWorkFinished(std::move(work_item));
[email protected]76d7f722011-10-10 17:22:4199 return;
Peter Kastingd039b772021-08-18 00:06:20100 case State::kPending:
Eric Orth88a6aaa2021-10-19 17:20:56101 RerunWork(std::move(work_item));
[email protected]76d7f722011-10-10 17:22:41102 return;
103 default:
Peter Kastingd039b772021-08-18 00:06:20104 NOTREACHED() << "Unexpected state " << static_cast<int>(state_);
[email protected]76d7f722011-10-10 17:22:41105 }
106}
107
Eric Orth88a6aaa2021-10-19 17:20:56108void SerialWorker::RerunWork(std::unique_ptr<WorkItem> work_item) {
109 // `WorkNow()` was retriggered while working, so need to redo work
110 // immediately to ensure up-to-date results. Reuse `work_item` rather than
111 // returning it to the derived class (and letting it potentially act on a
112 // potential obsolete result).
113 DCHECK_EQ(state_, State::kPending);
114 state_ = State::kWorking;
115 base::ThreadPool::PostTaskAndReplyWithResult(
116 FROM_HERE,
117 {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
118 base::BindOnce(&DoWork, std::move(work_item)),
119 base::BindOnce(&SerialWorker::OnDoWorkFinished, AsWeakPtr()));
120}
121
Eric Orth8ec1b8e2021-10-11 19:33:47122base::WeakPtr<SerialWorker> SerialWorker::AsWeakPtr() {
123 return weak_factory_.GetWeakPtr();
124}
125
[email protected]76d7f722011-10-10 17:22:41126} // namespace net