• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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