Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_ | |
| 6 #define MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_ | |
| 7 | |
| 8 #include <assert.h> | |
| 9 #include <stdio.h> | |
| 10 | |
| 11 #include <algorithm> | |
| 12 | |
| 13 #include "mojo/public/cpp/bindings/error_handler.h" | |
| 14 #include "mojo/public/cpp/bindings/lib/interface_ptr_internal.h" | |
| 15 #include "mojo/public/cpp/system/macros.h" | |
| 16 | |
| 17 namespace mojo { | |
| 18 | |
| 19 template <typename Interface> | |
| 20 class InterfacePtr { | |
| 21 MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InterfacePtr, RValue) | |
| 22 public: | |
| 23 InterfacePtr() {} | |
| 24 explicit InterfacePtr(Interface* impl) { state_.impl = impl; } | |
| 25 | |
| 26 InterfacePtr(RValue other) { other.object->state_.Swap(&state_); } | |
| 27 InterfacePtr& operator=(RValue other) { | |
| 28 other.object->state_.Swap(&state_); | |
| 29 return *this; | |
| 30 } | |
| 31 | |
| 32 ~InterfacePtr() {} | |
| 33 | |
| 34 Interface* get() const { | |
| 35 return state_.impl; | |
| 36 } | |
| 37 Interface* operator->() const { return get(); } | |
| 38 Interface* operator*() const { return get(); } | |
| 39 | |
| 40 void reset() { | |
| 41 State doomed; | |
| 42 state_.Swap(&doomed); | |
| 43 } | |
| 44 | |
| 45 void Bind(Interface* impl) { | |
| 46 reset(); | |
| 47 state_.impl = impl; | |
| 48 } | |
| 49 | |
| 50 bool encountered_error() const; | |
| 51 | |
| 52 void set_error_handler(ErrorHandler* error_handler) { | |
| 53 assert(state_.context); | |
| 54 state_.context->router()->set_error_handler(error_handler); | |
| 55 } | |
| 56 | |
| 57 // XXX figure out how to hide these! | |
| 58 | |
| 59 bool has_context() const { return !!state_.context; } | |
| 60 | |
| 61 void ConfigureProxy(ScopedMessagePipeHandle handle, | |
| 62 MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) { | |
| 63 assert(!state_.impl); | |
| 64 assert(!state_.context); | |
| 65 | |
| 66 internal::InterfacePtrContext* context = | |
| 67 new internal::InterfacePtrContext(handle.Pass(), waiter); | |
| 68 ProxyWithStub* proxy = new ProxyWithStub(context->router()); | |
| 69 context->router()->set_incoming_receiver(&proxy->stub); | |
| 70 | |
| 71 state_.impl = proxy; | |
| 72 state_.context = context; | |
| 73 } | |
| 74 | |
| 75 void ConfigureStub(ScopedMessagePipeHandle handle, | |
| 76 MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) { | |
| 77 assert(state_.impl); // Should have already been set! | |
| 78 assert(!state_.context); | |
| 79 | |
| 80 // Stub for binding to state_.impl | |
| 81 // Proxy for communicating to the client on the other end of the pipe. | |
| 82 | |
| 83 internal::InterfacePtrContext* context = | |
| 84 new internal::InterfacePtrContext(handle.Pass(), waiter); | |
| 85 ClientProxyWithStub* proxy = new ClientProxyWithStub(context->router()); | |
| 86 proxy->stub.set_sink(state_.impl); | |
| 87 context->router()->set_incoming_receiver(&proxy->stub); | |
| 88 | |
| 89 state_.impl->SetClient(proxy); | |
| 90 | |
| 91 state_.client = proxy; | |
| 92 state_.context = context; | |
| 93 } | |
| 94 | |
| 95 void Detach() { | |
| 96 new DetachedState(&state_); | |
| 97 } | |
| 98 | |
| 99 internal::Router* router_for_testing() { return state_.context->router(); } | |
| 100 | |
| 101 private: | |
| 102 class ProxyWithStub : public Interface::Proxy_ { | |
| 103 public: | |
| 104 explicit ProxyWithStub(MessageReceiver* receiver) | |
| 105 : Interface::Proxy_(receiver) { | |
| 106 } | |
| 107 virtual void SetClient(typename Interface::Client_* client) MOJO_OVERRIDE { | |
| 108 stub.set_sink(client); | |
| 109 } | |
| 110 typename Interface::Client_::Stub_ stub; | |
| 111 private: | |
| 112 MOJO_DISALLOW_COPY_AND_ASSIGN(ProxyWithStub); | |
| 113 }; | |
| 114 | |
| 115 class ClientProxyWithStub : public Interface::Client_::Proxy_ { | |
| 116 public: | |
| 117 explicit ClientProxyWithStub(MessageReceiver* receiver) | |
| 118 : Interface::Client_::Proxy_(receiver) { | |
| 119 } | |
| 120 typename Interface::Stub_ stub; | |
| 121 private: | |
| 122 MOJO_DISALLOW_COPY_AND_ASSIGN(ClientProxyWithStub); | |
| 123 }; | |
| 124 | |
| 125 struct State { | |
| 126 State() : impl(NULL), client(NULL), context(NULL) {} | |
| 127 | |
| 128 ~State() { | |
| 129 // Destruction order matters here. We delete |impl| first, even though | |
| 130 // |context| may have a reference to it, so that |~Interface| may have a | |
| 131 // shot at generating new outbound messages (ie, nvoking client methods). | |
| 132 delete impl; | |
| 133 delete context; | |
| 134 delete client; | |
| 135 } | |
| 136 | |
| 137 void Swap(State* other) { | |
| 138 std::swap(other->impl, impl); | |
| 139 std::swap(other->client, client); | |
| 140 std::swap(other->context, context); | |
| 141 } | |
| 142 | |
| 143 Interface* impl; | |
| 144 typename Interface::Client_* client; | |
| 145 internal::InterfacePtrContext* context; | |
| 146 | |
| 147 MOJO_DISALLOW_COPY_AND_ASSIGN(State); | |
| 148 }; | |
| 149 | |
| 150 class DetachedState : public ErrorHandler { | |
| 151 public: | |
| 152 explicit DetachedState(State* state) { | |
| 153 internal::LogDetachedState(this, +1); | |
| 154 | |
| 155 state_.Swap(state); | |
| 156 | |
| 157 assert(state_.context); | |
| 158 assert(!state_.context->router()->encountered_error()); | |
| 159 | |
| 160 // Register to observe when the pipe is broken. | |
| 161 state_.context->router()->set_error_handler(this); | |
| 162 } | |
| 163 | |
| 164 virtual void OnError() MOJO_OVERRIDE { | |
| 165 internal::LogDetachedState(this, -1); | |
| 166 | |
| 167 delete this; | |
| 168 } | |
| 169 | |
| 170 private: | |
| 171 State state_; | |
| 172 | |
| 173 MOJO_DISALLOW_COPY_AND_ASSIGN(DetachedState); | |
| 174 }; | |
| 175 | |
| 176 State state_; | |
| 177 }; | |
| 178 | |
| 179 // Takes a handle to the proxy end-point of a pipe. On the other end is | |
| 180 // presumed to be an interface implementation of type |Interface|. Returns a | |
| 181 // generated proxy to that interface, which may be used on the current thread. | |
| 182 // It is valid to call SetClient on the returned Interface to set an instance | |
| 183 // of Interface::Client. | |
| 184 // | |
|
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
| |
| 185 // XXX not sure if MakeProxy is the best name here. | |
| 186 template <typename Interface> | |
| 187 InterfacePtr<Interface> MakeProxy( | |
| 188 ScopedMessagePipeHandle handle, | |
| 189 MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) { | |
| 190 InterfacePtr<Interface> ptr; | |
| 191 if (handle.is_valid()) | |
| 192 ptr.ConfigureProxy(handle.Pass(), waiter); | |
| 193 return ptr.Pass(); | |
| 194 } | |
| 195 | |
| 196 // Takes a heap-allocated interface implementation and binds its lifetime to | |
| 197 // that of a MessagePipe. A handle to the proxy end-point of the pipe is | |
| 198 // returned. If that pipe is closed, then the interface implementation will be | |
| 199 // deleted. | |
| 200 // | |
| 201 // The interface implementation is also bound to the current thread. Its | |
| 202 // methods will only be called on the current thread, and if the current thread | |
| 203 // exits, then it will also be deleted and its end point of the pipe will be | |
| 204 // closed. | |
| 205 // | |
| 206 // Before returning the interface implementation will receive a SetClient call, | |
| 207 // providing it with a proxy to the client on the other end of the pipe. | |
| 208 // | |
| 209 // XXX not sure if BindToPipe is the best name here. | |
| 210 template <typename Interface> | |
| 211 ScopedMessagePipeHandle BindToPipe(Interface* impl) { | |
| 212 InterfacePtr<Interface> ptr(impl); | |
| 213 MessagePipe pipe; | |
| 214 ptr.ConfigureStub(pipe.handle0.Pass()); | |
| 215 ptr.Detach(); | |
| 216 return pipe.handle1.Pass(); | |
| 217 } | |
| 218 | |
| 219 } // namespace mojo | |
| 220 | |
| 221 #endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_ | |
| OLD | NEW |