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