summaryrefslogtreecommitdiffstats
path: root/net/dns/serial_worker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/dns/serial_worker.cc')
-rw-r--r--net/dns/serial_worker.cc99
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
+