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 10 #include <algorithm> 11 12 #include "mojo/public/cpp/bindings/error_handler.h" 13 #include "mojo/public/cpp/bindings/lib/interface_ptr_internal.h" 14 #include "mojo/public/cpp/environment/environment.h" 15 #include "mojo/public/cpp/system/macros.h" 16 17 namespace mojo { 18 class ErrorHandler; 19 20 // InterfacePtr represents a proxy to a remote instance of an interface. 21 template <typename Interface> 22 class InterfacePtr { MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InterfacePtr,RValue)23 MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InterfacePtr, RValue) 24 public: 25 InterfacePtr() {} 26 InterfacePtr(RValue other)27 InterfacePtr(RValue other) { 28 internal_state_.Swap(&other.object->internal_state_); 29 } 30 InterfacePtr& operator=(RValue other) { 31 reset(); 32 internal_state_.Swap(&other.object->internal_state_); 33 return *this; 34 } 35 ~InterfacePtr()36 ~InterfacePtr() {} 37 get()38 Interface* get() const { 39 return internal_state_.instance(); 40 } 41 Interface* operator->() const { return get(); } 42 Interface& operator*() const { return *get(); } 43 reset()44 void reset() { 45 State doomed; 46 internal_state_.Swap(&doomed); 47 } 48 49 // This method configures the InterfacePtr<..> to be a proxy to a remote 50 // object on the other end of the given pipe. 51 // 52 // The proxy is bound to the current thread, which means its methods may 53 // only be called on the current thread. 54 // 55 // To move a bound InterfacePtr<..> to another thread, call 56 // ResetAndReturnMessagePipe. Then create a new InterfacePtr<..> on another 57 // thread, and bind the new InterfacePtr<..> to the message pipe on that 58 // thread. 59 void Bind( 60 ScopedMessagePipeHandle handle, 61 const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) { 62 reset(); 63 internal_state_.ConfigureProxy(handle.Pass(), waiter); 64 } 65 66 // The client interface may only be set after this InterfacePtr<..> is bound. set_client(typename Interface::Client * client)67 void set_client(typename Interface::Client* client) { 68 internal_state_.set_client(client); 69 } 70 71 // This method may be called to query if the underlying pipe has encountered 72 // an error. If true, this means method calls made on this interface will be 73 // dropped (and may have already been dropped) on the floor. encountered_error()74 bool encountered_error() const { 75 assert(internal_state_.router()); 76 return internal_state_.router()->encountered_error(); 77 } 78 79 // This method may be called to register an ErrorHandler to observe a 80 // connection error on the underlying pipe. The callback runs asynchronously 81 // from the current message loop. set_error_handler(ErrorHandler * error_handler)82 void set_error_handler(ErrorHandler* error_handler) { 83 assert(internal_state_.router()); 84 internal_state_.router()->set_error_handler(error_handler); 85 } 86 87 // Returns the underlying message pipe handle (if any) and resets the 88 // InterfacePtr<..> to its uninitialized state. This method is helpful if you 89 // need to move a proxy to another thread. See related notes for Bind. PassMessagePipe()90 ScopedMessagePipeHandle PassMessagePipe() { 91 State state; 92 internal_state_.Swap(&state); 93 return state.router() ? 94 state.router()->PassMessagePipe() : ScopedMessagePipeHandle(); 95 } 96 97 // DO NOT USE. Exposed only for internal use and for testing. internal_state()98 internal::InterfacePtrState<Interface>* internal_state() { 99 return &internal_state_; 100 } 101 102 private: 103 typedef internal::InterfacePtrState<Interface> State; 104 State internal_state_; 105 }; 106 107 // Takes a handle to the proxy end-point of a pipe. On the other end is 108 // presumed to be an interface implementation of type |Interface|. Returns a 109 // generated proxy to that interface, which may be used on the current thread. 110 // It is valid to call set_client on the returned InterfacePtr<..> to set an 111 // instance of Interface::Client. 112 template <typename Interface> 113 InterfacePtr<Interface> MakeProxy( 114 ScopedMessagePipeHandle handle, 115 const MojoAsyncWaiter* waiter = Environment::GetDefaultAsyncWaiter()) { 116 InterfacePtr<Interface> ptr; 117 if (handle.is_valid()) 118 ptr.Bind(handle.Pass(), waiter); 119 return ptr.Pass(); 120 } 121 122 } // namespace mojo 123 124 #endif // MOJO_PUBLIC_CPP_BINDINGS_INTERFACE_PTR_H_ 125