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 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