diff options
-rw-r--r-- | remoting/base/scoped_thread_proxy.cc | 84 | ||||
-rw-r--r-- | remoting/base/scoped_thread_proxy.h | 73 | ||||
-rw-r--r-- | remoting/base/task_thread_proxy.cc | 34 | ||||
-rw-r--r-- | remoting/base/task_thread_proxy.h | 50 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_instance.cc | 31 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_instance.h | 9 | ||||
-rw-r--r-- | remoting/host/desktop_environment.cc | 71 | ||||
-rw-r--r-- | remoting/host/desktop_environment.h | 4 | ||||
-rw-r--r-- | remoting/remoting.gyp | 4 |
9 files changed, 189 insertions, 171 deletions
diff --git a/remoting/base/scoped_thread_proxy.cc b/remoting/base/scoped_thread_proxy.cc new file mode 100644 index 0000000..b526d6af --- /dev/null +++ b/remoting/base/scoped_thread_proxy.cc @@ -0,0 +1,84 @@ +// 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 "remoting/base/scoped_thread_proxy.h" + +namespace remoting { + +class ScopedThreadProxy::Core : public base::RefCountedThreadSafe<Core> { + public: + Core(base::MessageLoopProxy* message_loop) + : message_loop_(message_loop), + canceled_(false) { + } + + void PostTask(const tracked_objects::Location& from_here, + const base::Closure& closure) { + if (!canceled_) + message_loop_->PostTask(from_here, Wrap(closure)); + } + + void PostDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& closure, + int64 delay_ms) { + if (!canceled_) { + message_loop_->PostDelayedTask(from_here, Wrap(closure), delay_ms); + } + } + + void Detach() { + DCHECK(message_loop_->BelongsToCurrentThread()); + canceled_ = true; + } + + private: + friend class base::RefCountedThreadSafe<Core>; + + ~Core() { + DCHECK(canceled_); + } + + base::Closure Wrap(const base::Closure& closure) { + return base::Bind(&Core::CallClosure, this, closure); + } + + void CallClosure(const base::Closure& closure) { + DCHECK(message_loop_->BelongsToCurrentThread()); + + if (!canceled_) + closure.Run(); + } + + scoped_refptr<base::MessageLoopProxy> message_loop_; + bool canceled_; + + DISALLOW_COPY_AND_ASSIGN(Core); +}; + +ScopedThreadProxy::ScopedThreadProxy(base::MessageLoopProxy* message_loop) + : core_(new Core(message_loop)) { +} + +ScopedThreadProxy::~ScopedThreadProxy() { + Detach(); +} + +void ScopedThreadProxy::PostTask(const tracked_objects::Location& from_here, + const base::Closure& closure) { + core_->PostTask(from_here, closure); +} + +void ScopedThreadProxy::PostDelayedTask( + const tracked_objects::Location& from_here, + const base::Closure& closure, + int64 delay_ms) { + core_->PostDelayedTask(from_here, closure, delay_ms); +} + +void ScopedThreadProxy::Detach() { + core_->Detach(); +} + +} // namespace remoting diff --git a/remoting/base/scoped_thread_proxy.h b/remoting/base/scoped_thread_proxy.h new file mode 100644 index 0000000..63dcaf8 --- /dev/null +++ b/remoting/base/scoped_thread_proxy.h @@ -0,0 +1,73 @@ +// 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. + +#ifndef REMOTING_BASE_SCOPED_THREAD_PROXY_H_ +#define REMOTING_BASE_SCOPED_THREAD_PROXY_H_ + +#include "base/bind.h" +#include "base/message_loop_proxy.h" + +namespace remoting { + +// ScopedThreadProxy is proxy for message loops that cancels all +// pending tasks when it is destroyed. It can be used to post tasks +// for a non-refcounted object. Must be deleted on the thread it +// belongs to. +// +// The main difference from WeakPtr<> and ScopedRunnableMethodFactory<> +// is that this class can be used safely to post tasks from different +// threads. +// It is similar to WeakHandle<> used in sync: the main difference is +// that WeakHandle<> creates closures itself, while ScopedThreadProxy +// accepts base::Closure instances which caller needs to create using +// base::Bind(). +// +// TODO(sergeyu): Potentially we could use WeakHandle<> instead of +// this class. Consider migrating to WeakHandle<> when it is moved to +// src/base and support for delayed tasks is implemented. +// +// Usage: +// class MyClass { +// public: +// MyClass() +// : thread_proxy_(base::MessageLoopProxy::current()) {} +// +// // Always called on the thread on which this object was created. +// void NonThreadSafeMethod() {} +// +// // Can be called on any thread. +// void ThreadSafeMethod() { +// thread_proxy_.PostTask(FROM_HERE, base::Bind( +// &MyClass::NonThreadSafeMethod, base::Unretained(this))); +// } +// +// private: +// ScopedThreadProxy thread_proxy_; +// }; +class ScopedThreadProxy { + public: + ScopedThreadProxy(base::MessageLoopProxy* message_loop); + ~ScopedThreadProxy(); + + void PostTask(const tracked_objects::Location& from_here, + const base::Closure& closure); + void PostDelayedTask(const tracked_objects::Location& from_here, + const base::Closure& closure, + int64 delay_ms); + + // Cancels all tasks posted via this proxy. Must be called on the + // thread this object belongs to. + void Detach(); + + private: + class Core; + + scoped_refptr<Core> core_; + + DISALLOW_COPY_AND_ASSIGN(ScopedThreadProxy); +}; + +} // namespace remoting + +#endif // REMOTING_BASE_SCOPED_THREAD_PROXY_H_ diff --git a/remoting/base/task_thread_proxy.cc b/remoting/base/task_thread_proxy.cc deleted file mode 100644 index d379620..0000000 --- a/remoting/base/task_thread_proxy.cc +++ /dev/null @@ -1,34 +0,0 @@ -// 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 "remoting/base/task_thread_proxy.h" - -#include "base/bind.h" - -namespace remoting { - -TaskThreadProxy::TaskThreadProxy(MessageLoop* loop) - : message_loop_(loop) { -} - -TaskThreadProxy::~TaskThreadProxy() { -} - -void TaskThreadProxy::Detach() { - message_loop_ = NULL; -} - -void TaskThreadProxy::Call(const base::Closure& closure) { - if (message_loop_) { - message_loop_->PostTask(FROM_HERE, NewRunnableMethod( - this, &TaskThreadProxy::CallClosure, closure)); - } -} - -void TaskThreadProxy::CallClosure(const base::Closure& closure) { - if (message_loop_) - closure.Run(); -} - -} // namespace remoting diff --git a/remoting/base/task_thread_proxy.h b/remoting/base/task_thread_proxy.h deleted file mode 100644 index 67ccc2d..0000000 --- a/remoting/base/task_thread_proxy.h +++ /dev/null @@ -1,50 +0,0 @@ -// 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. - -#ifndef REMOTING_BASE_TASK_THREAD_PROXY_H_ -#define REMOTING_BASE_TASK_THREAD_PROXY_H_ - -#include "base/message_loop.h" - -namespace remoting { - -// This is a refcounted class that is used to switch to the appropriate thread -// before running a task on a target object. It should be used whenever you -// need to post to an object, but: -// (1) You don't know when the object might be deleted, and -// (2) You cannot subclass the target from RefCountedThreadSafe. -// -// Example usage: -// Instead of: -// MyClass* obj; -// obj->Method(param); -// Use: -// proxy->Call(base::Bind(&MyClass::Method, -// base::Unretained(obj), -// param); -class TaskThreadProxy : public base::RefCountedThreadSafe<TaskThreadProxy> { - public: - TaskThreadProxy(MessageLoop* loop); - - // Detach should be called when the target of the posted task is being - // destroyed. - void Detach(); - - void Call(const base::Closure& closure); - - private: - friend class base::RefCountedThreadSafe<TaskThreadProxy>; - - virtual ~TaskThreadProxy(); - - void CallClosure(const base::Closure& closure); - - MessageLoop* message_loop_; - - DISALLOW_COPY_AND_ASSIGN(TaskThreadProxy); -}; - -} // namespace remoting - -#endif // REMOTING_BASE_TASK_THREAD_PROXY_H_ diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index 6281a24..d4176ed 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc @@ -24,7 +24,6 @@ #include "ppapi/cpp/rect.h" // TODO(wez): Remove this when crbug.com/86353 is complete. #include "ppapi/cpp/private/var_private.h" -#include "remoting/base/task_thread_proxy.h" #include "remoting/base/util.h" #include "remoting/client/client_config.h" #include "remoting/client/chromoting_client.h" @@ -71,12 +70,10 @@ ChromotingInstance::ChromotingInstance(PP_Instance pp_instance) scale_to_fit_(false), enable_client_nat_traversal_(false), initial_policy_received_(false), - task_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { + thread_proxy_(new ScopedThreadProxy(plugin_message_loop_)) { RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE | PP_INPUTEVENT_CLASS_WHEEL); RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); - log_proxy_ = new TaskThreadProxy(MessageLoop::current()); - // Resister this instance to handle debug log messsages. RegisterLoggingInstance(); } @@ -86,7 +83,7 @@ ChromotingInstance::~ChromotingInstance() { // Detach the log proxy so we don't log anything else to the UI. // This needs to be done before the instance is unregistered for logging. - log_proxy_->Detach(); + thread_proxy_->Detach(); // Unregister this instance so that debug log messages will no longer be sent // to it. This will stop all logging in all Chromoting instances. @@ -107,6 +104,10 @@ ChromotingInstance::~ChromotingInstance() { view_proxy_->Detach(); } + // Delete |thread_proxy_| before we detach |plugin_message_loop_|, + // otherwise ScopedThreadProxy may DCHECK when destroying. + thread_proxy_.reset(); + plugin_message_loop_->Detach(); } @@ -150,8 +151,10 @@ void ChromotingInstance::Connect(const ClientConfig& config) { // enterprise policy is pushed at least once, we we delay the connect call. if (!initial_policy_received_) { VLOG(1) << "Delaying connect until initial policy is read."; - delayed_connect_.reset( - task_factory_.NewRunnableMethod(&ChromotingInstance::Connect, config)); + // base::Unretained() is safe here because |delayed_connect_| is + // used only with |thread_proxy_|. + delayed_connect_ = base::Bind(&ChromotingInstance::Connect, + base::Unretained(this), config); return; } @@ -395,11 +398,11 @@ bool ChromotingInstance::LogToUI(int severity, const char* file, int line, if (g_logging_instance) { std::string message = remoting::GetTimestampString(); message += (str.c_str() + message_start); - // |log_proxy_| is safe to use here because we detach the proxy before + // |thread_proxy_| is safe to use here because we detach it before // tearing down the |g_logging_instance|. - g_logging_instance->log_proxy_->Call( - base::Bind(&ChromotingInstance::ProcessLogToUI, - base::Unretained(g_logging_instance), message)); + g_logging_instance->thread_proxy_->PostTask( + FROM_HERE, base::Bind(&ChromotingInstance::ProcessLogToUI, + base::Unretained(g_logging_instance), message)); } } @@ -514,8 +517,10 @@ void ChromotingInstance::HandlePolicyUpdate(const std::string policy_json) { initial_policy_received_ = true; enable_client_nat_traversal_ = traversal_policy; - if (delayed_connect_.get()) - plugin_message_loop_->PostTask(FROM_HERE, delayed_connect_.release()); + if (!delayed_connect_.is_null()) { + thread_proxy_->PostTask(FROM_HERE, delayed_connect_); + delayed_connect_.Reset(); + } } } // namespace remoting diff --git a/remoting/client/plugin/chromoting_instance.h b/remoting/client/plugin/chromoting_instance.h index 856f040..d17f371 100644 --- a/remoting/client/plugin/chromoting_instance.h +++ b/remoting/client/plugin/chromoting_instance.h @@ -19,6 +19,7 @@ #include "ppapi/c/pp_var.h" #include "ppapi/cpp/var.h" #include "ppapi/cpp/private/instance_private.h" +#include "remoting/base/scoped_thread_proxy.h" #include "remoting/client/client_context.h" #include "remoting/client/plugin/chromoting_scriptable_object.h" #include "remoting/client/plugin/pepper_plugin_thread_delegate.h" @@ -47,7 +48,6 @@ class JingleThread; class PepperView; class PepperViewProxy; class RectangleUpdateDecoder; -class TaskThreadProxy; struct ClientConfig; @@ -139,9 +139,6 @@ class ChromotingInstance : public pp::InstancePrivate { // True if scale to fit is enabled. bool scale_to_fit_; - // A refcounted class to perform thread-switching for logging tasks. - scoped_refptr<TaskThreadProxy> log_proxy_; - // PepperViewProxy is refcounted and used to interface between chromoting // objects and PepperView and perform thread switching. It wraps around // |view_| and receives method calls on chromoting threads. These method @@ -173,8 +170,8 @@ class ChromotingInstance : public pp::InstancePrivate { // settings. bool initial_policy_received_; - ScopedRunnableMethodFactory<ChromotingInstance> task_factory_; - scoped_ptr<Task> delayed_connect_; + scoped_ptr<ScopedThreadProxy> thread_proxy_; + base::Closure delayed_connect_; DISALLOW_COPY_AND_ASSIGN(ChromotingInstance); }; diff --git a/remoting/host/desktop_environment.cc b/remoting/host/desktop_environment.cc index ada7c2a..3f1bf89 100644 --- a/remoting/host/desktop_environment.cc +++ b/remoting/host/desktop_environment.cc @@ -24,63 +24,6 @@ static const int kContinueWindowHideTimeoutMs = 60 * 1000; namespace remoting { -// UIThreadProxy proxies DesktopEnvironment method calls to the UI -// thread. This is neccessary so that DesktopEnvironment can be -// deleted synchronously even while there are pending tasks on the -// message queue. -// -// TODO(sergeyu): Merge this code with remoting::TaskThreadProxy. The -// problem solved by this class is very simular to the one solved by -// ScopedRunnableMethodFactory. The main difference is that this class -// is thread-safe. Change the interface to make it look more like -// ScopedRunnableMethodFactory and rename it to avoid confusion with -// MessageLoopProxy. -class UIThreadProxy : public base::RefCountedThreadSafe<UIThreadProxy> { - public: - explicit UIThreadProxy(base::MessageLoopProxy* message_loop) - : message_loop_(message_loop) { - } - - // TODO(sergeyu): Rename this method. - void Detach() { - DCHECK(message_loop_->BelongsToCurrentThread()); - message_loop_ = NULL; - } - - void CallOnUIThread(const tracked_objects::Location& from_here, - const base::Closure& closure) { - scoped_refptr<base::MessageLoopProxy> message_loop = message_loop_; - if (message_loop) { - message_loop->PostTask(from_here, base::Bind( - &UIThreadProxy::CallClosure, this, closure)); - } - } - - void CallOnUIThreadDelayed(const tracked_objects::Location& from_here, - const base::Closure& closure, - int delay_ms) { - scoped_refptr<base::MessageLoopProxy> message_loop = message_loop_; - if (message_loop) { - message_loop->PostDelayedTask(from_here, base::Bind( - &UIThreadProxy::CallClosure, this, closure), delay_ms); - } - } - - private: - friend class base::RefCountedThreadSafe<UIThreadProxy>; - - virtual ~UIThreadProxy() { } - - void CallClosure(const base::Closure& closure) { - if (message_loop_) - closure.Run(); - } - - scoped_refptr<base::MessageLoopProxy> message_loop_; - - DISALLOW_COPY_AND_ASSIGN(UIThreadProxy); -}; - // static DesktopEnvironment* DesktopEnvironment::Create(ChromotingHostContext* context) { scoped_ptr<Capturer> capturer(Capturer::Create()); @@ -125,7 +68,7 @@ DesktopEnvironment::DesktopEnvironment(ChromotingHostContext* context, local_input_monitor_(local_input_monitor), is_monitoring_local_inputs_(false), continue_timer_state_(INACTIVE), - proxy_(new UIThreadProxy(context->ui_message_loop())) { + ui_thread_proxy_(context->ui_message_loop()) { } DesktopEnvironment::~DesktopEnvironment() { @@ -139,21 +82,21 @@ void DesktopEnvironment::Shutdown() { ShowContinueWindow(false); StartContinueWindowTimer(false); - proxy_->Detach(); + ui_thread_proxy_.Detach(); } void DesktopEnvironment::OnConnect(const std::string& username) { - proxy_->CallOnUIThread(FROM_HERE, base::Bind( + ui_thread_proxy_.PostTask(FROM_HERE, base::Bind( &DesktopEnvironment::ProcessOnConnect, base::Unretained(this), username)); } void DesktopEnvironment::OnLastDisconnect() { - proxy_->CallOnUIThread(FROM_HERE, base::Bind( + ui_thread_proxy_.PostTask(FROM_HERE, base::Bind( &DesktopEnvironment::ProcessOnLastDisconnect, base::Unretained(this))); } void DesktopEnvironment::OnPause(bool pause) { - proxy_->CallOnUIThread(FROM_HERE, base::Bind( + ui_thread_proxy_.PostTask(FROM_HERE, base::Bind( &DesktopEnvironment::ProcessOnPause, base::Unretained(this), pause)); } @@ -221,7 +164,7 @@ void DesktopEnvironment::StartContinueWindowTimer(bool start) { if (start && continue_timer_state_ == INACTIVE) { continue_timer_target_time_ = base::Time::Now() + base::TimeDelta::FromMilliseconds(kContinueWindowShowTimeoutMs); - proxy_->CallOnUIThreadDelayed( + ui_thread_proxy_.PostDelayedTask( FROM_HERE, base::Bind(&DesktopEnvironment::ContinueWindowTimerFunc, base::Unretained(this)), kContinueWindowShowTimeoutMs); @@ -249,7 +192,7 @@ void DesktopEnvironment::ContinueWindowTimerFunc() { ShowContinueWindow(true); continue_timer_target_time_ = base::Time::Now() + base::TimeDelta::FromMilliseconds(kContinueWindowHideTimeoutMs); - proxy_->CallOnUIThreadDelayed( + ui_thread_proxy_.PostDelayedTask( FROM_HERE, base::Bind(&DesktopEnvironment::ContinueWindowTimerFunc, base::Unretained(this)), kContinueWindowHideTimeoutMs); diff --git a/remoting/host/desktop_environment.h b/remoting/host/desktop_environment.h index 0fc00c9..e0ed196 100644 --- a/remoting/host/desktop_environment.h +++ b/remoting/host/desktop_environment.h @@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/time.h" +#include "remoting/base/scoped_thread_proxy.h" namespace remoting { @@ -22,7 +23,6 @@ class Curtain; class DisconnectWindow; class EventExecutor; class LocalInputMonitor; -class UIThreadProxy; class DesktopEnvironment { public: @@ -114,7 +114,7 @@ class DesktopEnvironment { ContinueTimerState continue_timer_state_; base::Time continue_timer_target_time_; - scoped_refptr<UIThreadProxy> proxy_; + ScopedThreadProxy ui_thread_proxy_; DISALLOW_COPY_AND_ASSIGN(DesktopEnvironment); }; diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 6f1fa50..d79b8bb 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -396,8 +396,8 @@ 'base/rate_counter.h', 'base/running_average.cc', 'base/running_average.h', - 'base/task_thread_proxy.cc', - 'base/task_thread_proxy.h', + 'base/scoped_thread_proxy.cc', + 'base/scoped_thread_proxy.h', 'base/util.cc', 'base/util.h', ], |