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 |