src/Handles.h
changeset 86 32ad0523b309
parent 85 06a0015b6a5c
child 174 e718b56aba78
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/Handles.h	Tue Jul 24 23:53:34 2012 -0700
     1.3 @@ -0,0 +1,204 @@
     1.4 +/* vim: set ts=4 sw=4 tw=99 et:
     1.5 + *
     1.6 + * Copyright (C) 2012 David Anderson
     1.7 + *
     1.8 + * This file is part of JITCraft.
     1.9 + *
    1.10 + * JITCraft is free software: you can redistribute it and/or modify it under
    1.11 + * the terms of the GNU General Public License as published by the Free
    1.12 + * Software Foundation, either version 3 of the License, or (at your option)
    1.13 + * any later version.
    1.14 + * 
    1.15 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    1.16 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    1.17 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    1.18 + *
    1.19 + * You should have received a copy of the GNU General Public License along with
    1.20 + * JITCraft. If not, see http://www.gnu.org/licenses/.
    1.21 + */
    1.22 +#ifndef _include_jitcraft_rooting_h_
    1.23 +#define _include_jitcraft_rooting_h_
    1.24 +
    1.25 +#include <stdlib.h>
    1.26 +
    1.27 +namespace ke {
    1.28 +
    1.29 +class Zone;
    1.30 +class Object;
    1.31 +
    1.32 +template <typename T> class Local;
    1.33 +template <typename T> class ScopedRoot;
    1.34 +
    1.35 +/*
    1.36 + * Internal handles work differently from API handles. An API handle is a
    1.37 + * root, whereas as an internal handle points to a rooted location. This
    1.38 + * subtle difference makes handles easy for embedders, but somewhat
    1.39 + * cumbersome internally.
    1.40 + */
    1.41 +template <typename T>
    1.42 +class Handle
    1.43 +{
    1.44 +    T * const *thingp_;
    1.45 +
    1.46 +  public:
    1.47 +    Handle(const Handle &other) {
    1.48 +        thingp_ = other.address();
    1.49 +    }
    1.50 +    template <typename S> Handle(const Handle<S> &handle) {
    1.51 +        typeCheck<S>();
    1.52 +        thingp_ = reinterpret_cast<T * const *>(handle.address());
    1.53 +    }
    1.54 +    template <typename S> inline Handle(const Local<S> &local);
    1.55 +    template <typename S> inline Handle(const ScopedRoot<S> &root);
    1.56 +
    1.57 +  public:
    1.58 +    T *operator ->() {
    1.59 +        return *thingp_;
    1.60 +    }
    1.61 +    T *operator *() {
    1.62 +        return *thingp_;
    1.63 +    }
    1.64 +    operator T *() { return *thingp_; }
    1.65 +    operator bool() const {
    1.66 +        return thingp_ && *thingp_;
    1.67 +    }
    1.68 +    T * const *address() const {
    1.69 +        return thingp_;
    1.70 +    }
    1.71 +
    1.72 +  private:
    1.73 +    template <typename S>
    1.74 +    void typeCheck() {
    1.75 +#ifndef NDEBUG
    1.76 +        T *v1 = NULL;
    1.77 +        S *v2 = NULL;
    1.78 +        v1 = v2;
    1.79 +        (void)v1;
    1.80 +#endif
    1.81 +    }
    1.82 +};
    1.83 +
    1.84 +template <typename T>
    1.85 +class Local
    1.86 +{
    1.87 +    friend class Zone;
    1.88 +
    1.89 +    Zone *zone_;
    1.90 +    T *thing_;
    1.91 +    Local<Object> *prev_;
    1.92 +
    1.93 +    Local<Object> *prev() {
    1.94 +        return prev_;
    1.95 +    }
    1.96 +    Local<Object> *toRaw() {
    1.97 +        return reinterpret_cast<Local<Object>*>(this);
    1.98 +    }
    1.99 +
   1.100 +  public:
   1.101 +    // These are implemented in Zone.h.
   1.102 +    inline explicit Local(Zone *zone, T *thing = NULL);
   1.103 +    inline ~Local();
   1.104 +
   1.105 +    const Local &operator =(T *thing) {
   1.106 +        thing_ = thing;
   1.107 +        return *this;
   1.108 +    }
   1.109 +    T *operator ->() const {
   1.110 +        return operator *();
   1.111 +    }
   1.112 +    T *operator *() const {
   1.113 +        return thing_;
   1.114 +    }
   1.115 +    operator bool () const {
   1.116 +        return !!thing_;
   1.117 +    }
   1.118 +    bool operator !=(const Local &other) {
   1.119 +        return thing_ != other.thing_;
   1.120 +    }
   1.121 +
   1.122 +    Object **address() {
   1.123 +        return (Object **)&thing_;
   1.124 +    }
   1.125 +    Object * const *address() const {
   1.126 +        return (Object * const *)&thing_;
   1.127 +    }
   1.128 +    T **ref() {
   1.129 +        return &thing_;
   1.130 +    }
   1.131 +    operator T *() {
   1.132 +        return thing_;
   1.133 +    }
   1.134 +
   1.135 +  private:
   1.136 +    // Disallow heap allocation.
   1.137 +    void *operator new(size_t size);
   1.138 +    void *operator new[](size_t size);
   1.139 +
   1.140 +    // Disallow copy construction.
   1.141 +    Local(const Local<T> &other);
   1.142 +    Local &operator =(const Local &other);
   1.143 +};
   1.144 +
   1.145 +// A ScopedRoot is a special kind of handle for storing references on the
   1.146 +// heap in bulk.
   1.147 +template <typename T>
   1.148 +class ScopedRoot
   1.149 +{
   1.150 +    T **thingp_;
   1.151 +
   1.152 +  private:
   1.153 +    // This is implemented in Zone.h.
   1.154 +    inline T **make(T *other);
   1.155 +
   1.156 +    void assign(T *other) {
   1.157 +        *thingp_ = other;
   1.158 +    }
   1.159 +
   1.160 +  public:
   1.161 +    ScopedRoot();
   1.162 +
   1.163 +    // This is implemented in Zone.h.
   1.164 +    inline ScopedRoot(T *thing);
   1.165 +
   1.166 +    ScopedRoot &operator =(const ScopedRoot<T> &other) {
   1.167 +        assign(*other);
   1.168 +        return *this;
   1.169 +    }
   1.170 +    ScopedRoot &operator =(T *other) {
   1.171 +        assign(other);
   1.172 +        return *this;
   1.173 +    }
   1.174 +    T *operator ->() const {
   1.175 +        return operator *();
   1.176 +    }
   1.177 +    T *operator *() const {
   1.178 +        return *thingp_;
   1.179 +    }
   1.180 +    operator T *() const {
   1.181 +        return *thingp_;
   1.182 +    }
   1.183 +    operator bool () const {
   1.184 +        return !!*thingp_;
   1.185 +    }
   1.186 +    T **address() const {
   1.187 +        return thingp_;
   1.188 +    }
   1.189 +};
   1.190 +
   1.191 +template <typename T> template <typename S> inline
   1.192 +Handle<T>::Handle(const Local<S> &local)
   1.193 +{
   1.194 +    typeCheck<S>();
   1.195 +    thingp_ = reinterpret_cast<T * const *>(local.address());
   1.196 +}
   1.197 +
   1.198 +template <typename T> template <typename S> inline
   1.199 +Handle<T>::Handle(const ScopedRoot<S> &root)
   1.200 +{
   1.201 +    typeCheck<S>();
   1.202 +    thingp_ = reinterpret_cast<T * const *>(root.address());
   1.203 +}
   1.204 +
   1.205 +}
   1.206 +
   1.207 +#endif // _include_jitcraft_rooting_h_