diff options
Diffstat (limited to 'net/dns/serial_worker.cc')
-rw-r--r-- | net/dns/serial_worker.cc | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/net/dns/serial_worker.cc b/net/dns/serial_worker.cc new file mode 100644 index 0000000..d2e42c0 --- /dev/null +++ b/net/dns/serial_worker.cc @@ -0,0 +1,99 @@ +// Copyright (c) 2011 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"; + message_loop_->PostDelayedTask( + FROM_HERE, + base::Bind(&SerialWorker::RetryWork, this), + 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 + |