Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Unified Diff: mojo/public/cpp/bindings/thread_safe_interface_ptr.h

Issue 2668153003: Mojo C++ Bindings: Eliminate unbound ThreadSafeInterfacePtr (Closed)
Patch Set: format and rebase... Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc ('k') | remoting/host/BUILD.gn » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
index 605bddda1376bb97f2beef559129afe9169342db..f475c1f12e1ac738f4482ca2a977ab2e5a6570bd 100644
--- a/mojo/public/cpp/bindings/thread_safe_interface_ptr.h
+++ b/mojo/public/cpp/bindings/thread_safe_interface_ptr.h
@@ -18,134 +18,55 @@
namespace mojo {
-struct ThreadSafeInterfacePtrDeleter;
-
-// ThreadSafeInterfacePtr and ThreadSafeAssociatedInterfacePtr are versions of
-// InterfacePtr and AssociatedInterfacePtr that let callers invoke
-// interface methods from any threads. Callbacks are received on the thread that
-// performed the interface call.
-//
-// To create a ThreadSafeInterfacePtr/ThreadSafeAssociatedInterfacePtr, first
-// create a regular InterfacePtr/AssociatedInterfacePtr that
-// you then provide to ThreadSafeInterfacePtr/AssociatedInterfacePtr::Create.
-// You can then call methods on the
-// ThreadSafeInterfacePtr/AssociatedInterfacePtr instance from any thread.
-//
-// Ex for ThreadSafeInterfacePtr:
-// frob::FrobinatorPtr frobinator;
-// frob::FrobinatorImpl impl(MakeRequest(&frobinator));
-// scoped_refptr<frob::ThreadSafeFrobinatorPtr> thread_safe_frobinator =
-// frob::ThreadSafeFrobinatorPtr::Create(std::move(frobinator));
-// (*thread_safe_frobinator)->FrobinateToTheMax();
-//
-// An alternate way is to create the ThreadSafeInterfacePtr unbound (not
-// associated with an InterfacePtr) and call Bind() at a later time when the
-// InterfacePtr becomes available. Note that you shouldn't call any interface
-// methods on the ThreadSafeInterfacePtr before it is bound.
-
-template <typename Interface, template <typename> class InterfacePtrType>
-class ThreadSafeInterfacePtrBase
- : public MessageReceiverWithResponder,
- public base::RefCountedThreadSafe<
- ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>,
- ThreadSafeInterfacePtrDeleter> {
+// Instances of this class may be used from any thread to serialize |Interface|
+// messages and forward them elsewhere. In general you should use one of the
+// ThreadSafeInterfacePtrBase helper aliases defined below, but this type may be
+// useful if you need/want to manually manage the lifetime of the underlying
+// proxy object which will be used to ultimately send messages.
+template <typename Interface>
+class ThreadSafeForwarder : public MessageReceiverWithResponder {
public:
using ProxyType = typename Interface::Proxy_;
-
- static scoped_refptr<ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>>
- Create(InterfacePtrType<Interface> interface_ptr) {
- scoped_refptr<ThreadSafeInterfacePtrBase> ptr(
- new ThreadSafeInterfacePtrBase());
- return ptr->Bind(std::move(interface_ptr)) ? ptr : nullptr;
- }
-
- // Creates a ThreadSafeInterfacePtrBase with no associated InterfacePtr.
- // Call Bind() with the InterfacePtr once available, which must be called on
- // the |bind_task_runner|.
- // Providing the TaskRunner here allows you to post a task to
- // |bind_task_runner| to do the bind and then immediately start calling
- // methods on the returned interface.
- static scoped_refptr<ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>>
- CreateUnbound(
- const scoped_refptr<base::SingleThreadTaskRunner>& bind_task_runner) {
- scoped_refptr<ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>> ptr =
- new ThreadSafeInterfacePtrBase();
- ptr->interface_ptr_task_runner_ = bind_task_runner;
- return ptr;
- }
-
- // Binds a ThreadSafeInterfacePtrBase previously created with CreateUnbound().
- // This must be called on the thread that |interface_ptr| should be used.
- // If created with CreateUnbound() that thread should be the same as the one
- // provided at creation time.
- bool Bind(InterfacePtrType<Interface> interface_ptr) {
- DCHECK(!interface_ptr_task_runner_ ||
- interface_ptr_task_runner_ == base::ThreadTaskRunnerHandle::Get());
- if (!interface_ptr.is_bound()) {
- LOG(ERROR) << "Attempting to bind a ThreadSafe[Associated]InterfacePtr "
- "from an unbound InterfacePtr.";
- return false;
- }
- interface_ptr_ = std::move(interface_ptr);
- interface_ptr_task_runner_ = base::ThreadTaskRunnerHandle::Get();
- return true;
- }
-
- ~ThreadSafeInterfacePtrBase() override {}
-
- Interface* get() { return &proxy_; }
- Interface* operator->() { return get(); }
- Interface& operator*() { return *get(); }
+ using ForwardMessageCallback = base::Callback<void(Message)>;
+ using ForwardMessageWithResponderCallback =
+ base::Callback<void(Message, std::unique_ptr<MessageReceiver>)>;
+
+ // Constructs a ThreadSafeForwarder through which Messages are forwarded to
+ // |forward| or |forward_with_responder| by posting to |task_runner|.
+ //
+ // Any message sent through this forwarding interface will dispatch its reply,
+ // if any, back to the thread which called the corresponding interface method.
+ ThreadSafeForwarder(
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner,
+ const ForwardMessageCallback& forward,
+ const ForwardMessageWithResponderCallback& forward_with_responder)
+ : proxy_(this),
+ task_runner_(task_runner),
+ forward_(forward),
+ forward_with_responder_(forward_with_responder) {}
+
+ ~ThreadSafeForwarder() override {}
+
+ ProxyType& proxy() { return proxy_; }
private:
- friend class base::RefCountedThreadSafe<
- ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>>;
- friend struct ThreadSafeInterfacePtrDeleter;
-
- ThreadSafeInterfacePtrBase() : proxy_(this), weak_ptr_factory_(this) {}
-
- void DeleteOnCorrectThread() const {
- if (interface_ptr_task_runner_ &&
- !interface_ptr_task_runner_->BelongsToCurrentThread() &&
- interface_ptr_task_runner_->DeleteSoon(FROM_HERE, this)) {
- return;
- }
- delete this;
- }
-
// MessageReceiverWithResponder implementation:
bool Accept(Message* message) override {
- interface_ptr_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&ThreadSafeInterfacePtrBase::AcceptOnInterfacePtrThread,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(std::move(*message))));
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(forward_, base::Passed(message)));
return true;
}
bool AcceptWithResponder(Message* message,
- MessageReceiver* responder) override {
- auto forward_responder = base::MakeUnique<ForwardToCallingThread>(
- base::WrapUnique(responder));
- interface_ptr_task_runner_->PostTask(
- FROM_HERE, base::Bind(&ThreadSafeInterfacePtrBase::
- AcceptWithResponderOnInterfacePtrThread,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(std::move(*message)),
- base::Passed(std::move(forward_responder))));
+ MessageReceiver* response_receiver) override {
+ auto responder = base::MakeUnique<ForwardToCallingThread>(
+ base::WrapUnique(response_receiver));
+ task_runner_->PostTask(
+ FROM_HERE, base::Bind(forward_with_responder_, base::Passed(message),
+ base::Passed(&responder)));
return true;
}
- void AcceptOnInterfacePtrThread(Message message) {
- interface_ptr_.internal_state()->ForwardMessage(std::move(message));
- }
- void AcceptWithResponderOnInterfacePtrThread(
- Message message,
- std::unique_ptr<MessageReceiver> responder) {
- interface_ptr_.internal_state()->ForwardMessageWithResponder(
- std::move(message), std::move(responder));
- }
-
class ForwardToCallingThread : public MessageReceiver {
public:
explicit ForwardToCallingThread(std::unique_ptr<MessageReceiver> responder)
@@ -175,28 +96,143 @@ class ThreadSafeInterfacePtrBase
scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
};
- scoped_refptr<base::SingleThreadTaskRunner> interface_ptr_task_runner_;
ProxyType proxy_;
- InterfacePtrType<Interface> interface_ptr_;
- base::WeakPtrFactory<ThreadSafeInterfacePtrBase> weak_ptr_factory_;
+ const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ const ForwardMessageCallback forward_;
+ const ForwardMessageWithResponderCallback forward_with_responder_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThreadSafeForwarder);
};
-struct ThreadSafeInterfacePtrDeleter {
- template <typename Interface, template <typename> class InterfacePtrType>
- static void Destruct(
- const ThreadSafeInterfacePtrBase<Interface, InterfacePtrType>*
- interface_ptr) {
- interface_ptr->DeleteOnCorrectThread();
+template <typename InterfacePtrType>
+class ThreadSafeInterfacePtrBase
+ : public base::RefCountedThreadSafe<
+ ThreadSafeInterfacePtrBase<InterfacePtrType>> {
+ public:
+ using InterfaceType = typename InterfacePtrType::InterfaceType;
+ using PtrInfoType = typename InterfacePtrType::PtrInfoType;
+
+ explicit ThreadSafeInterfacePtrBase(
+ std::unique_ptr<ThreadSafeForwarder<InterfaceType>> forwarder)
+ : forwarder_(std::move(forwarder)) {}
+
+ // Creates a ThreadSafeInterfacePtrBase wrapping an underlying non-thread-safe
+ // InterfacePtrType which is bound to the calling thread. All messages sent
+ // via this thread-safe proxy will internally be sent by first posting to this
+ // (the calling) thread's TaskRunner.
+ static scoped_refptr<ThreadSafeInterfacePtrBase> Create(
+ InterfacePtrType interface_ptr) {
+ scoped_refptr<PtrWrapper> wrapper =
+ new PtrWrapper(std::move(interface_ptr));
+ return new ThreadSafeInterfacePtrBase(wrapper->CreateForwarder());
+ }
+
+ // Creates a ThreadSafeInterfacePtrBase which binds the underlying
+ // non-thread-safe InterfacePtrType on the specified TaskRunner. All messages
+ // sent via this thread-safe proxy will internally be sent by first posting to
+ // that TaskRunner.
+ static scoped_refptr<ThreadSafeInterfacePtrBase> Create(
+ PtrInfoType ptr_info,
+ const scoped_refptr<base::SingleThreadTaskRunner>& bind_task_runner) {
+ scoped_refptr<PtrWrapper> wrapper = new PtrWrapper(bind_task_runner);
+ wrapper->BindOnTaskRunner(std::move(ptr_info));
+ return new ThreadSafeInterfacePtrBase(wrapper->CreateForwarder());
}
+
+ InterfaceType* get() { return &forwarder_->proxy(); }
+ InterfaceType* operator->() { return get(); }
+ InterfaceType& operator*() { return *get(); }
+
+ private:
+ friend class base::RefCountedThreadSafe<
+ ThreadSafeInterfacePtrBase<InterfacePtrType>>;
+
+ struct PtrWrapperDeleter;
+
+ // Helper class which owns an |InterfacePtrType| instance on an appropriate
+ // thread. This is kept alive as long its bound within some
+ // ThreadSafeForwarder's callbacks.
+ class PtrWrapper
+ : public base::RefCountedThreadSafe<PtrWrapper, PtrWrapperDeleter> {
+ public:
+ explicit PtrWrapper(InterfacePtrType ptr)
+ : PtrWrapper(base::ThreadTaskRunnerHandle::Get()) {
+ ptr_ = std::move(ptr);
+ }
+
+ explicit PtrWrapper(
+ const scoped_refptr<base::SequencedTaskRunner>& task_runner)
+ : task_runner_(task_runner) {}
+
+ void BindOnTaskRunner(PtrInfoType ptr_info) {
+ task_runner_->PostTask(FROM_HERE, base::Bind(&PtrWrapper::Bind, this,
+ base::Passed(&ptr_info)));
+ }
+
+ std::unique_ptr<ThreadSafeForwarder<InterfaceType>> CreateForwarder() {
+ return base::MakeUnique<ThreadSafeForwarder<InterfaceType>>(
+ task_runner_, base::Bind(&PtrWrapper::Accept, this),
+ base::Bind(&PtrWrapper::AcceptWithResponder, this));
+ }
+
+ private:
+ friend struct PtrWrapperDeleter;
+
+ ~PtrWrapper() {}
+
+ void Bind(PtrInfoType ptr_info) {
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+ ptr_.Bind(std::move(ptr_info));
+ }
+
+ void Accept(Message message) {
+ ptr_.internal_state()->ForwardMessage(std::move(message));
+ }
+
+ void AcceptWithResponder(Message message,
+ std::unique_ptr<MessageReceiver> responder) {
+ ptr_.internal_state()->ForwardMessageWithResponder(std::move(message),
+ std::move(responder));
+ }
+
+ void DeleteOnCorrectThread() const {
+ if (!task_runner_->RunsTasksOnCurrentThread()) {
+ // NOTE: This is only called when there are no more references to
+ // |this|, so binding it unretained is both safe and necessary.
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&PtrWrapper::DeleteOnCorrectThread,
+ base::Unretained(this)));
+ } else {
+ delete this;
+ }
+ }
+
+ InterfacePtrType ptr_;
+ const scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(PtrWrapper);
+ };
+
+ struct PtrWrapperDeleter {
+ static void Destruct(const PtrWrapper* interface_ptr) {
+ interface_ptr->DeleteOnCorrectThread();
+ }
+ };
+
+ ~ThreadSafeInterfacePtrBase() {}
+
+ const std::unique_ptr<ThreadSafeForwarder<InterfaceType>> forwarder_;
+
+ DISALLOW_COPY_AND_ASSIGN(ThreadSafeInterfacePtrBase);
};
template <typename Interface>
using ThreadSafeAssociatedInterfacePtr =
- ThreadSafeInterfacePtrBase<Interface, AssociatedInterfacePtr>;
+ ThreadSafeInterfacePtrBase<AssociatedInterfacePtr<Interface>>;
template <typename Interface>
using ThreadSafeInterfacePtr =
- ThreadSafeInterfacePtrBase<Interface, InterfacePtr>;
+ ThreadSafeInterfacePtrBase<InterfacePtr<Interface>>;
} // namespace mojo
« no previous file with comments | « mojo/public/cpp/bindings/tests/interface_ptr_unittest.cc ('k') | remoting/host/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698