Chromium Code Reviews| Index: mojo/public/cpp/bindings/thread_safe_interface_ptr.h |
| diff --git a/mojo/public/cpp/bindings/thread_safe_interface_ptr.h b/mojo/public/cpp/bindings/thread_safe_interface_ptr.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ef7801620ebb9b4b914d332e13e1da0755561847 |
| --- /dev/null |
| +++ b/mojo/public/cpp/bindings/thread_safe_interface_ptr.h |
| @@ -0,0 +1,113 @@ |
| +// Copyright 2016 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 MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ |
| +#define MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ |
| + |
| +namespace mojo { |
| + |
| +#include <memory> |
| + |
| +#include "base/callback.h" |
| +#include "base/macros.h" |
| +#include "base/memory/ref_counted.h" |
| +#include "base/task_runner.h" |
| +#include "base/threading/thread_task_runner_handle.h" |
| +#include "mojo/public/cpp/bindings/message.h" |
| + |
| +namespace internal { |
| +template <typename Interface, bool use_multiplex_router> |
| +class InterfacePtrState; |
| +} |
| + |
| +// ThreadSafeInterfacePtr is a version of InterfacePtr that lets caller invoke |
| +// interface methods from any threads. Callbacks are called on the thread that |
| +// made the interface call. |
| +// To create a ThreadSafeInterfacePtr, create a regular InterfacePtr and then |
| +// retrieve a ThreadSafeInterfacePtr with InterfacePtr::GetThreadSafePtr() (this |
| +// must be done on one thread). You can then use the ThreadSafeInterfacePtr from |
| +// any thread. |
|
yzshen1
2016/11/11 22:32:10
Please consider adding comments about whether the
Jay Civelli
2016/11/15 05:02:30
Updated that comment based on the modified design
|
| +template <typename Interface> |
| +class ThreadSafeInterfacePtr : public MessageReceiverWithResponder, |
| + public base::RefCountedThreadSafe<ThreadSafeInterfacePtr<Interface>> { |
|
darin (slow to review)
2016/11/12 04:09:23
Does this class need to be ref-counted? Can it be
Jay Civelli
2016/11/15 05:02:30
After discussing with @yzshen1 we think it makes m
|
| + public: |
| + using ProxyType = typename Interface::Proxy_; |
| + |
| + using AcceptCallback = base::Callback<void(Message)>; |
| + using AcceptWithResponderCallback = |
| + base::Callback<void(Message, std::unique_ptr<MessageReceiver>)>; |
| + |
| + Interface* get_interface() { return &proxy_; } |
|
yzshen1
2016/11/11 22:32:10
Does it make sense to name it "get()" to be more c
Jay Civelli
2016/11/15 05:02:30
Very good point. Done.
|
| + |
| + private: |
| + friend class base::RefCountedThreadSafe<ThreadSafeInterfacePtr<Interface>>; |
| + friend class internal::InterfacePtrState<Interface, true>; |
| + |
| + ThreadSafeInterfacePtr( |
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| + const AcceptCallback& accept_callback, |
| + const AcceptWithResponderCallback& accept_with_responder_callback) |
| + : task_runner_(task_runner), |
| + proxy_(this), |
| + accept_callback_(accept_callback), |
| + accept_with_responder_callback_(accept_with_responder_callback) { |
| + } |
| + |
| + // MessageReceiverWithResponder implementation: |
| + bool Accept(Message* message) override { |
| + task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(accept_callback_, base::Passed(std::move(*message)))); |
| + return true; |
| + } |
| + |
| + bool AcceptWithResponder(Message* message, |
| + MessageReceiver* responder) override { |
| + auto forward_responder = base::MakeUnique<ForwardToCallingThread>( |
| + base::WrapUnique(responder)); |
| + task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(accept_with_responder_callback_, |
| + base::Passed(std::move(*message)), |
| + base::Passed(std::move(forward_responder)))); |
| + return true; |
| + } |
| + |
| + class ForwardToCallingThread : public MessageReceiver { |
| + public: |
| + explicit ForwardToCallingThread(std::unique_ptr<MessageReceiver> responder) |
| + : responder_(std::move(responder)), |
| + task_runner_(base::ThreadTaskRunnerHandle::Get()) { |
| + } |
| + |
| + private: |
| + bool Accept(Message* message) { |
| + // The current instance will be deleted when this method returns, so we |
| + // have to relinquish the responder so it does not get deleted. |
| + task_runner_->PostTask(FROM_HERE, |
| + base::Bind(&ForwardToCallingThread::CallAcceptAndDeleteResponder, |
| + base::Passed(std::move(responder_)), |
| + base::Passed(std::move(*message)))); |
| + return true; |
| + } |
| + |
| + static void CallAcceptAndDeleteResponder( |
| + std::unique_ptr<MessageReceiver> responder, |
| + Message message) { |
| + ignore_result(responder->Accept(&message)); |
| + } |
| + |
| + std::unique_ptr<MessageReceiver> responder_; |
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| + }; |
| + |
| + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; |
| + ProxyType proxy_; |
| + AcceptCallback accept_callback_; |
| + AcceptWithResponderCallback accept_with_responder_callback_; |
| +}; |
| + |
| +} // namespace mojo |
| + |
| +#endif // MOJO_PUBLIC_CPP_BINDINGS_THREAD_SAFE_INTERFACE_PTR_H_ |