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