src/Handles.h
author David Anderson <dvander@alliedmods.net>
Sat Jul 28 22:03:38 2012 -0700 (2012-07-28)
changeset 121 06bf112c6944
parent 86 32ad0523b309
child 174 e718b56aba78
permissions -rw-r--r--
trigger build
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #ifndef _include_jitcraft_rooting_h_
    20 #define _include_jitcraft_rooting_h_
    21 
    22 #include <stdlib.h>
    23 
    24 namespace ke {
    25 
    26 class Zone;
    27 class Object;
    28 
    29 template <typename T> class Local;
    30 template <typename T> class ScopedRoot;
    31 
    32 /*
    33  * Internal handles work differently from API handles. An API handle is a
    34  * root, whereas as an internal handle points to a rooted location. This
    35  * subtle difference makes handles easy for embedders, but somewhat
    36  * cumbersome internally.
    37  */
    38 template <typename T>
    39 class Handle
    40 {
    41     T * const *thingp_;
    42 
    43   public:
    44     Handle(const Handle &other) {
    45         thingp_ = other.address();
    46     }
    47     template <typename S> Handle(const Handle<S> &handle) {
    48         typeCheck<S>();
    49         thingp_ = reinterpret_cast<T * const *>(handle.address());
    50     }
    51     template <typename S> inline Handle(const Local<S> &local);
    52     template <typename S> inline Handle(const ScopedRoot<S> &root);
    53 
    54   public:
    55     T *operator ->() {
    56         return *thingp_;
    57     }
    58     T *operator *() {
    59         return *thingp_;
    60     }
    61     operator T *() { return *thingp_; }
    62     operator bool() const {
    63         return thingp_ && *thingp_;
    64     }
    65     T * const *address() const {
    66         return thingp_;
    67     }
    68 
    69   private:
    70     template <typename S>
    71     void typeCheck() {
    72 #ifndef NDEBUG
    73         T *v1 = NULL;
    74         S *v2 = NULL;
    75         v1 = v2;
    76         (void)v1;
    77 #endif
    78     }
    79 };
    80 
    81 template <typename T>
    82 class Local
    83 {
    84     friend class Zone;
    85 
    86     Zone *zone_;
    87     T *thing_;
    88     Local<Object> *prev_;
    89 
    90     Local<Object> *prev() {
    91         return prev_;
    92     }
    93     Local<Object> *toRaw() {
    94         return reinterpret_cast<Local<Object>*>(this);
    95     }
    96 
    97   public:
    98     // These are implemented in Zone.h.
    99     inline explicit Local(Zone *zone, T *thing = NULL);
   100     inline ~Local();
   101 
   102     const Local &operator =(T *thing) {
   103         thing_ = thing;
   104         return *this;
   105     }
   106     T *operator ->() const {
   107         return operator *();
   108     }
   109     T *operator *() const {
   110         return thing_;
   111     }
   112     operator bool () const {
   113         return !!thing_;
   114     }
   115     bool operator !=(const Local &other) {
   116         return thing_ != other.thing_;
   117     }
   118 
   119     Object **address() {
   120         return (Object **)&thing_;
   121     }
   122     Object * const *address() const {
   123         return (Object * const *)&thing_;
   124     }
   125     T **ref() {
   126         return &thing_;
   127     }
   128     operator T *() {
   129         return thing_;
   130     }
   131 
   132   private:
   133     // Disallow heap allocation.
   134     void *operator new(size_t size);
   135     void *operator new[](size_t size);
   136 
   137     // Disallow copy construction.
   138     Local(const Local<T> &other);
   139     Local &operator =(const Local &other);
   140 };
   141 
   142 // A ScopedRoot is a special kind of handle for storing references on the
   143 // heap in bulk.
   144 template <typename T>
   145 class ScopedRoot
   146 {
   147     T **thingp_;
   148 
   149   private:
   150     // This is implemented in Zone.h.
   151     inline T **make(T *other);
   152 
   153     void assign(T *other) {
   154         *thingp_ = other;
   155     }
   156 
   157   public:
   158     ScopedRoot();
   159 
   160     // This is implemented in Zone.h.
   161     inline ScopedRoot(T *thing);
   162 
   163     ScopedRoot &operator =(const ScopedRoot<T> &other) {
   164         assign(*other);
   165         return *this;
   166     }
   167     ScopedRoot &operator =(T *other) {
   168         assign(other);
   169         return *this;
   170     }
   171     T *operator ->() const {
   172         return operator *();
   173     }
   174     T *operator *() const {
   175         return *thingp_;
   176     }
   177     operator T *() const {
   178         return *thingp_;
   179     }
   180     operator bool () const {
   181         return !!*thingp_;
   182     }
   183     T **address() const {
   184         return thingp_;
   185     }
   186 };
   187 
   188 template <typename T> template <typename S> inline
   189 Handle<T>::Handle(const Local<S> &local)
   190 {
   191     typeCheck<S>();
   192     thingp_ = reinterpret_cast<T * const *>(local.address());
   193 }
   194 
   195 template <typename T> template <typename S> inline
   196 Handle<T>::Handle(const ScopedRoot<S> &root)
   197 {
   198     typeCheck<S>();
   199     thingp_ = reinterpret_cast<T * const *>(root.address());
   200 }
   201 
   202 }
   203 
   204 #endif // _include_jitcraft_rooting_h_