| 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
|
|
|
|
|