summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-15 01:43:19 +0000
committerakalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-15 01:43:19 +0000
commit6b28d9469f63df13c9918d5f2d8d24ba8b9893a5 (patch)
tree195a09586b5388359914e63ebeca1aa66a2516fe
parent1005065913ee5ced3fd8fc915d31e0c0461e2b1d (diff)
downloadchromium_src-6b28d9469f63df13c9918d5f2d8d24ba8b9893a5.zip
chromium_src-6b28d9469f63df13c9918d5f2d8d24ba8b9893a5.tar.gz
chromium_src-6b28d9469f63df13c9918d5f2d8d24ba8b9893a5.tar.bz2
Make new TaskRunner, SequencedTaskRunner, and SingleThreadTaskRunner interfaces
TaskRunner just has Post{,Delayed}Task(), SequencedTaskRunner extends Executor to have ordering guarantees and PostNonNestable{,Delayed}Task(), and SingleThreadTaskRunner extends SequencedTaskRunner and guarantees execution on a single thread. Move a bunch of methods from MessageLoopProxy into the TaskRunner classes and make it inherit from SingleThreadTaskRunner. BUG=110973 TEST= Review URL: https://chromiumcodereview.appspot.com/9169037 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@121999 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/base.gypi7
-rw-r--r--base/message_loop.h6
-rw-r--r--base/message_loop_helpers.h99
-rw-r--r--base/message_loop_proxy.cc51
-rw-r--r--base/message_loop_proxy.h123
-rw-r--r--base/message_loop_proxy_impl.cc12
-rw-r--r--base/message_loop_proxy_impl.h6
-rw-r--r--base/sequenced_task_runner.cc31
-rw-r--r--base/sequenced_task_runner.h156
-rw-r--r--base/sequenced_task_runner_helpers.h113
-rw-r--r--base/single_thread_task_runner.h38
-rw-r--r--base/task_runner.cc68
-rw-r--r--base/task_runner.h155
-rw-r--r--content/browser/browser_thread_impl.cc20
-rw-r--r--remoting/base/plugin_message_loop_proxy.cc15
-rw-r--r--remoting/base/plugin_message_loop_proxy.h8
16 files changed, 592 insertions, 316 deletions
diff --git a/base/base.gypi b/base/base.gypi
index 36400ed..693f393 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -187,6 +187,7 @@
'memory/weak_ptr.h',
'message_loop.cc',
'message_loop.h',
+ 'message_loop_helpers.h',
'message_loop_proxy.cc',
'message_loop_proxy.h',
'message_loop_proxy_impl.cc',
@@ -252,6 +253,9 @@
'scoped_native_library.h',
'scoped_temp_dir.cc',
'scoped_temp_dir.h',
+ 'sequenced_task_runner.cc',
+ 'sequenced_task_runner.h',
+ 'sequenced_task_runner_helpers.h',
'sha1.h',
'sha1_portable.cc',
'sha1_win.cc',
@@ -259,6 +263,7 @@
'shared_memory_android.cc',
'shared_memory_posix.cc',
'shared_memory_win.cc',
+ 'single_thread_task_runner.h',
'spin_wait.h',
'stack_container.h',
'stl_util.h',
@@ -311,6 +316,8 @@
'sys_string_conversions_mac.mm',
'sys_string_conversions_posix.cc',
'sys_string_conversions_win.cc',
+ 'task_runner.cc',
+ 'task_runner.h',
'template_util.h',
'threading/non_thread_safe.h',
'threading/non_thread_safe_impl.cc',
diff --git a/base/message_loop.h b/base/message_loop.h
index f940502..355d58b 100644
--- a/base/message_loop.h
+++ b/base/message_loop.h
@@ -14,11 +14,11 @@
#include "base/callback_forward.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop_helpers.h"
#include "base/message_loop_proxy.h"
#include "base/message_pump.h"
#include "base/observer_list.h"
#include "base/pending_task.h"
+#include "base/sequenced_task_runner_helpers.h"
#include "base/synchronization/lock.h"
#include "base/tracking_info.h"
#include "base/time.h"
@@ -199,7 +199,7 @@ class BASE_EXPORT MessageLoop : public base::MessagePump::Delegate {
// from RefCountedThreadSafe<T>!
template <class T>
void DeleteSoon(const tracked_objects::Location& from_here, const T* object) {
- base::subtle::DeleteHelperInternal<T, void>::DeleteOnMessageLoop(
+ base::subtle::DeleteHelperInternal<T, void>::DeleteViaSequencedTaskRunner(
this, from_here, object);
}
@@ -216,7 +216,7 @@ class BASE_EXPORT MessageLoop : public base::MessagePump::Delegate {
template <class T>
void ReleaseSoon(const tracked_objects::Location& from_here,
const T* object) {
- base::subtle::ReleaseHelperInternal<T, void>::ReleaseOnMessageLoop(
+ base::subtle::ReleaseHelperInternal<T, void>::ReleaseViaSequencedTaskRunner(
this, from_here, object);
}
diff --git a/base/message_loop_helpers.h b/base/message_loop_helpers.h
index 9aeaad7..931f02d 100644
--- a/base/message_loop_helpers.h
+++ b/base/message_loop_helpers.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -6,99 +6,8 @@
#define BASE_MESSAGE_LOOP_HELPERS_H_
#pragma once
-#include "base/basictypes.h"
-
-namespace tracked_objects {
-class Location;
-}
-
-namespace base {
-
-namespace subtle {
-template <class T, class R> class DeleteHelperInternal;
-template <class T, class R> class ReleaseHelperInternal;
-}
-
-// Template helpers which use a function indirection to erase T from the
-// function signature while still remembering it so we can call the correct
-// destructor/release function.
-// We use this trick so we don't need to include bind.h in a header file like
-// message_loop.h. We also wrap the helpers in a templated class to make it
-// easier for users of DeleteSoon to declare the helper as a friend.
-template <class T>
-class DeleteHelper {
- private:
- template <class T2, class R> friend class subtle::DeleteHelperInternal;
-
- static void DoDelete(const void* object) {
- delete reinterpret_cast<const T*>(object);
- }
-
- DISALLOW_COPY_AND_ASSIGN(DeleteHelper);
-};
-
-template <class T>
-class ReleaseHelper {
- private:
- template <class T2, class R> friend class subtle::ReleaseHelperInternal;
-
- static void DoRelease(const void* object) {
- reinterpret_cast<const T*>(object)->Release();
- }
-
- DISALLOW_COPY_AND_ASSIGN(ReleaseHelper);
-};
-
-namespace subtle {
-
-// An internal MessageLoop-like class helper for DeleteHelper and ReleaseHelper.
-// We don't want to expose the Do*() functions directly directly since the void*
-// argument makes it possible to pass/ an object of the wrong type to delete.
-// Instead, we force callers to go through these internal helpers for type
-// safety. MessageLoop-like classes which expose DeleteSoon or ReleaseSoon
-// methods should friend the appropriate helper and implement a corresponding
-// *Internal method with the following signature:
-// bool(const tracked_objects::Location&,
-// void(*function)(const void*),
-// void* object)
-// An implementation of this function should simply create a base::Closure
-// from (function, object) and return the result of posting the task.
-template <class T, class ReturnType>
-class DeleteHelperInternal {
- public:
- template <class MessageLoopType>
- static ReturnType DeleteOnMessageLoop(
- MessageLoopType* message_loop,
- const tracked_objects::Location& from_here,
- const T* object) {
- return message_loop->DeleteSoonInternal(from_here,
- &DeleteHelper<T>::DoDelete,
- object);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DeleteHelperInternal);
-};
-
-template <class T, class ReturnType>
-class ReleaseHelperInternal {
- public:
- template <class MessageLoopType>
- static ReturnType ReleaseOnMessageLoop(
- MessageLoopType* message_loop,
- const tracked_objects::Location& from_here,
- const T* object) {
- return message_loop->ReleaseSoonInternal(from_here,
- &ReleaseHelper<T>::DoRelease,
- object);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ReleaseHelperInternal);
-};
-
-} // namespace subtle
-
-} // namespace base
+// TODO(akalin): Change all includers of message_loop_helpers.h to
+// include sequenced_task_runner_helpers.h instead.
+#include "base/sequenced_task_runner_helpers.h"
#endif // BASE_MESSAGE_LOOP_HELPERS_H_
diff --git a/base/message_loop_proxy.cc b/base/message_loop_proxy.cc
index b815bb1..755564b 100644
--- a/base/message_loop_proxy.cc
+++ b/base/message_loop_proxy.cc
@@ -1,66 +1,17 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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 "base/message_loop_proxy.h"
#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/location.h"
-#include "base/threading/post_task_and_reply_impl.h"
namespace base {
-namespace {
-
-class PostTaskAndReplyMessageLoopProxy : public internal::PostTaskAndReplyImpl {
- public:
- PostTaskAndReplyMessageLoopProxy(MessageLoopProxy* destination)
- : destination_(destination) {
- }
-
- private:
- virtual bool PostTask(const tracked_objects::Location& from_here,
- const base::Closure& task) OVERRIDE {
- return destination_->PostTask(from_here, task);
- }
-
- // Non-owning.
- MessageLoopProxy* destination_;
-};
-
-} // namespace
-
MessageLoopProxy::MessageLoopProxy() {
}
MessageLoopProxy::~MessageLoopProxy() {
}
-bool MessageLoopProxy::PostTaskAndReply(
- const tracked_objects::Location& from_here,
- const Closure& task,
- const Closure& reply) {
- return PostTaskAndReplyMessageLoopProxy(this).PostTaskAndReply(
- from_here, task, reply);
-}
-
-void MessageLoopProxy::OnDestruct() const {
- delete this;
-}
-
-bool MessageLoopProxy::DeleteSoonInternal(
- const tracked_objects::Location& from_here,
- void(*deleter)(const void*),
- const void* object) {
- return PostNonNestableTask(from_here, base::Bind(deleter, object));
-}
-
-bool MessageLoopProxy::ReleaseSoonInternal(
- const tracked_objects::Location& from_here,
- void(*releaser)(const void*),
- const void* object) {
- return PostNonNestableTask(from_here, base::Bind(releaser, object));
-}
-
} // namespace base
diff --git a/base/message_loop_proxy.h b/base/message_loop_proxy.h
index 4487775..320ccfb 100644
--- a/base/message_loop_proxy.h
+++ b/base/message_loop_proxy.h
@@ -7,19 +7,12 @@
#pragma once
#include "base/base_export.h"
-#include "base/basictypes.h"
-#include "base/callback_forward.h"
+#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop_helpers.h"
-
-namespace tracked_objects {
-class Location;
-} // namespace tracked_objects
+#include "base/single_thread_task_runner.h"
namespace base {
-struct MessageLoopProxyTraits;
-
// This class provides a thread-safe refcounted interface to the Post* methods
// of a message loop. This class can outlive the target message loop.
// MessageLoopProxy objects are constructed automatically for all MessageLoops.
@@ -27,122 +20,18 @@ struct MessageLoopProxyTraits;
// Thread::message_loop_proxy()
// MessageLoop::current()->message_loop_proxy()
// MessageLoopProxy::current()
-class BASE_EXPORT MessageLoopProxy
- : public base::RefCountedThreadSafe<MessageLoopProxy,
- MessageLoopProxyTraits> {
+//
+// TODO(akalin): Now that we have the *TaskRunner interfaces, we can
+// merge this with MessageLoopProxyImpl.
+class BASE_EXPORT MessageLoopProxy : public SingleThreadTaskRunner {
public:
- // These methods are the same as in message_loop.h, but are guaranteed to
- // either post the Task to the MessageLoop (if it's still alive), or the task
- // is discarded.
- // They return true iff the thread existed and the task was posted. Note that
- // even if the task is posted, there's no guarantee that it will run; for
- // example the target loop may already be quitting, or in the case of a
- // delayed task a Quit message may preempt it in the message loop queue.
- // Conversely, a return value of false is a guarantee the task will not run.
- virtual bool PostTask(const tracked_objects::Location& from_here,
- const base::Closure& task) = 0;
- virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
- const base::Closure& task,
- int64 delay_ms) = 0;
- virtual bool PostNonNestableTask(const tracked_objects::Location& from_here,
- const base::Closure& task) = 0;
- virtual bool PostNonNestableDelayedTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task,
- int64 delay_ms) = 0;
-
- // A method which checks if the caller is currently running in the thread that
- // this proxy represents.
- virtual bool BelongsToCurrentThread() = 0;
-
- // Executes |task| on the given MessageLoopProxy. On completion, |reply|
- // is passed back to the MessageLoopProxy for the thread that called
- // PostTaskAndReply(). Both |task| and |reply| are guaranteed to be deleted
- // on the thread from which PostTaskAndReply() is invoked. This allows
- // objects that must be deleted on the originating thread to be bound into the
- // |task| and |reply| Closures. In particular, it can be useful to use
- // WeakPtr<> in the |reply| Closure so that the reply operation can be
- // canceled. See the following pseudo-code:
- //
- // class DataBuffer : public RefCountedThreadSafe<DataBuffer> {
- // public:
- // // Called to add data into a buffer.
- // void AddData(void* buf, size_t length);
- // ...
- // };
- //
- //
- // class DataLoader : public SupportsWeakPtr<DataLoader> {
- // public:
- // void GetData() {
- // scoped_refptr<DataBuffer> buffer = new DataBuffer();
- // target_thread_.message_loop_proxy()->PostTaskAndReply(
- // FROM_HERE,
- // base::Bind(&DataBuffer::AddData, buffer),
- // base::Bind(&DataLoader::OnDataReceived, AsWeakPtr(), buffer));
- // }
- //
- // private:
- // void OnDataReceived(scoped_refptr<DataBuffer> buffer) {
- // // Do something with buffer.
- // }
- // };
- //
- //
- // Things to notice:
- // * Results of |task| are shared with |reply| by binding a shared argument
- // (a DataBuffer instance).
- // * The DataLoader object has no special thread safety.
- // * The DataLoader object can be deleted while |task| is still running,
- // and the reply will cancel itself safely because it is bound to a
- // WeakPtr<>.
- bool PostTaskAndReply(const tracked_objects::Location& from_here,
- const Closure& task,
- const Closure& reply);
-
- template <class T>
- bool DeleteSoon(const tracked_objects::Location& from_here,
- const T* object) {
- return subtle::DeleteHelperInternal<T, bool>::DeleteOnMessageLoop(
- this, from_here, object);
- }
- template <class T>
- bool ReleaseSoon(const tracked_objects::Location& from_here,
- T* object) {
- return subtle::ReleaseHelperInternal<T, bool>::ReleaseOnMessageLoop(
- this, from_here, object);
- }
-
// Gets the MessageLoopProxy for the current message loop, creating one if
// needed.
static scoped_refptr<MessageLoopProxy> current();
protected:
- friend class RefCountedThreadSafe<MessageLoopProxy, MessageLoopProxyTraits>;
- friend struct MessageLoopProxyTraits;
-
MessageLoopProxy();
virtual ~MessageLoopProxy();
-
- // Called when the proxy is about to be deleted. Subclasses can override this
- // to provide deletion on specific threads.
- virtual void OnDestruct() const;
-
- private:
- template <class T, class R> friend class subtle::DeleteHelperInternal;
- template <class T, class R> friend class subtle::ReleaseHelperInternal;
- bool DeleteSoonInternal(const tracked_objects::Location& from_here,
- void(*deleter)(const void*),
- const void* object);
- bool ReleaseSoonInternal(const tracked_objects::Location& from_here,
- void(*releaser)(const void*),
- const void* object);
-};
-
-struct MessageLoopProxyTraits {
- static void Destruct(const MessageLoopProxy* proxy) {
- proxy->OnDestruct();
- }
};
} // namespace base
diff --git a/base/message_loop_proxy_impl.cc b/base/message_loop_proxy_impl.cc
index dd20b39..eeeb1db 100644
--- a/base/message_loop_proxy_impl.cc
+++ b/base/message_loop_proxy_impl.cc
@@ -12,11 +12,6 @@ namespace base {
MessageLoopProxyImpl::~MessageLoopProxyImpl() {
}
-bool MessageLoopProxyImpl::PostTask(const tracked_objects::Location& from_here,
- const base::Closure& task) {
- return PostTaskHelper(from_here, task, 0, true);
-}
-
bool MessageLoopProxyImpl::PostDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
@@ -24,11 +19,6 @@ bool MessageLoopProxyImpl::PostDelayedTask(
return PostTaskHelper(from_here, task, delay_ms, true);
}
-bool MessageLoopProxyImpl::PostNonNestableTask(
- const tracked_objects::Location& from_here, const base::Closure& task) {
- return PostTaskHelper(from_here, task, 0, false);
-}
-
bool MessageLoopProxyImpl::PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
@@ -36,7 +26,7 @@ bool MessageLoopProxyImpl::PostNonNestableDelayedTask(
return PostTaskHelper(from_here, task, delay_ms, false);
}
-bool MessageLoopProxyImpl::BelongsToCurrentThread() {
+bool MessageLoopProxyImpl::RunsTasksOnCurrentThread() const {
// We shouldn't use MessageLoop::current() since it uses LazyInstance which
// may be deleted by ~AtExitManager when a WorkerPool thread calls this
// function.
diff --git a/base/message_loop_proxy_impl.h b/base/message_loop_proxy_impl.h
index bb1fc0b..847ee4c 100644
--- a/base/message_loop_proxy_impl.h
+++ b/base/message_loop_proxy_impl.h
@@ -22,18 +22,14 @@ class BASE_EXPORT MessageLoopProxyImpl
virtual ~MessageLoopProxyImpl();
// MessageLoopProxy implementation
- virtual bool PostTask(const tracked_objects::Location& from_here,
- const base::Closure& task) OVERRIDE;
virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
const base::Closure& task,
int64 delay_ms) OVERRIDE;
- virtual bool PostNonNestableTask(const tracked_objects::Location& from_here,
- const base::Closure& task) OVERRIDE;
virtual bool PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
int64 delay_ms) OVERRIDE;
- virtual bool BelongsToCurrentThread() OVERRIDE;
+ virtual bool RunsTasksOnCurrentThread() const OVERRIDE;
protected:
// Override OnDestruct so that we can delete the object on the target message
diff --git a/base/sequenced_task_runner.cc b/base/sequenced_task_runner.cc
new file mode 100644
index 0000000..bab7d1c
--- /dev/null
+++ b/base/sequenced_task_runner.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2012 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 "base/sequenced_task_runner.h"
+
+#include "base/bind.h"
+
+namespace base {
+
+bool SequencedTaskRunner::PostNonNestableTask(
+ const tracked_objects::Location& from_here,
+ const Closure& task) {
+ return PostNonNestableDelayedTask(from_here, task, 0);
+}
+
+bool SequencedTaskRunner::DeleteSoonInternal(
+ const tracked_objects::Location& from_here,
+ void(*deleter)(const void*),
+ const void* object) {
+ return PostNonNestableTask(from_here, Bind(deleter, object));
+}
+
+bool SequencedTaskRunner::ReleaseSoonInternal(
+ const tracked_objects::Location& from_here,
+ void(*releaser)(const void*),
+ const void* object) {
+ return PostNonNestableTask(from_here, Bind(releaser, object));
+}
+
+} // namespace base
diff --git a/base/sequenced_task_runner.h b/base/sequenced_task_runner.h
new file mode 100644
index 0000000..a280522
--- /dev/null
+++ b/base/sequenced_task_runner.h
@@ -0,0 +1,156 @@
+// Copyright (c) 2012 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.
+
+#ifndef BASE_SEQUENCED_TASKRUNNER_H_
+#define BASE_SEQUENCED_TASKRUNNER_H_
+#pragma once
+
+#include "base/base_export.h"
+#include "base/sequenced_task_runner_helpers.h"
+#include "base/task_runner.h"
+
+namespace base {
+
+// A SequencedTaskRunner is a subclass of TaskRunner that provides
+// additional guarantees on the order that tasks are started, as well
+// as guarantees on when tasks are in sequence, i.e. one task finishes
+// before the other one starts.
+//
+// Summary
+// -------
+// Barring delayed/non-nestable tasks, tasks posted will run one by
+// one in FIFO order.
+//
+// Detailed guarantees
+// -------------------
+//
+// SequencedTaskRunner also adds additional methods for posting
+// non-nestable tasks. In general, an implementation of TaskRunner
+// may expose task-running methods which are themselves callable from
+// within tasks. A non-nestable task is one that is guaranteed to not
+// be run from within an already-running task. Conversely, a nestable
+// task (the default) is a task that can be run from within an
+// already-running task.
+//
+// The guarantees of SequencedTaskRunner are as follows:
+//
+// - Given two tasks T2 and T1, T2 will start after T1 starts if:
+//
+// * T2 is posted after T1;
+// * T2 has equal or higher delay than T1; and
+// * T2 is non-nestable or T1 is nestable.
+//
+// - If T2 will start after T1 starts by the above guarantee, then
+// T2 will start after T1 finishes if:
+//
+// * T2 is non-nestable, or
+// * T1 doesn't call any task-running methods.
+//
+// - If T2 will start after T1 finishes by the above guarantee, then
+// all memory changes in T1 will be visible to T2.
+//
+// - If T2 runs nested within T1 via a call to the task-running
+// method M, then all memory changes in T1 up to the call to M
+// will be visible to T2, and all memory changes in T2 will be
+// visible to T1 from the return from M.
+//
+// Note that SequencedTaskRunner does not guarantee that tasks are run
+// on a single dedicated thread, although the above guarantees provide
+// most (but not all) of the same guarantees. If you do need to
+// guarantee that tasks are run on a single dedicated thread, see
+// SingleThreadTaskRunner (in single_thread_task_runner.h).
+//
+// Some corollaries to the above guarantees, assuming the tasks in
+// question don't call any task-running methods:
+//
+// - Tasks posted via PostTask are run in FIFO order.
+//
+// - Tasks posted via PostNonNestableTask are run in FIFO order.
+//
+// - Tasks posted with the same delay and the same nestable state
+// are run in FIFO order.
+//
+// - A list of tasks with the same nestable state posted in order of
+// non-decreasing delay is run in FIFO order.
+//
+// - A list of tasks posted in order of non-decreasing delay with at
+// most a single change in nestable state from nestable to
+// non-nestable is run in FIFO order. (This is equivalent to the
+// statement of the first guarantee above.)
+//
+// Some theoretical implementations of SequencedTaskRunner:
+//
+// - A SequencedTaskRunner that wraps a regular TaskRunner but makes
+// sure that only one task at a time is posted to the TaskRunner,
+// with appropriate memory barriers in between tasks.
+//
+// - A SequencedTaskRunner that, for each task, spawns a joinable
+// thread to run that task and immediately quit, and then
+// immediately joins that thread.
+//
+// - A SequencedTaskRunner that stores the list of posted tasks and
+// has a method Run() that runs each runnable task in FIFO order
+// that can be called from any thread, but only if another
+// (non-nested) Run() call isn't already happening.
+class BASE_EXPORT SequencedTaskRunner : public TaskRunner {
+ public:
+ // The two PostNonNestable*Task methods below are like their
+ // nestable equivalents in TaskRunner, but they guarantee that the
+ // posted task will not run nested within an already-running task.
+ //
+ // A simple corollary is that posting a task as non-nestable can
+ // only delay when the task gets run. That is, posting a task as
+ // non-nestable may not affect when the task gets run, or it could
+ // make it run later than it normally would, but it won't make it
+ // run earlier than it normally would.
+
+ // TODO(akalin): Get rid of the boolean return value for the methods
+ // below.
+
+ bool PostNonNestableTask(const tracked_objects::Location& from_here,
+ const Closure& task);
+
+ virtual bool PostNonNestableDelayedTask(
+ const tracked_objects::Location& from_here,
+ const Closure& task,
+ int64 delay_ms) = 0;
+
+ // Submits a non-nestable task to delete the given object. Returns
+ // true if the object may be deleted at some point in the future,
+ // and false if the object definitely will not be deleted.
+ template <class T>
+ bool DeleteSoon(const tracked_objects::Location& from_here,
+ const T* object) {
+ return
+ subtle::DeleteHelperInternal<T, bool>::DeleteViaSequencedTaskRunner(
+ this, from_here, object);
+ }
+
+ // Submits a non-nestable task to release the given object. Returns
+ // true if the object may be released at some point in the future,
+ // and false if the object definitely will not be released.
+ template <class T>
+ bool ReleaseSoon(const tracked_objects::Location& from_here,
+ T* object) {
+ return
+ subtle::ReleaseHelperInternal<T, bool>::ReleaseViaSequencedTaskRunner(
+ this, from_here, object);
+ }
+
+private:
+ template <class T, class R> friend class subtle::DeleteHelperInternal;
+ template <class T, class R> friend class subtle::ReleaseHelperInternal;
+
+ bool DeleteSoonInternal(const tracked_objects::Location& from_here,
+ void(*deleter)(const void*),
+ const void* object);
+
+ bool ReleaseSoonInternal(const tracked_objects::Location& from_here,
+ void(*releaser)(const void*),
+ const void* object);
+};
+
+} // namespace base
+
+#endif // BASE_SEQUENCED_TASKRUNNER_H_
diff --git a/base/sequenced_task_runner_helpers.h b/base/sequenced_task_runner_helpers.h
new file mode 100644
index 0000000..f03ca9e
--- /dev/null
+++ b/base/sequenced_task_runner_helpers.h
@@ -0,0 +1,113 @@
+// Copyright (c) 2012 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.
+
+#ifndef BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_
+#define BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_
+#pragma once
+
+#include "base/basictypes.h"
+
+// TODO(akalin): Investigate whether it's possible to just have
+// SequencedTaskRunner use these helpers (instead of MessageLoop).
+// Then we can just move these to sequenced_task_runner.h.
+
+namespace tracked_objects {
+class Location;
+}
+
+namespace base {
+
+namespace subtle {
+template <class T, class R> class DeleteHelperInternal;
+template <class T, class R> class ReleaseHelperInternal;
+}
+
+// Template helpers which use function indirection to erase T from the
+// function signature while still remembering it so we can call the
+// correct destructor/release function.
+//
+// We use this trick so we don't need to include bind.h in a header
+// file like sequenced_task_runner.h. We also wrap the helpers in a
+// templated class to make it easier for users of DeleteSoon to
+// declare the helper as a friend.
+template <class T>
+class DeleteHelper {
+ private:
+ template <class T2, class R> friend class subtle::DeleteHelperInternal;
+
+ static void DoDelete(const void* object) {
+ delete reinterpret_cast<const T*>(object);
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(DeleteHelper);
+};
+
+template <class T>
+class ReleaseHelper {
+ private:
+ template <class T2, class R> friend class subtle::ReleaseHelperInternal;
+
+ static void DoRelease(const void* object) {
+ reinterpret_cast<const T*>(object)->Release();
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(ReleaseHelper);
+};
+
+namespace subtle {
+
+// An internal SequencedTaskRunner-like class helper for DeleteHelper
+// and ReleaseHelper. We don't want to expose the Do*() functions
+// directly directly since the void* argument makes it possible to
+// pass/ an object of the wrong type to delete. Instead, we force
+// callers to go through these internal helpers for type
+// safety. SequencedTaskRunner-like classes which expose DeleteSoon or
+// ReleaseSoon methods should friend the appropriate helper and
+// implement a corresponding *Internal method with the following
+// signature:
+//
+// bool(const tracked_objects::Location&,
+// void(*function)(const void*),
+// void* object)
+//
+// An implementation of this function should simply create a
+// base::Closure from (function, object) and return the result of
+// posting the task.
+template <class T, class ReturnType>
+class DeleteHelperInternal {
+ public:
+ template <class SequencedTaskRunnerType>
+ static ReturnType DeleteViaSequencedTaskRunner(
+ SequencedTaskRunnerType* sequenced_task_runner,
+ const tracked_objects::Location& from_here,
+ const T* object) {
+ return sequenced_task_runner->DeleteSoonInternal(
+ from_here, &DeleteHelper<T>::DoDelete, object);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DeleteHelperInternal);
+};
+
+template <class T, class ReturnType>
+class ReleaseHelperInternal {
+ public:
+ template <class SequencedTaskRunnerType>
+ static ReturnType ReleaseViaSequencedTaskRunner(
+ SequencedTaskRunnerType* sequenced_task_runner,
+ const tracked_objects::Location& from_here,
+ const T* object) {
+ return sequenced_task_runner->ReleaseSoonInternal(
+ from_here, &ReleaseHelper<T>::DoRelease, object);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ReleaseHelperInternal);
+};
+
+} // namespace subtle
+
+} // namespace base
+
+#endif // BASE_SEQUENCED_TASK_RUNNER_HELPERS_H_
diff --git a/base/single_thread_task_runner.h b/base/single_thread_task_runner.h
new file mode 100644
index 0000000..93f694e
--- /dev/null
+++ b/base/single_thread_task_runner.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2012 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.
+
+#ifndef BASE_SINGLE_THREAD_TASK_RUNNER_H_
+#define BASE_SINGLE_THREAD_TASK_RUNNER_H_
+#pragma once
+
+#include "base/base_export.h"
+#include "base/sequenced_task_runner.h"
+
+namespace base {
+
+// A SingleThreadTaskRunner is a SequencedTaskRunner with one more
+// guarantee; namely, that all tasks are run on a single dedicated
+// thread. Most use cases require only a SequencedTaskRunner, unless
+// there is a specific need to run tasks on only a single dedicated.
+//
+// Some theoretical implementations of SingleThreadTaskRunner:
+//
+// - A SingleThreadTaskRunner that uses a single worker thread to
+// run posted tasks (i.e., a message loop).
+//
+// - A SingleThreadTaskRunner that stores the list of posted tasks
+// and has a method Run() that runs each runnable task in FIFO
+// order that must be run only from the thread the
+// SingleThreadTaskRunner was created on.
+class BASE_EXPORT SingleThreadTaskRunner : public SequencedTaskRunner {
+public:
+ // A more explicit alias to RunsTasksOnCurrentThread().
+ bool BelongsToCurrentThread() const {
+ return RunsTasksOnCurrentThread();
+ }
+};
+
+} // namespace base
+
+#endif // BASE_SERIAL_TASK_RUNNER_H_
diff --git a/base/task_runner.cc b/base/task_runner.cc
new file mode 100644
index 0000000..734674f
--- /dev/null
+++ b/base/task_runner.cc
@@ -0,0 +1,68 @@
+// Copyright (c) 2012 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 "base/task_runner.h"
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/threading/post_task_and_reply_impl.h"
+
+namespace base {
+
+namespace {
+
+// TODO(akalin): There's only one other implementation of
+// PostTaskAndReplyImpl in WorkerPool. Investigate whether it'll be
+// possible to merge the two.
+class PostTaskAndReplyTaskRunner : public internal::PostTaskAndReplyImpl {
+ public:
+ PostTaskAndReplyTaskRunner(TaskRunner* destination);
+
+ private:
+ virtual bool PostTask(const tracked_objects::Location& from_here,
+ const Closure& task) OVERRIDE;
+
+ // Non-owning.
+ TaskRunner* destination_;
+};
+
+PostTaskAndReplyTaskRunner::PostTaskAndReplyTaskRunner(
+ TaskRunner* destination) : destination_(destination) {
+ DCHECK(destination_);
+}
+
+bool PostTaskAndReplyTaskRunner::PostTask(
+ const tracked_objects::Location& from_here,
+ const Closure& task) {
+ return destination_->PostTask(from_here, task);
+}
+
+} // namespace
+
+bool TaskRunner::PostTask(const tracked_objects::Location& from_here,
+ const Closure& task) {
+ return PostDelayedTask(from_here, task, 0);
+}
+
+bool TaskRunner::PostTaskAndReply(
+ const tracked_objects::Location& from_here,
+ const Closure& task,
+ const Closure& reply) {
+ return PostTaskAndReplyTaskRunner(this).PostTaskAndReply(
+ from_here, task, reply);
+}
+
+TaskRunner::TaskRunner() {}
+
+TaskRunner::~TaskRunner() {}
+
+void TaskRunner::OnDestruct() const {
+ delete this;
+}
+
+void TaskRunnerTraits::Destruct(const TaskRunner* task_runner) {
+ task_runner->OnDestruct();
+}
+
+} // namespace base
diff --git a/base/task_runner.h b/base/task_runner.h
new file mode 100644
index 0000000..7527031
--- /dev/null
+++ b/base/task_runner.h
@@ -0,0 +1,155 @@
+// Copyright (c) 2012 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.
+
+#ifndef BASE_TASK_RUNNER_H_
+#define BASE_TASK_RUNNER_H_
+#pragma once
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/memory/ref_counted.h"
+
+namespace tracked_objects {
+class Location;
+} // namespace tracked_objects
+
+namespace base {
+
+struct TaskRunnerTraits;
+
+// A TaskRunner is an object that runs posted tasks (in the form of
+// Closure objects). The TaskRunner interface provides a way of
+// decoupling task posting from the mechanics of how each task will be
+// run. TaskRunner provides very weak guarantees as to how posted
+// tasks are run (or if they're run at all). In particular, it only
+// guarantees:
+//
+// - Posting a task will not run it synchronously. That is, no
+// Post*Task method will call task.Run() directly.
+//
+// - Increasing the delay can only delay when the task gets run.
+// That is, increasing the delay may not affect when the task gets
+// run, or it could make it run later than it normally would, but
+// it won't make it run earlier than it normally would.
+//
+// TaskRunner does not guarantee the order in which posted tasks are
+// run, whether tasks overlap, or whether they're run on a particular
+// thread. Also it does not guarantee a memory model for shared data
+// between tasks. (In other words, you should use your own
+// synchronization/locking primitives if you need to share data
+// between tasks.)
+//
+// Implementations of TaskRunner should be thread-safe in that all
+// methods must be safe to call on any thread. Ownership semantics
+// for TaskRunners are in general not clear, which is why the
+// interface itself is RefCountedThreadSafe.
+//
+// Some theoretical implementations of TaskRunner:
+//
+// - A TaskRunner that uses a thread pool to run posted tasks.
+//
+// - A TaskRunner that, for each task, spawns a non-joinable thread
+// to run that task and immediately quit.
+//
+// - A TaskRunner that stores the list of posted tasks and has a
+// method Run() that runs each runnable task in random order.
+class BASE_EXPORT TaskRunner
+ : public RefCountedThreadSafe<TaskRunner, TaskRunnerTraits> {
+ public:
+ // Posts the given task to be run. Returns true if the task may be
+ // run at some point in the future, and false if the task definitely
+ // will not be run.
+ //
+ // Equivalent to PostDelayedTask(from_here, task, 0).
+ bool PostTask(const tracked_objects::Location& from_here,
+ const Closure& task);
+
+ // Like PostTask, but tries to run the posted task only after
+ // |delay_ms| has passed.
+ //
+ // It is valid for an implementation to ignore |delay_ms|; that is,
+ // to have PostDelayedTask behave the same as PostTask.
+ //
+ // TODO(akalin): Make PostDelayedTask use TimeDelta instead.
+ virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
+ const Closure& task,
+ int64 delay_ms) = 0;
+
+ // Returns true if the current thread is a thread on which a task
+ // may be run, and false if no task will be run on the current
+ // thread.
+ //
+ // It is valid for an implementation to always return true, or in
+ // general to use 'true' as a default value.
+ virtual bool RunsTasksOnCurrentThread() const = 0;
+
+ // Posts |task| on the current TaskRunner. On completion, |reply|
+ // is posted to the thread that called PostTaskAndReply(). Both
+ // |task| and |reply| are guaranteed to be deleted on the thread
+ // from which PostTaskAndReply() is invoked. This allows objects
+ // that must be deleted on the originating thread to be bound into
+ // the |task| and |reply| Closures. In particular, it can be useful
+ // to use WeakPtr<> in the |reply| Closure so that the reply
+ // operation can be canceled. See the following pseudo-code:
+ //
+ // class DataBuffer : public RefCountedThreadSafe<DataBuffer> {
+ // public:
+ // // Called to add data into a buffer.
+ // void AddData(void* buf, size_t length);
+ // ...
+ // };
+ //
+ //
+ // class DataLoader : public SupportsWeakPtr<DataLoader> {
+ // public:
+ // void GetData() {
+ // scoped_refptr<DataBuffer> buffer = new DataBuffer();
+ // target_thread_.message_loop_proxy()->PostTaskAndReply(
+ // FROM_HERE,
+ // base::Bind(&DataBuffer::AddData, buffer),
+ // base::Bind(&DataLoader::OnDataReceived, AsWeakPtr(), buffer));
+ // }
+ //
+ // private:
+ // void OnDataReceived(scoped_refptr<DataBuffer> buffer) {
+ // // Do something with buffer.
+ // }
+ // };
+ //
+ //
+ // Things to notice:
+ // * Results of |task| are shared with |reply| by binding a shared argument
+ // (a DataBuffer instance).
+ // * The DataLoader object has no special thread safety.
+ // * The DataLoader object can be deleted while |task| is still running,
+ // and the reply will cancel itself safely because it is bound to a
+ // WeakPtr<>.
+ bool PostTaskAndReply(const tracked_objects::Location& from_here,
+ const Closure& task,
+ const Closure& reply);
+
+ protected:
+ friend struct TaskRunnerTraits;
+
+ // Only the Windows debug build seems to need this: see
+ // http://crbug.com/112250.
+ friend class RefCountedThreadSafe<TaskRunner, TaskRunnerTraits>;
+
+ TaskRunner();
+ virtual ~TaskRunner();
+
+ // Called when this object should be destroyed. By default simply
+ // deletes |this|, but can be overridden to do something else, like
+ // delete on a certain thread.
+ virtual void OnDestruct() const;
+};
+
+struct BASE_EXPORT TaskRunnerTraits {
+ static void Destruct(const TaskRunner* task_runner);
+};
+
+} // namespace base
+
+#endif // BASE_TASK_RUNNER_H_
diff --git a/content/browser/browser_thread_impl.cc b/content/browser/browser_thread_impl.cc
index 155160b..f0aab01 100644
--- a/content/browser/browser_thread_impl.cc
+++ b/content/browser/browser_thread_impl.cc
@@ -6,6 +6,7 @@
#include "base/atomicops.h"
#include "base/bind.h"
+#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
@@ -184,30 +185,21 @@ class BrowserThreadMessageLoopProxy : public base::MessageLoopProxy {
}
// MessageLoopProxy implementation.
- virtual bool PostTask(const tracked_objects::Location& from_here,
- const base::Closure& task) {
- return BrowserThread::PostTask(id_, from_here, task);
- }
-
- virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
- const base::Closure& task, int64 delay_ms) {
+ virtual bool PostDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task, int64 delay_ms) OVERRIDE{
return BrowserThread::PostDelayedTask(id_, from_here, task, delay_ms);
}
- virtual bool PostNonNestableTask(const tracked_objects::Location& from_here,
- const base::Closure& task) {
- return BrowserThread::PostNonNestableTask(id_, from_here, task);
- }
-
virtual bool PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
- int64 delay_ms) {
+ int64 delay_ms) OVERRIDE {
return BrowserThread::PostNonNestableDelayedTask(id_, from_here, task,
delay_ms);
}
- virtual bool BelongsToCurrentThread() {
+ virtual bool RunsTasksOnCurrentThread() const OVERRIDE {
return BrowserThread::CurrentlyOn(id_);
}
diff --git a/remoting/base/plugin_message_loop_proxy.cc b/remoting/base/plugin_message_loop_proxy.cc
index b3bc453..7cd03a4 100644
--- a/remoting/base/plugin_message_loop_proxy.cc
+++ b/remoting/base/plugin_message_loop_proxy.cc
@@ -24,12 +24,6 @@ void PluginMessageLoopProxy::Detach() {
}
}
-bool PluginMessageLoopProxy::PostTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task) {
- return PostDelayedTask(from_here, task, 0);
-}
-
bool PluginMessageLoopProxy::PostDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
@@ -44,13 +38,6 @@ bool PluginMessageLoopProxy::PostDelayedTask(
delay_ms, &PluginMessageLoopProxy::TaskSpringboard, springpad_closure);
}
-bool PluginMessageLoopProxy::PostNonNestableTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task) {
- // All tasks running on this message loop are non-nestable.
- return PostTask(from_here, task);
-}
-
bool PluginMessageLoopProxy::PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
@@ -59,7 +46,7 @@ bool PluginMessageLoopProxy::PostNonNestableDelayedTask(
return PostDelayedTask(from_here, task, delay_ms);
}
-bool PluginMessageLoopProxy::BelongsToCurrentThread() {
+bool PluginMessageLoopProxy::RunsTasksOnCurrentThread() const {
// In pepper plugins ideally we should use pp::Core::IsMainThread,
// but it is problematic because we would need to keep reference to
// Core somewhere, e.g. make the delegate ref-counted.
diff --git a/remoting/base/plugin_message_loop_proxy.h b/remoting/base/plugin_message_loop_proxy.h
index 19082a0..855134f 100644
--- a/remoting/base/plugin_message_loop_proxy.h
+++ b/remoting/base/plugin_message_loop_proxy.h
@@ -32,22 +32,16 @@ class PluginMessageLoopProxy : public base::MessageLoopProxy {
void Detach();
// base::MessageLoopProxy implementation.
- virtual bool PostTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task) OVERRIDE;
virtual bool PostDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
int64 delay_ms) OVERRIDE;
- virtual bool PostNonNestableTask(
- const tracked_objects::Location& from_here,
- const base::Closure& task) OVERRIDE;
virtual bool PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
int64 delay_ms) OVERRIDE;
- virtual bool BelongsToCurrentThread() OVERRIDE;
+ virtual bool RunsTasksOnCurrentThread() const OVERRIDE;
private:
static void TaskSpringboard(void* data);