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

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

Issue 265793015: Mojo: Replace RemotePtr with InterfacePtr and InterfaceImpl (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 7 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
Index: mojo/public/cpp/bindings/interface_ptr.h
diff --git a/mojo/public/cpp/bindings/interface_ptr.h b/mojo/public/cpp/bindings/interface_ptr.h
new file mode 100644
index 0000000000000000000000000000000000000000..1e0bc24b55f0da6ef05dd85a6147fe37bab608b8
--- /dev/null
+++ b/mojo/public/cpp/bindings/interface_ptr.h
@@ -0,0 +1,221 @@
+// Copyright 2014 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_INTERFACE_PTR_H_
+#define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <algorithm>
+
+#include "mojo/public/cpp/bindings/error_handler.h"
+#include "mojo/public/cpp/bindings/lib/interface_ptr_internal.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+template <typename Interface>
+class InterfacePtr {
+ MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InterfacePtr, RValue)
+ public:
+ InterfacePtr() {}
+ explicit InterfacePtr(Interface* impl) { state_.impl = impl; }
+
+ InterfacePtr(RValue other) { other.object->state_.Swap(&state_); }
+ InterfacePtr& operator=(RValue other) {
+ other.object->state_.Swap(&state_);
+ return *this;
+ }
+
+ ~InterfacePtr() {}
+
+ Interface* get() const {
+ return state_.impl;
+ }
+ Interface* operator->() const { return get(); }
+ Interface* operator*() const { return get(); }
+
+ void reset() {
+ State doomed;
+ state_.Swap(&doomed);
+ }
+
+ void Bind(Interface* impl) {
+ reset();
+ state_.impl = impl;
+ }
+
+ bool encountered_error() const;
+
+ void set_error_handler(ErrorHandler* error_handler) {
+ assert(state_.context);
+ state_.context->router()->set_error_handler(error_handler);
+ }
+
+ // XXX figure out how to hide these!
+
+ bool has_context() const { return !!state_.context; }
+
+ void ConfigureProxy(ScopedMessagePipeHandle handle,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
+ assert(!state_.impl);
+ assert(!state_.context);
+
+ internal::InterfacePtrContext* context =
+ new internal::InterfacePtrContext(handle.Pass(), waiter);
+ ProxyWithStub* proxy = new ProxyWithStub(context->router());
+ context->router()->set_incoming_receiver(&proxy->stub);
+
+ state_.impl = proxy;
+ state_.context = context;
+ }
+
+ void ConfigureStub(ScopedMessagePipeHandle handle,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
+ assert(state_.impl); // Should have already been set!
+ assert(!state_.context);
+
+ // Stub for binding to state_.impl
+ // Proxy for communicating to the client on the other end of the pipe.
+
+ internal::InterfacePtrContext* context =
+ new internal::InterfacePtrContext(handle.Pass(), waiter);
+ ClientProxyWithStub* proxy = new ClientProxyWithStub(context->router());
+ proxy->stub.set_sink(state_.impl);
+ context->router()->set_incoming_receiver(&proxy->stub);
+
+ state_.impl->SetClient(proxy);
+
+ state_.client = proxy;
+ state_.context = context;
+ }
+
+ void Detach() {
+ new DetachedState(&state_);
+ }
+
+ internal::Router* router_for_testing() { return state_.context->router(); }
+
+ private:
+ class ProxyWithStub : public Interface::Proxy_ {
+ public:
+ explicit ProxyWithStub(MessageReceiver* receiver)
+ : Interface::Proxy_(receiver) {
+ }
+ virtual void SetClient(typename Interface::Client_* client) MOJO_OVERRIDE {
+ stub.set_sink(client);
+ }
+ typename Interface::Client_::Stub_ stub;
+ private:
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ProxyWithStub);
+ };
+
+ class ClientProxyWithStub : public Interface::Client_::Proxy_ {
+ public:
+ explicit ClientProxyWithStub(MessageReceiver* receiver)
+ : Interface::Client_::Proxy_(receiver) {
+ }
+ typename Interface::Stub_ stub;
+ private:
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ClientProxyWithStub);
+ };
+
+ struct State {
+ State() : impl(NULL), client(NULL), context(NULL) {}
+
+ ~State() {
+ // Destruction order matters here. We delete |impl| first, even though
+ // |context| may have a reference to it, so that |~Interface| may have a
+ // shot at generating new outbound messages (ie, nvoking client methods).
+ delete impl;
+ delete context;
+ delete client;
+ }
+
+ void Swap(State* other) {
+ std::swap(other->impl, impl);
+ std::swap(other->client, client);
+ std::swap(other->context, context);
+ }
+
+ Interface* impl;
+ typename Interface::Client_* client;
+ internal::InterfacePtrContext* context;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(State);
+ };
+
+ class DetachedState : public ErrorHandler {
+ public:
+ explicit DetachedState(State* state) {
+ internal::LogDetachedState(this, +1);
+
+ state_.Swap(state);
+
+ assert(state_.context);
+ assert(!state_.context->router()->encountered_error());
+
+ // Register to observe when the pipe is broken.
+ state_.context->router()->set_error_handler(this);
+ }
+
+ virtual void OnError() MOJO_OVERRIDE {
+ internal::LogDetachedState(this, -1);
+
+ delete this;
+ }
+
+ private:
+ State state_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(DetachedState);
+ };
+
+ State state_;
+};
+
+// Takes a handle to the proxy end-point of a pipe. On the other end is
+// presumed to be an interface implementation of type |Interface|. Returns a
+// generated proxy to that interface, which may be used on the current thread.
+// It is valid to call SetClient on the returned Interface to set an instance
+// of Interface::Client.
+//
DaveMoore 2014/05/06 21:30:54 Maybe there should be a variant of this that takes
darin (slow to review) 2014/05/06 21:39:11 Yeah, that's something I've been considering as we
+// XXX not sure if MakeProxy is the best name here.
+template <typename Interface>
+InterfacePtr<Interface> MakeProxy(
+ ScopedMessagePipeHandle handle,
+ MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
+ InterfacePtr<Interface> ptr;
+ if (handle.is_valid())
+ ptr.ConfigureProxy(handle.Pass(), waiter);
+ return ptr.Pass();
+}
+
+// Takes a heap-allocated interface implementation and binds its lifetime to
+// that of a MessagePipe. A handle to the proxy end-point of the pipe is
+// returned. If that pipe is closed, then the interface implementation will be
+// deleted.
+//
+// The interface implementation is also bound to the current thread. Its
+// methods will only be called on the current thread, and if the current thread
+// exits, then it will also be deleted and its end point of the pipe will be
+// closed.
+//
+// Before returning the interface implementation will receive a SetClient call,
+// providing it with a proxy to the client on the other end of the pipe.
+//
+// XXX not sure if BindToPipe is the best name here.
+template <typename Interface>
+ScopedMessagePipeHandle BindToPipe(Interface* impl) {
+ InterfacePtr<Interface> ptr(impl);
+ MessagePipe pipe;
+ ptr.ConfigureStub(pipe.handle0.Pass());
+ ptr.Detach();
+ return pipe.handle1.Pass();
+}
+
+} // namespace mojo
+
+#endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_

Powered by Google App Engine
This is Rietveld 408576698