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_