diff options
author | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-15 01:43:19 +0000 |
---|---|---|
committer | akalin@chromium.org <akalin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-15 01:43:19 +0000 |
commit | 6b28d9469f63df13c9918d5f2d8d24ba8b9893a5 (patch) | |
tree | 195a09586b5388359914e63ebeca1aa66a2516fe | |
parent | 1005065913ee5ced3fd8fc915d31e0c0461e2b1d (diff) | |
download | chromium_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.gypi | 7 | ||||
-rw-r--r-- | base/message_loop.h | 6 | ||||
-rw-r--r-- | base/message_loop_helpers.h | 99 | ||||
-rw-r--r-- | base/message_loop_proxy.cc | 51 | ||||
-rw-r--r-- | base/message_loop_proxy.h | 123 | ||||
-rw-r--r-- | base/message_loop_proxy_impl.cc | 12 | ||||
-rw-r--r-- | base/message_loop_proxy_impl.h | 6 | ||||
-rw-r--r-- | base/sequenced_task_runner.cc | 31 | ||||
-rw-r--r-- | base/sequenced_task_runner.h | 156 | ||||
-rw-r--r-- | base/sequenced_task_runner_helpers.h | 113 | ||||
-rw-r--r-- | base/single_thread_task_runner.h | 38 | ||||
-rw-r--r-- | base/task_runner.cc | 68 | ||||
-rw-r--r-- | base/task_runner.h | 155 | ||||
-rw-r--r-- | content/browser/browser_thread_impl.cc | 20 | ||||
-rw-r--r-- | remoting/base/plugin_message_loop_proxy.cc | 15 | ||||
-rw-r--r-- | remoting/base/plugin_message_loop_proxy.h | 8 |
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); |