Home | History | Annotate | Download | only in bindings
      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_STRUCT_PTR_H_
      6 #define MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
      7 
      8 #include <assert.h>
      9 
     10 #include <new>
     11 
     12 #include "mojo/public/cpp/system/macros.h"
     13 
     14 namespace mojo {
     15 namespace internal {
     16 
     17 template <typename Struct>
     18 class StructHelper {
     19  public:
     20   template <typename Ptr>
     21   static void Initialize(Ptr* ptr) { ptr->Initialize(); }
     22 };
     23 
     24 }  // namespace internal
     25 
     26 template <typename Struct>
     27 class StructPtr {
     28   MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(StructPtr, RValue);
     29  public:
     30   typedef typename Struct::Data_ Data_;
     31 
     32   StructPtr() : ptr_(NULL) {}
     33   ~StructPtr() {
     34     delete ptr_;
     35   }
     36 
     37   StructPtr(RValue other) : ptr_(NULL) { Take(other.object); }
     38   StructPtr& operator=(RValue other) {
     39     Take(other.object);
     40     return *this;
     41   }
     42 
     43   template <typename U>
     44   U To() const {
     45     return TypeConverter<StructPtr, U>::ConvertTo(*this);
     46   }
     47 
     48   void reset() {
     49     if (ptr_) {
     50       delete ptr_;
     51       ptr_ = NULL;
     52     }
     53   }
     54 
     55   bool is_null() const { return ptr_ == NULL; }
     56 
     57   Struct& operator*() const {
     58     assert(ptr_);
     59     return *ptr_;
     60   }
     61   Struct* operator->() const {
     62     assert(ptr_);
     63     return ptr_;
     64   }
     65   Struct* get() const { return ptr_; }
     66 
     67   void Swap(StructPtr* other) {
     68     std::swap(ptr_, other->ptr_);
     69   }
     70 
     71  private:
     72   typedef Struct* StructPtr::*Testable;
     73 
     74  public:
     75   operator Testable() const { return ptr_ ? &StructPtr::ptr_ : 0; }
     76 
     77  private:
     78   friend class internal::StructHelper<Struct>;
     79   void Initialize() { assert(!ptr_); ptr_ = new Struct(); }
     80 
     81   void Take(StructPtr* other) {
     82     reset();
     83     Swap(other);
     84   }
     85 
     86   Struct* ptr_;
     87 };
     88 
     89 // Designed to be used when Struct is small and copyable.
     90 template <typename Struct>
     91 class InlinedStructPtr {
     92   MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(InlinedStructPtr, RValue);
     93  public:
     94   typedef typename Struct::Data_ Data_;
     95 
     96   InlinedStructPtr() : is_null_(true) {}
     97   ~InlinedStructPtr() {}
     98 
     99   InlinedStructPtr(RValue other) : is_null_(true) { Take(other.object); }
    100   InlinedStructPtr& operator=(RValue other) {
    101     Take(other.object);
    102     return *this;
    103   }
    104 
    105   template <typename U>
    106   U To() const {
    107     return TypeConverter<InlinedStructPtr, U>::ConvertTo(*this);
    108   }
    109 
    110   void reset() {
    111     is_null_ = true;
    112     value_.~Struct();
    113     new (&value_) Struct();
    114   }
    115 
    116   bool is_null() const { return is_null_; }
    117 
    118   Struct& operator*() const {
    119     assert(!is_null_);
    120     return value_;
    121   }
    122   Struct* operator->() const {
    123     assert(!is_null_);
    124     return &value_;
    125   }
    126   Struct* get() const { return &value_; }
    127 
    128   void Swap(InlinedStructPtr* other) {
    129     std::swap(value_, other->value_);
    130     std::swap(is_null_, other->is_null_);
    131   }
    132 
    133  private:
    134   typedef Struct InlinedStructPtr::*Testable;
    135 
    136  public:
    137   operator Testable() const { return is_null_ ? 0 : &InlinedStructPtr::value_; }
    138 
    139  private:
    140   friend class internal::StructHelper<Struct>;
    141   void Initialize() { is_null_ = false; }
    142 
    143   void Take(InlinedStructPtr* other) {
    144     reset();
    145     Swap(other);
    146   }
    147 
    148   mutable Struct value_;
    149   bool is_null_;
    150 };
    151 
    152 }  // namespace mojo
    153 
    154 #endif  // MOJO_PUBLIC_CPP_BINDINGS_STRUCT_PTR_H_
    155