| OLD | NEW |
| (Empty) |
| 1 // Copyright 2016 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_SYNCHRONOUS_INTERFACE_PTR_H_ | |
| 6 #define MOJO_PUBLIC_CPP_BINDINGS_SYNCHRONOUS_INTERFACE_PTR_H_ | |
| 7 | |
| 8 #include <cstddef> | |
| 9 #include <memory> | |
| 10 #include <utility> | |
| 11 | |
| 12 #include "mojo/public/cpp/bindings/interface_handle.h" | |
| 13 #include "mojo/public/cpp/bindings/lib/message_header_validator.h" | |
| 14 #include "mojo/public/cpp/bindings/lib/synchronous_connector.h" | |
| 15 #include "mojo/public/cpp/bindings/message_validator.h" | |
| 16 #include "mojo/public/cpp/environment/logging.h" | |
| 17 #include "mojo/public/cpp/system/macros.h" | |
| 18 | |
| 19 namespace mojo { | |
| 20 | |
| 21 // A synchronous version of InterfacePtr. Interface message calls using a | |
| 22 // SynchronousInterfacePtr will block if a response message is expected. This | |
| 23 // class uses the generated synchronous versions of the mojo interfaces. | |
| 24 // | |
| 25 // To make a SynchronousInterfacePtr, use the |Create()| factory method and | |
| 26 // supply the InterfaceHandle to it. Use |PassInterfaceHandle()| to extract the | |
| 27 // InterfaceHandle. | |
| 28 // | |
| 29 // SynchronousInterfacePtr is thread-compatible (but not thread-safe). | |
| 30 // | |
| 31 // TODO(vardhan): Add support for InterfaceControlMessage methods. | |
| 32 // TODO(vardhan): Message calls invoked on this class will return |false| if | |
| 33 // there are any message pipe errors. Should there be a better way to expose | |
| 34 // underlying message pipe errors? | |
| 35 template <typename Interface> | |
| 36 class SynchronousInterfacePtr { | |
| 37 public: | |
| 38 // Constructs an unbound SynchronousInterfacePtr. | |
| 39 SynchronousInterfacePtr() : version_(0) {} | |
| 40 SynchronousInterfacePtr(std::nullptr_t) : SynchronousInterfacePtr() {} | |
| 41 | |
| 42 // Takes over the binding of another SynchronousInterfacePtr, and closes any | |
| 43 // message pipe already bound to this pointer. | |
| 44 SynchronousInterfacePtr(SynchronousInterfacePtr&& other) = default; | |
| 45 | |
| 46 // Takes over the binding of another SynchronousInterfacePtr, and closes any | |
| 47 // message pipe already bound to this pointer. | |
| 48 SynchronousInterfacePtr& operator=(SynchronousInterfacePtr&& other) = default; | |
| 49 | |
| 50 static SynchronousInterfacePtr<Interface> Create( | |
| 51 InterfaceHandle<Interface> handle) { | |
| 52 return SynchronousInterfacePtr<Interface>(std::move(handle)); | |
| 53 } | |
| 54 | |
| 55 // Closes the bound message pipe (if any). | |
| 56 void reset() { *this = SynchronousInterfacePtr<Interface>(); } | |
| 57 | |
| 58 // Returns a raw pointer to the local proxy. Caller does not take ownership. | |
| 59 // Note that the local proxy is thread hostile, as stated above. | |
| 60 typename Interface::Synchronous_* get() { return proxy_.get(); } | |
| 61 | |
| 62 typename Interface::Synchronous_* operator->() { | |
| 63 MOJO_DCHECK(connector_); | |
| 64 MOJO_DCHECK(proxy_); | |
| 65 return proxy_.get(); | |
| 66 } | |
| 67 typename Interface::Synchronous_& operator*() { return *operator->(); } | |
| 68 | |
| 69 // Returns whether or not this SynchronousInterfacePtr is bound to a message | |
| 70 // pipe. | |
| 71 bool is_bound() const { return connector_ && connector_->is_valid(); } | |
| 72 explicit operator bool() const { return is_bound(); } | |
| 73 | |
| 74 uint32_t version() const { return version_; } | |
| 75 | |
| 76 // Unbinds the SynchronousInterfacePtr and returns the underlying | |
| 77 // InterfaceHandle for the interface. | |
| 78 InterfaceHandle<Interface> PassInterfaceHandle() { | |
| 79 InterfaceHandle<Interface> handle(connector_->PassHandle(), version_); | |
| 80 reset(); | |
| 81 return handle; | |
| 82 } | |
| 83 | |
| 84 private: | |
| 85 // We save the version_ here before we pass the underlying message pipe handle | |
| 86 // to |connector_|. | |
| 87 uint32_t version_; | |
| 88 | |
| 89 // A simple I/O interface we supply to the generated |proxy_| so it doesn't | |
| 90 // have to know how to write mojo message. | |
| 91 std::unique_ptr<internal::SynchronousConnector> connector_; | |
| 92 // |proxy_| must outlive |connector_|, so make sure it is declared in this | |
| 93 // order. | |
| 94 std::unique_ptr<typename Interface::Synchronous_::Proxy_> proxy_; | |
| 95 | |
| 96 SynchronousInterfacePtr(InterfaceHandle<Interface> handle) | |
| 97 : version_(handle.version()) { | |
| 98 connector_.reset(new internal::SynchronousConnector(handle.PassHandle())); | |
| 99 | |
| 100 mojo::internal::MessageValidatorList validators; | |
| 101 validators.push_back(std::unique_ptr<mojo::internal::MessageValidator>( | |
| 102 new mojo::internal::MessageHeaderValidator)); | |
| 103 validators.push_back(std::unique_ptr<mojo::internal::MessageValidator>( | |
| 104 new typename Interface::ResponseValidator_)); | |
| 105 | |
| 106 proxy_.reset(new typename Interface::Synchronous_::Proxy_( | |
| 107 connector_.get(), std::move(validators))); | |
| 108 } | |
| 109 | |
| 110 MOJO_MOVE_ONLY_TYPE(SynchronousInterfacePtr); | |
| 111 }; | |
| 112 | |
| 113 // Creates a new message pipe over which Interface is to be served. Binds the | |
| 114 // specified SynchronousInterfacePtr to one end of the message pipe, and returns | |
| 115 // an InterfaceRequest bound to the other. The SynchronousInterfacePtr should be | |
| 116 // passed to the client, and the InterfaceRequest should be passed to whatever | |
| 117 // will provide the implementation. Unlike InterfacePtr<>, invocations on | |
| 118 // SynchronousInterfacePtr<> will block until a response is received, so the | |
| 119 // user must pass off InterfaceRequest<> to an implementation before issuing any | |
| 120 // calls. | |
| 121 // | |
| 122 // Example: | |
| 123 // ======== | |
| 124 // Given the following interface | |
| 125 // interface Echo { | |
| 126 // EchoString(string str) => (string value); | |
| 127 // } | |
| 128 // | |
| 129 // The client would have code similar to the following: | |
| 130 // | |
| 131 // SynchronousInterfacePtr<Echo> client; | |
| 132 // InterfaceRequest<Echo> impl = GetSynchronousProxy(&client); | |
| 133 // // .. pass |impl| off to an implementation. | |
| 134 // mojo::String out; | |
| 135 // client->EchoString("hello!", &out); | |
| 136 // | |
| 137 // TODO(vardhan): Consider renaming this function, along with her sister | |
| 138 // |GetProxy()| functions. Maybe `MakeSyncProxy()`? | |
| 139 template <typename Interface> | |
| 140 InterfaceRequest<Interface> GetSynchronousProxy( | |
| 141 SynchronousInterfacePtr<Interface>* ptr) { | |
| 142 InterfaceHandle<Interface> iface_handle; | |
| 143 auto retval = GetProxy(&iface_handle); | |
| 144 *ptr = SynchronousInterfacePtr<Interface>::Create(std::move(iface_handle)); | |
| 145 return retval; | |
| 146 } | |
| 147 | |
| 148 } // namespace mojo | |
| 149 | |
| 150 #endif // MOJO_PUBLIC_CPP_BINDINGS_SYNCHRONOUS_INTERFACE_PTR_H_ | |
| OLD | NEW |