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