src/Handles.h
author David Anderson <dvander@alliedmods.net>
Sun Jan 06 13:52:21 2013 -0800 (2013-01-06)
changeset 256 3c184218462d
parent 240 e3c851a14f16
child 257 9db4cc815ebc
permissions -rw-r--r--
Initial implementation of module imports.
     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 struct NullAddress
    33 {
    34     static void * const Sentinel;
    35 };
    36 
    37 /*
    38  * Internal handles work differently from API handles. An API handle is a
    39  * root, whereas as an internal handle points to a rooted location. This
    40  * subtle difference makes handles easy for embedders, but somewhat
    41  * cumbersome internally.
    42  */
    43 template <typename T>
    44 class Handle
    45 {
    46     T * const *thingp_;
    47 
    48   private:
    49     Handle()
    50       : thingp_(reinterpret_cast<T * const *>(&NullAddress::Sentinel))
    51     {
    52     }
    53 
    54   public:
    55     Handle(const Handle &other) {
    56         thingp_ = other.address();
    57     }
    58     template <typename S> Handle(const Handle<S> &handle) {
    59         typeCheck<S>();
    60         thingp_ = reinterpret_cast<T * const *>(handle.address());
    61     }
    62     template <typename S> inline Handle(const Local<S> &local);
    63     template <typename S> inline Handle(const ScopedRoot<S> &root);
    64 
    65     static inline Handle Null() {
    66         return Handle();
    67     }
    68 
    69   public:
    70     T *operator ->() {
    71         return *thingp_;
    72     }
    73     T *operator *() {
    74         return *thingp_;
    75     }
    76     operator T *() const { return *thingp_; }
    77     operator bool() const {
    78         return thingp_ && *thingp_;
    79     }
    80     T * const *address() const {
    81         return thingp_;
    82     }
    83 
    84     bool operator ==(const Handle<T> &other) const {
    85         return (!thingp_ && !other.thingp_) ||
    86                *thingp_ == *other.thingp_;
    87     }
    88     bool operator !=(const Handle<T> &other) const {
    89         return (!thingp_ != !other.thingp_) ||
    90                *thingp_ != *other.thingp_;
    91     }
    92 
    93   private:
    94     template <typename S>
    95     void typeCheck() {
    96 #ifndef NDEBUG
    97         T *v1 = NULL;
    98         S *v2 = NULL;
    99         v1 = v2;
   100         (void)v1;
   101 #endif
   102     }
   103 };
   104 
   105 template <typename T>
   106 class Local
   107 {
   108     friend class Zone;
   109 
   110     Zone *zone_;
   111     T *thing_;
   112     Local<Object> *prev_;
   113 
   114     Local<Object> *prev() {
   115         return prev_;
   116     }
   117     Local<Object> *toRaw() {
   118         return reinterpret_cast<Local<Object>*>(this);
   119     }
   120 
   121   public:
   122     // These are implemented in Zone.h.
   123     inline explicit Local(Zone *zone, T *thing = NULL);
   124     inline ~Local();
   125 
   126     const Local &operator =(T *thing) {
   127         thing_ = thing;
   128         return *this;
   129     }
   130     T *operator ->() const {
   131         return operator *();
   132     }
   133     T *operator *() const {
   134         return thing_;
   135     }
   136     operator bool () const {
   137         return !!thing_;
   138     }
   139     bool operator !=(const Local &other) {
   140         return thing_ != other.thing_;
   141     }
   142 
   143     T **address() {
   144         return (T **)&thing_;
   145     }
   146     T * const *address() const {
   147         return (T * const *)&thing_;
   148     }
   149     T **ref() {
   150         return &thing_;
   151     }
   152     operator T *() {
   153         return thing_;
   154     }
   155 
   156     Local &operator =(const Local &other) {
   157         thing_ = other.thing_;
   158         return *this;
   159     }
   160 
   161   private:
   162     // Disallow heap allocation.
   163     void *operator new(size_t size);
   164     void *operator new[](size_t size);
   165 
   166     // Disallow copy construction.
   167     Local(const Local<T> &other);
   168 };
   169 
   170 // A ScopedRoot is a special kind of handle for storing references on the
   171 // heap in bulk.
   172 template <typename T>
   173 class ScopedRoot : public PoolObject
   174 {
   175     T **thingp_;
   176 
   177   private:
   178     // This is implemented in Zone.h.
   179     inline T **make(T *other);
   180 
   181     void assign(T *other) {
   182         *thingp_ = other;
   183     }
   184 
   185   public:
   186     ScopedRoot();
   187 
   188     // This is implemented in Zone.h.
   189     inline ScopedRoot(T *thing);
   190 
   191     ScopedRoot &operator =(const ScopedRoot<T> &other) {
   192         assign(*other);
   193         return *this;
   194     }
   195     ScopedRoot &operator =(T *other) {
   196         assign(other);
   197         return *this;
   198     }
   199     T *operator ->() const {
   200         return operator *();
   201     }
   202     T *operator *() const {
   203         return *thingp_;
   204     }
   205     operator T *() const {
   206         return *thingp_;
   207     }
   208     operator bool () const {
   209         return !!*thingp_;
   210     }
   211     T **address() const {
   212         return thingp_;
   213     }
   214 };
   215 
   216 template <typename T> template <typename S> inline
   217 Handle<T>::Handle(const Local<S> &local)
   218 {
   219     typeCheck<S>();
   220     thingp_ = reinterpret_cast<T * const *>(local.address());
   221 }
   222 
   223 template <typename T> template <typename S> inline
   224 Handle<T>::Handle(const ScopedRoot<S> &root)
   225 {
   226     typeCheck<S>();
   227     thingp_ = reinterpret_cast<T * const *>(root.address());
   228 }
   229 
   230 }
   231 
   232 #endif // _include_jitcraft_rooting_h_