OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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_ASSOCIATED_INTERFACE_PTR_H_ | |
6 #define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ | |
7 | |
8 #include <algorithm> | |
9 | |
10 #include "base/macros.h" | |
11 #include "mojo/public/cpp/bindings/associated_group.h" | |
12 #include "mojo/public/cpp/bindings/associated_interface_ptr_info.h" | |
13 #include "mojo/public/cpp/bindings/associated_interface_request.h" | |
14 #include "mojo/public/cpp/bindings/callback.h" | |
15 #include "mojo/public/cpp/bindings/lib/associated_interface_ptr_internal.h" | |
16 | |
17 namespace mojo { | |
18 | |
19 // Represents the client side of an associated interface. It is similar to | |
20 // InterfacePtr, except that it doesn't own a message pipe handle. | |
21 template <typename Interface> | |
22 class AssociatedInterfacePtr { | |
23 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(AssociatedInterfacePtr) | |
24 | |
25 public: | |
26 // Constructs an unbound AssociatedInterfacePtr. | |
27 AssociatedInterfacePtr() {} | |
28 AssociatedInterfacePtr(decltype(nullptr)) {} | |
29 | |
30 AssociatedInterfacePtr(AssociatedInterfacePtr&& other) { | |
31 internal_state_.Swap(&other.internal_state_); | |
32 } | |
33 | |
34 AssociatedInterfacePtr& operator=(AssociatedInterfacePtr&& other) { | |
35 reset(); | |
36 internal_state_.Swap(&other.internal_state_); | |
37 return *this; | |
38 } | |
39 | |
40 // Assigning nullptr to this class causes it to closes the associated | |
41 // interface (if any) and returns the pointer to the unbound state. | |
42 AssociatedInterfacePtr& operator=(decltype(nullptr)) { | |
43 reset(); | |
44 return *this; | |
45 } | |
46 | |
47 ~AssociatedInterfacePtr() {} | |
48 | |
49 // Sets up this object as the client side of an associated interface. | |
50 // Calling with an invalid |info| has the same effect as reset(). In this | |
51 // case, the AssociatedInterfacePtr is not considered as bound. | |
52 // | |
53 // NOTE: Please see the comments of | |
54 // AssociatedGroup.CreateAssociatedInterface() about when you can use this | |
55 // object to make calls. | |
56 void Bind(AssociatedInterfacePtrInfo<Interface> info) { | |
57 reset(); | |
58 | |
59 bool is_local = | |
60 internal::AssociatedInterfacePtrInfoHelper::GetHandle(&info).is_local(); | |
61 | |
62 DCHECK(is_local) << "The AssociatedInterfacePtrInfo is supposed to be used " | |
63 "at the other side of the message pipe."; | |
64 | |
65 if (info.is_valid() && is_local) | |
66 internal_state_.Bind(info.Pass()); | |
67 } | |
68 | |
69 bool is_bound() const { return internal_state_.is_bound(); } | |
70 | |
71 Interface* get() const { return internal_state_.instance(); } | |
72 | |
73 // Functions like a pointer to Interface. Must already be bound. | |
74 Interface* operator->() const { return get(); } | |
75 Interface& operator*() const { return *get(); } | |
76 | |
77 // Returns the version number of the interface that the remote side supports. | |
78 uint32_t version() const { return internal_state_.version(); } | |
79 | |
80 // Queries the max version that the remote side supports. On completion, the | |
81 // result will be returned as the input of |callback|. The version number of | |
82 // this object will also be updated. | |
83 void QueryVersion(const Callback<void(uint32_t)>& callback) { | |
84 internal_state_.QueryVersion(callback); | |
85 } | |
86 | |
87 // If the remote side doesn't support the specified version, it will close the | |
88 // associated interface asynchronously. This does nothing if it's already | |
89 // known that the remote side supports the specified version, i.e., if | |
90 // |version <= this->version()|. | |
91 // | |
92 // After calling RequireVersion() with a version not supported by the remote | |
93 // side, all subsequent calls to interface methods will be ignored. | |
94 void RequireVersion(uint32_t version) { | |
95 internal_state_.RequireVersion(version); | |
96 } | |
97 | |
98 // Closes the associated interface (if any) and returns the pointer to the | |
99 // unbound state. | |
100 void reset() { | |
101 State doomed; | |
102 internal_state_.Swap(&doomed); | |
103 } | |
104 | |
105 // Indicates whether an error has been encountered. If true, method calls made | |
106 // on this interface will be dropped (and may already have been dropped). | |
107 bool encountered_error() const { return internal_state_.encountered_error(); } | |
108 | |
109 // Registers a handler to receive error notifications. | |
110 // | |
111 // This method may only be called after the AssociatedInterfacePtr has been | |
112 // bound. | |
113 void set_connection_error_handler(const Closure& error_handler) { | |
114 internal_state_.set_connection_error_handler(error_handler); | |
115 } | |
116 | |
117 // Unbinds and returns the associated interface pointer information which | |
118 // could be used to setup an AssociatedInterfacePtr again. This method may be | |
119 // used to move the proxy to a different thread. | |
120 // | |
121 // It is an error to call PassInterface() while there are pending responses. | |
122 // TODO: fix this restriction, it's not always obvious when there is a | |
123 // pending response. | |
124 AssociatedInterfacePtrInfo<Interface> PassInterface() { | |
125 DCHECK(!internal_state_.has_pending_callbacks()); | |
126 State state; | |
127 internal_state_.Swap(&state); | |
128 | |
129 return state.PassInterface(); | |
130 } | |
131 | |
132 // Returns the associated group that this object belongs to. Returns null if | |
133 // the object is not bound. | |
134 AssociatedGroup* associated_group() { | |
135 return internal_state_->associated_group(); | |
136 } | |
137 | |
138 // DO NOT USE. Exposed only for internal use and for testing. | |
139 internal::AssociatedInterfacePtrState<Interface>* internal_state() { | |
140 return &internal_state_; | |
141 } | |
142 | |
143 // Allow AssociatedInterfacePtr<> to be used in boolean expressions, but not | |
144 // implicitly convertible to a real bool (which is dangerous). | |
145 private: | |
146 typedef internal::AssociatedInterfacePtrState<Interface> | |
147 AssociatedInterfacePtr::*Testable; | |
148 | |
149 public: | |
150 operator Testable() const { | |
151 return internal_state_.is_bound() ? &AssociatedInterfacePtr::internal_state_ | |
152 : nullptr; | |
153 } | |
154 | |
155 private: | |
156 // Forbid the == and != operators explicitly, otherwise AssociatedInterfacePtr | |
157 // will be | |
158 // converted to Testable to do == or != comparison. | |
sky
2015/11/23 21:05:42
nit: move onto previous line.
yzshen1
2015/11/23 21:50:04
Done.
| |
159 template <typename T> | |
160 bool operator==(const AssociatedInterfacePtr<T>& other) const = delete; | |
161 template <typename T> | |
162 bool operator!=(const AssociatedInterfacePtr<T>& other) const = delete; | |
163 | |
164 typedef internal::AssociatedInterfacePtrState<Interface> State; | |
165 mutable State internal_state_; | |
166 }; | |
167 | |
168 // Creates an associated interface. The output |ptr| should be used locally | |
169 // while the returned request should be passed through the message pipe endpoint | |
170 // referred to by |associated_group| to setup the corresponding asssociated | |
171 // interface implementation at the remote side. | |
172 // | |
173 // NOTE: |ptr| should NOT be used to make calls before the request is sent. | |
174 // Violating that will cause the message pipe to be closed. On the other hand, | |
175 // as soon as the request is sent, |ptr| is usable. There is no need to wait | |
176 // until the request is bound to an implementation at the remote side. | |
177 template <typename Interface> | |
178 AssociatedInterfaceRequest<Interface> GetProxy( | |
179 AssociatedInterfacePtr<Interface>* ptr, | |
180 AssociatedGroup* group) { | |
181 AssociatedInterfaceRequest<Interface> request; | |
182 AssociatedInterfacePtrInfo<Interface> ptr_info; | |
183 group->CreateAssociatedInterface(AssociatedGroup::WILL_PASS_REQUEST, | |
184 &ptr_info, &request); | |
185 | |
186 ptr->Bind(ptr_info.Pass()); | |
187 return request.Pass(); | |
188 } | |
189 | |
190 } // namespace mojo | |
191 | |
192 #endif // MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_INTERFACE_PTR_H_ | |
OLD | NEW |