15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/dns/serial_worker.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/location.h"
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/worker_pool.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SerialWorker::SerialWorker()
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : message_loop_(base::MessageLoopProxy::current()),
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_(IDLE) {}
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SerialWorker::~SerialWorker() {}
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SerialWorker::WorkNow() {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state_) {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case IDLE:
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!base::WorkerPool::PostTask(FROM_HERE, base::Bind(
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &SerialWorker::DoWorkJob, this), false)) {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // See worker_pool_posix.cc.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "WorkerPool::PostTask is not expected to fail on posix";
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(WARNING) << "Failed to WorkerPool::PostTask, will retry later";
3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        const int kWorkerPoolRetryDelayMs = 100;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        message_loop_->PostDelayedTask(
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FROM_HERE,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::Bind(&SerialWorker::RetryWork, this),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            base::TimeDelta::FromMilliseconds(kWorkerPoolRetryDelayMs));
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        state_ = WAITING;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_ = WORKING;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WORKING:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Remember to re-read after |DoRead| finishes.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_ = PENDING;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CANCELLED:
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PENDING:
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING:
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unexpected state " << state_;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SerialWorker::Cancel() {
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = CANCELLED;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SerialWorker::DoWorkJob() {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  this->DoWork();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If this fails, the loop is gone, so there is no point retrying.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_loop_->PostTask(FROM_HERE, base::Bind(
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &SerialWorker::OnWorkJobFinished, this));
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SerialWorker::OnWorkJobFinished() {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state_) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CANCELLED:
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WORKING:
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_ = IDLE;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this->OnWorkFinished();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case PENDING:
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_ = IDLE;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WorkNow();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unexpected state " << state_;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SerialWorker::RetryWork() {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(message_loop_->BelongsToCurrentThread());
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state_) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case CANCELLED:
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case WAITING:
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_ = IDLE;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WorkNow();
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unexpected state " << state_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
101