C++程序  |  127行  |  2.75 KB

// Copyright 2013 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_BINDINGS_LIB_REMOTE_PTR_H_
#define MOJO_PUBLIC_BINDINGS_LIB_REMOTE_PTR_H_

#include <assert.h>

#include "mojo/public/bindings/lib/connector.h"
#include "mojo/public/system/macros.h"

namespace mojo {

// A RemotePtr is a smart-pointer for managing the connection of a message pipe
// to an interface proxy.
//
// EXAMPLE
//
// On the client side of a service, RemotePtr might be used like so:
//
//   class FooClientImpl : public FooClientStub {
//    public:
//     explicit FooClientImpl(const mojo::MessagePipeHandle& message_pipe)
//         : foo_(message_pipe) {
//       foo_.SetPeer(this);
//       foo_.Ping();
//     }
//     virtual void Pong() {
//       ...
//     }
//    private:
//     mojo::RemotePtr<Foo> foo_;
//   };
//
// On the implementation side of a service, RemotePtr might be used like so:
//
//   class FooImpl : public FooStub {
//    public:
//     explicit FooImpl(const mojo::MessagePipeHandle& message_pipe)
//         : client_(message_pipe) {
//       client_.SetPeer(this);
//     }
//     virtual void Ping() {
//       client_->Pong();
//     }
//    private:
//     mojo::RemotePtr<FooClient> client_;
//   };
//
template <typename S>
class RemotePtr {
  MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(RemotePtr, RValue);

 public:
  RemotePtr() : state_(NULL) {}
  explicit RemotePtr(ScopedMessagePipeHandle message_pipe)
      : state_(new State(message_pipe.Pass())) {
  }

  // Move-only constructor and operator=.
  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(ScopedMessagePipeHandle message_pipe) {
    delete state_;
    state_ = new State(message_pipe.Pass());
  }

  bool encountered_error() const {
    assert(state_);
    return state_->connector.encountered_error();
  }

  void SetPeer(typename S::_Peer::_Stub* peer) {
    assert(state_);
    state_->connector.SetIncomingReceiver(peer);
  }

 private:
  struct State {
    State(ScopedMessagePipeHandle message_pipe)
        : connector(message_pipe.Pass()),
          proxy(&connector) {
    }
    internal::Connector connector;
    typename S::_Proxy proxy;
  };

  State* release() {
    State* state = state_;
    state_ = NULL;
    return state;
  }

  State* state_;
};

}  // namespace mojo

#endif  // MOJO_PUBLIC_BINDINGS_LIB_REMOTE_PTR_H_