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 12namespace net { 13 14namespace { 15 // Delay between calls to WorkerPool::PostTask 16 const int kWorkerPoolRetryDelayMs = 100; 17} 18 19SerialWorker::SerialWorker() 20 : message_loop_(base::MessageLoopProxy::current()), 21 state_(IDLE) {} 22 23SerialWorker::~SerialWorker() {} 24 25void 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 59void SerialWorker::Cancel() { 60 DCHECK(message_loop_->BelongsToCurrentThread()); 61 state_ = CANCELLED; 62} 63 64void 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 71void 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 89void 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