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