1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // 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 
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/task/post_task.h"
10 #include "base/task/thread_pool.h"
11 #include "base/threading/sequenced_task_runner_handle.h"
12 #include "base/threading/thread_task_runner_handle.h"
13 
14 namespace net {
15 
SerialWorker()16 SerialWorker::SerialWorker()
17     : base::RefCountedDeleteOnSequence<SerialWorker>(
18           base::SequencedTaskRunnerHandle::Get()),
19       state_(IDLE) {}
20 
21 SerialWorker::~SerialWorker() = default;
22 
WorkNow()23 void SerialWorker::WorkNow() {
24   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
25   switch (state_) {
26     case IDLE:
27       // We are posting weak pointer to OnWorkJobFinished to avoid leak when
28       // PostTaskAndReply fails to post task back to the original
29       // task runner. In this case the callback is not destroyed, and the
30       // weak reference allows SerialWorker instance to be deleted.
31       base::ThreadPool::PostTaskAndReply(
32           FROM_HERE,
33           {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
34           base::BindOnce(&SerialWorker::DoWork, this),
35           base::BindOnce(&SerialWorker::OnWorkJobFinished,
36                          weak_factory_.GetWeakPtr()));
37       state_ = WORKING;
38       return;
39     case WORKING:
40       // Remember to re-read after |DoRead| finishes.
41       state_ = PENDING;
42       return;
43     case CANCELLED:
44     case PENDING:
45       return;
46     default:
47       NOTREACHED() << "Unexpected state " << state_;
48   }
49 }
50 
Cancel()51 void SerialWorker::Cancel() {
52   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
53   state_ = CANCELLED;
54 }
55 
OnWorkJobFinished()56 void SerialWorker::OnWorkJobFinished() {
57   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
58   switch (state_) {
59     case CANCELLED:
60       return;
61     case WORKING:
62       state_ = IDLE;
63       this->OnWorkFinished();
64       return;
65     case PENDING:
66       state_ = IDLE;
67       WorkNow();
68       return;
69     default:
70       NOTREACHED() << "Unexpected state " << state_;
71   }
72 }
73 
74 }  // namespace net
75