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/message_loop/message_loop_proxy.h" 10 #include "base/threading/worker_pool.h" 11 12 namespace net { 13 14 namespace { 15 // Delay between calls to WorkerPool::PostTask 16 const int kWorkerPoolRetryDelayMs = 100; 17 } 18 19 SerialWorker::SerialWorker() 20 : message_loop_(base::MessageLoopProxy::current()), 21 state_(IDLE) {} 22 23 SerialWorker::~SerialWorker() {} 24 25 void SerialWorker::WorkNow() { 26 DCHECK(message_loop_->BelongsToCurrentThread()); 27 switch (state_) { 28 case IDLE: 29 if (!base::WorkerPool::PostTask(FROM_HERE, base::Bind( 30 &SerialWorker::DoWorkJob, this), false)) { 31 #if defined(OS_POSIX) 32 // See worker_pool_posix.cc. 33 NOTREACHED() << "WorkerPool::PostTask is not expected to fail on posix"; 34 #else 35 LOG(WARNING) << "Failed to WorkerPool::PostTask, will retry later"; 36 message_loop_->PostDelayedTask( 37 FROM_HERE, 38 base::Bind(&SerialWorker::RetryWork, this), 39 base::TimeDelta::FromMilliseconds(kWorkerPoolRetryDelayMs)); 40 state_ = WAITING; 41 return; 42 #endif 43 } 44 state_ = WORKING; 45 return; 46 case WORKING: 47 // Remember to re-read after |DoRead| finishes. 48 state_ = PENDING; 49 return; 50 case CANCELLED: 51 case PENDING: 52 case WAITING: 53 return; 54 default: 55 NOTREACHED() << "Unexpected state " << state_; 56 } 57 } 58 59 void SerialWorker::Cancel() { 60 DCHECK(message_loop_->BelongsToCurrentThread()); 61 state_ = CANCELLED; 62 } 63 64 void SerialWorker::DoWorkJob() { 65 this->DoWork(); 66 // If this fails, the loop is gone, so there is no point retrying. 67 message_loop_->PostTask(FROM_HERE, base::Bind( 68 &SerialWorker::OnWorkJobFinished, this)); 69 } 70 71 void SerialWorker::OnWorkJobFinished() { 72 DCHECK(message_loop_->BelongsToCurrentThread()); 73 switch (state_) { 74 case CANCELLED: 75 return; 76 case WORKING: 77 state_ = IDLE; 78 this->OnWorkFinished(); 79 return; 80 case PENDING: 81 state_ = IDLE; 82 WorkNow(); 83 return; 84 default: 85 NOTREACHED() << "Unexpected state " << state_; 86 } 87 } 88 89 void SerialWorker::RetryWork() { 90 DCHECK(message_loop_->BelongsToCurrentThread()); 91 switch (state_) { 92 case CANCELLED: 93 return; 94 case WAITING: 95 state_ = IDLE; 96 WorkNow(); 97 return; 98 default: 99 NOTREACHED() << "Unexpected state " << state_; 100 } 101 } 102 103 } // namespace net 104 105