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