#ifndef MOJO_PUBLIC_CPP_BINDINGS_REMOTE_PTR_H_
#define MOJO_PUBLIC_CPP_BINDINGS_REMOTE_PTR_H_
#include <assert.h>
#include "mojo/public/cpp/bindings/interface.h"
#include "mojo/public/cpp/bindings/lib/router.h"
#include "mojo/public/cpp/system/macros.h"
namespace mojo {
template <typename S>
class RemotePtr {
struct State;
MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(RemotePtr, RValue)
public:
RemotePtr() : state_(NULL) {}
explicit RemotePtr(typename Interface<S>::ScopedHandle interface_handle,
typename S::_Peer* peer,
ErrorHandler* error_handler = NULL,
MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter())
: state_(new State(ScopedMessagePipeHandle(interface_handle.Pass()), peer,
error_handler, waiter)) {
}
RemotePtr(RValue other) : state_(other.object->release()) {}
RemotePtr& operator=(RValue other) {
state_ = other.object->release();
return *this;
}
~RemotePtr() {
delete state_;
}
bool is_null() const {
return !state_;
}
S* get() {
assert(state_);
return &state_->proxy;
}
S* operator->() {
return get();
}
void reset() {
delete state_;
state_ = NULL;
}
void reset(typename Interface<S>::ScopedHandle interface_handle,
typename S::_Peer* peer,
ErrorHandler* error_handler = NULL,
MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
delete state_;
state_ = new State(ScopedMessagePipeHandle(interface_handle.Pass()), peer,
error_handler, waiter);
}
bool encountered_error() const {
assert(state_);
return state_->router.encountered_error();
}
private:
struct State {
State(ScopedMessagePipeHandle message_pipe, typename S::_Peer* peer,
ErrorHandler* error_handler, MojoAsyncWaiter* waiter)
: router(message_pipe.Pass(), waiter),
proxy(&router),
stub(peer) {
router.set_error_handler(error_handler);
if (peer)
router.set_incoming_receiver(&stub);
}
internal::Router router;
typename S::_Proxy proxy;
typename S::_Peer::_Stub stub;
};
State* release() {
State* state = state_;
state_ = NULL;
return state;
}
State* state_;
};
}
#endif