blob: 041a31c8a0c8134058705775019069d19f924f6c [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_INTERNAL_H_
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_INTERNAL_H_
#include <stdio.h>
#include "mojo/public/cpp/bindings/lib/router.h"
namespace mojo {
namespace internal {
template <typename Interface>
class InterfacePtrState {
public:
InterfacePtrState() : instance_(NULL), client_(NULL), router_(NULL) {}
~InterfacePtrState() {
// Destruction order matters here. We delete |instance_| first, even though
// |router_| may have a reference to it, so that |~Interface| may have a
// shot at generating new outbound messages (ie, invoking client methods).
delete instance_;
delete router_;
delete client_;
}
Interface* instance() const { return instance_; }
void set_instance(Interface* instance) { instance_ = instance; }
Router* router() const { return router_; }
bool is_configured_as_proxy() const {
// This question only makes sense if we have a bound pipe.
return router_ && !client_;
}
void Swap(InterfacePtrState* other) {
std::swap(other->instance_, instance_);
std::swap(other->client_, client_);
std::swap(other->router_, router_);
}
void ConfigureProxy(ScopedMessagePipeHandle handle,
MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
assert(!instance_);
assert(!router_);
router_ = new Router(handle.Pass(), waiter);
ProxyWithStub* proxy = new ProxyWithStub(router_);
router_->set_incoming_receiver(&proxy->stub);
instance_ = proxy;
}
void ConfigureStub(ScopedMessagePipeHandle handle,
MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
assert(instance_); // Should have already been set!
assert(!router_);
// Stub for binding to state_.instance
// Proxy for communicating to the client on the other end of the pipe.
router_ = new Router(handle.Pass(), waiter);
ClientProxyWithStub* proxy = new ClientProxyWithStub(router_);
proxy->stub.set_sink(instance_);
router_->set_incoming_receiver(&proxy->stub);
instance_->SetClient(proxy);
client_ = proxy;
}
private:
class ProxyWithStub : public Interface::Proxy_ {
public:
explicit ProxyWithStub(MessageReceiver* receiver)
: Interface::Proxy_(receiver) {
}
virtual void SetClient(typename Interface::Client_* client) MOJO_OVERRIDE {
stub.set_sink(client);
}
typename Interface::Client_::Stub_ stub;
private:
MOJO_DISALLOW_COPY_AND_ASSIGN(ProxyWithStub);
};
class ClientProxyWithStub : public Interface::Client_::Proxy_ {
public:
explicit ClientProxyWithStub(MessageReceiver* receiver)
: Interface::Client_::Proxy_(receiver) {
}
typename Interface::Stub_ stub;
private:
MOJO_DISALLOW_COPY_AND_ASSIGN(ClientProxyWithStub);
};
Interface* instance_;
typename Interface::Client_* client_;
Router* router_;
MOJO_DISALLOW_COPY_AND_ASSIGN(InterfacePtrState);
};
} // namespace internal
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_INTERFACE_PTR_INTERNAL_H_