Add ScopedClosureRunner.

BUG=None
TEST=Unittests


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

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


CrOS-Libchrome-Original-Commit: 0b5266df8f10697951e8b8f833f3d941b14258f0
diff --git a/base/task.cc b/base/task.cc
index 8c61473..89d2aa8 100644
--- a/base/task.cc
+++ b/base/task.cc
@@ -34,6 +34,21 @@
   return tmp;
 }
 
+ScopedClosureRunner::ScopedClosureRunner(const Closure& closure)
+    : closure_(closure) {
+}
+
+ScopedClosureRunner::~ScopedClosureRunner() {
+  if (!closure_.is_null())
+    closure_.Run();
+}
+
+Closure ScopedClosureRunner::Release() {
+  Closure result = closure_;
+  closure_.Reset();
+  return result;
+}
+
 namespace subtle {
 
 TaskClosureAdapter::TaskClosureAdapter(Task* task)
diff --git a/base/task.h b/base/task.h
index 4a33de0..69112c1 100644
--- a/base/task.h
+++ b/base/task.h
@@ -7,6 +7,7 @@
 #pragma once
 
 #include "base/base_export.h"
+#include "base/callback.h"
 #include "base/debug/alias.h"
 #include "base/memory/raw_scoped_refptr_mismatch_checker.h"
 #include "base/memory/weak_ptr.h"
@@ -566,6 +567,19 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedTaskRunner);
 };
 
+class BASE_EXPORT ScopedClosureRunner {
+ public:
+  explicit ScopedClosureRunner(const Closure& closure);
+  ~ScopedClosureRunner();
+
+  Closure Release();
+
+ private:
+  Closure closure_;
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedClosureRunner);
+};
+
 namespace subtle {
 
 // This class is meant for use in the implementation of MessageLoop classes
diff --git a/base/task_unittest.cc b/base/task_unittest.cc
index e0cb659..d7d31fa 100644
--- a/base/task_unittest.cc
+++ b/base/task_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/task.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -107,4 +108,30 @@
   EXPECT_TRUE(was_deleted);
 }
 
+void Increment(int* value) {
+  (*value)++;
+}
+
+TEST(TaskTest, TestScopedClosureRunnerExitScope) {
+  int run_count = 0;
+  {
+    base::ScopedClosureRunner runner(base::Bind(Increment, &run_count));
+    EXPECT_EQ(0, run_count);
+  }
+  EXPECT_EQ(1, run_count);
+}
+
+TEST(TaskTest, TestScopedClosureRunnerRelease) {
+  int run_count = 0;
+  base::Closure c;
+  {
+    base::ScopedClosureRunner runner(base::Bind(Increment, &run_count));
+    c = runner.Release();
+    EXPECT_EQ(0, run_count);
+  }
+  EXPECT_EQ(0, run_count);
+  c.Run();
+  EXPECT_EQ(1, run_count);
+}
+
 }  // namespace