Move media library AutoTaskRunner to base and rename ScopedTaskRunner.

This is needed to avoid faux dependencies on media/ creeping in to remoting/ code, and creating linker issues.

BUG=
TEST=Everything works as before.


Review URL: http://codereview.chromium.org/7062013

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86971 0039d316-1c4b-4281-b951-d872f2087c98


CrOS-Libchrome-Original-Commit: c9c0d079c24a02f8f9b667f3cbf06d234a586625
diff --git a/base/task.cc b/base/task.cc
index d33f3e1..e4da547 100644
--- a/base/task.cc
+++ b/base/task.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// 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.
 
@@ -15,3 +15,23 @@
 
 CancelableTask::~CancelableTask() {
 }
+
+namespace base {
+
+ScopedTaskRunner::ScopedTaskRunner(Task* task) : task_(task) {
+}
+
+ScopedTaskRunner::~ScopedTaskRunner() {
+  if (task_) {
+    task_->Run();
+    delete task_;
+  }
+}
+
+Task* ScopedTaskRunner::Release() {
+  Task* tmp = task_;
+  task_ = NULL;
+  return tmp;
+}
+
+}  // namespace base
diff --git a/base/task.h b/base/task.h
index b698576..a415b58 100644
--- a/base/task.h
+++ b/base/task.h
@@ -546,4 +546,24 @@
       function, MakeTuple(a, b, c, d, e, f, g, h));
 }
 
+namespace base {
+
+// ScopedTaskRunner is akin to scoped_ptr for Tasks.  It ensures that the Task
+// is executed and deleted no matter how the current scope exits.
+class ScopedTaskRunner {
+ public:
+  // Takes ownership of the task.
+  explicit ScopedTaskRunner(Task* task);
+  ~ScopedTaskRunner();
+
+  Task* Release();
+
+ private:
+  Task* task_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedTaskRunner);
+};
+
+}  // namespace base
+
 #endif  // BASE_TASK_H_
diff --git a/base/task_unittest.cc b/base/task_unittest.cc
index 25c201d..e0cb659 100644
--- a/base/task_unittest.cc
+++ b/base/task_unittest.cc
@@ -49,4 +49,62 @@
   delete cancelable_task;
 }
 
+class DoneTask : public Task {
+ public:
+  DoneTask(int* run_count, bool* was_deleted)
+      : run_count_(run_count), was_deleted_(was_deleted) {
+  }
+  virtual ~DoneTask() {
+    *was_deleted_ = true;
+  }
+
+  virtual void Run() {
+    ++(*run_count_);
+  }
+
+  int* run_count_;
+  bool* was_deleted_;
+};
+
+TEST(TaskTest, TestScopedTaskRunnerExitScope) {
+  int run_count = 0;
+  bool was_deleted = false;
+  {
+    base::ScopedTaskRunner runner(new DoneTask(&run_count, &was_deleted));
+    EXPECT_EQ(0, run_count);
+  }
+  EXPECT_EQ(1, run_count);
+  EXPECT_TRUE(was_deleted);
+}
+
+TEST(TaskTest, TestScopedTaskRunnerRelease) {
+  int run_count = 0;
+  bool was_deleted = false;
+  {
+    base::ScopedTaskRunner runner(new DoneTask(&run_count, &was_deleted));
+    delete runner.Release();
+    EXPECT_TRUE(was_deleted);
+  }
+  EXPECT_EQ(0, run_count);
+}
+
+TEST(TaskTest, TestScopedTaskRunnerManualRun) {
+  int run_count = 0;
+  Task* done_task = NULL;
+  bool was_deleted = false;
+  {
+    base::ScopedTaskRunner runner(new DoneTask(&run_count, &was_deleted));
+    done_task = runner.Release();
+    EXPECT_TRUE(NULL != done_task);
+    EXPECT_FALSE(was_deleted);
+    EXPECT_EQ(0, run_count);
+    done_task->Run();
+    EXPECT_FALSE(was_deleted);
+    EXPECT_EQ(1, run_count);
+  }
+  EXPECT_EQ(1, run_count);
+  delete done_task;
+  EXPECT_TRUE(was_deleted);
+}
+
 }  // namespace