| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/dns/serial_worker.h" |
| |
| #include "base/bind.h" |
| #include "base/location.h" |
| #include "base/message_loop_proxy.h" |
| #include "base/threading/worker_pool.h" |
| |
| namespace net { |
| |
| SerialWorker::SerialWorker() |
| : message_loop_(base::MessageLoopProxy::current()), |
| state_(IDLE) {} |
| |
| SerialWorker::~SerialWorker() {} |
| |
| void SerialWorker::WorkNow() { |
| DCHECK(message_loop_->BelongsToCurrentThread()); |
| switch (state_) { |
| case IDLE: |
| if (!base::WorkerPool::PostTask(FROM_HERE, base::Bind( |
| &SerialWorker::DoWorkJob, this), false)) { |
| #if defined(OS_POSIX) |
| // See worker_pool_posix.cc. |
| NOTREACHED() << "WorkerPool::PostTask is not expected to fail on posix"; |
| #else |
| LOG(WARNING) << "Failed to WorkerPool::PostTask, will retry later"; |
| const int kWorkerPoolRetryDelayMs = 100; |
| message_loop_->PostDelayedTask( |
| FROM_HERE, |
| base::Bind(&SerialWorker::RetryWork, this), |
| base::TimeDelta::FromMilliseconds(kWorkerPoolRetryDelayMs)); |
| state_ = WAITING; |
| return; |
| #endif |
| } |
| state_ = WORKING; |
| return; |
| case WORKING: |
| // Remember to re-read after |DoRead| finishes. |
| state_ = PENDING; |
| return; |
| case CANCELLED: |
| case PENDING: |
| case WAITING: |
| return; |
| default: |
| NOTREACHED() << "Unexpected state " << state_; |
| } |
| } |
| |
| void SerialWorker::Cancel() { |
| DCHECK(message_loop_->BelongsToCurrentThread()); |
| state_ = CANCELLED; |
| } |
| |
| void SerialWorker::DoWorkJob() { |
| this->DoWork(); |
| // If this fails, the loop is gone, so there is no point retrying. |
| message_loop_->PostTask(FROM_HERE, base::Bind( |
| &SerialWorker::OnWorkJobFinished, this)); |
| } |
| |
| void SerialWorker::OnWorkJobFinished() { |
| DCHECK(message_loop_->BelongsToCurrentThread()); |
| switch (state_) { |
| case CANCELLED: |
| return; |
| case WORKING: |
| state_ = IDLE; |
| this->OnWorkFinished(); |
| return; |
| case PENDING: |
| state_ = IDLE; |
| WorkNow(); |
| return; |
| default: |
| NOTREACHED() << "Unexpected state " << state_; |
| } |
| } |
| |
| void SerialWorker::RetryWork() { |
| DCHECK(message_loop_->BelongsToCurrentThread()); |
| switch (state_) { |
| case CANCELLED: |
| return; |
| case WAITING: |
| state_ = IDLE; |
| WorkNow(); |
| return; |
| default: |
| NOTREACHED() << "Unexpected state " << state_; |
| } |
| } |
| |
| } // namespace net |
| |