src/Handles.h
author David Anderson <dvander@alliedmods.net>
Wed Dec 26 17:20:55 2012 -0800 (2012-12-26)
changeset 244 3c57bbf22aa2
parent 240 e3c851a14f16
child 256 3c184218462d
permissions -rw-r--r--
Fix clang bustage.
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@240
    76
    operator T *() const { 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@233
    88
    bool operator !=(const Handle<T> &other) const {
dvander@233
    89
        return (!thingp_ != !other.thingp_) ||
dvander@233
    90
               *thingp_ != *other.thingp_;
dvander@233
    91
    }
dvander@196
    92
dvander@11
    93
  private:
dvander@11
    94
    template <typename S>
dvander@11
    95
    void typeCheck() {
dvander@85
    96
#ifndef NDEBUG
dvander@11
    97
        T *v1 = NULL;
dvander@11
    98
        S *v2 = NULL;
dvander@11
    99
        v1 = v2;
dvander@11
   100
        (void)v1;
dvander@11
   101
#endif
dvander@11
   102
    }
dvander@28
   103
};
dvander@28
   104
dvander@11
   105
template <typename T>
dvander@11
   106
class Local
dvander@11
   107
{
dvander@11
   108
    friend class Zone;
dvander@11
   109
dvander@11
   110
    Zone *zone_;
dvander@28
   111
    T *thing_;
dvander@11
   112
    Local<Object> *prev_;
dvander@11
   113
dvander@11
   114
    Local<Object> *prev() {
dvander@11
   115
        return prev_;
dvander@11
   116
    }
dvander@11
   117
    Local<Object> *toRaw() {
dvander@11
   118
        return reinterpret_cast<Local<Object>*>(this);
dvander@11
   119
    }
dvander@11
   120
dvander@11
   121
  public:
dvander@29
   122
    // These are implemented in Zone.h.
dvander@28
   123
    inline explicit Local(Zone *zone, T *thing = NULL);
dvander@11
   124
    inline ~Local();
dvander@11
   125
dvander@11
   126
    const Local &operator =(T *thing) {
dvander@11
   127
        thing_ = thing;
dvander@11
   128
        return *this;
dvander@11
   129
    }
dvander@11
   130
    T *operator ->() const {
dvander@11
   131
        return operator *();
dvander@11
   132
    }
dvander@11
   133
    T *operator *() const {
dvander@11
   134
        return thing_;
dvander@11
   135
    }
dvander@11
   136
    operator bool () const {
dvander@11
   137
        return !!thing_;
dvander@11
   138
    }
dvander@83
   139
    bool operator !=(const Local &other) {
dvander@83
   140
        return thing_ != other.thing_;
dvander@83
   141
    }
dvander@11
   142
dvander@174
   143
    T **address() {
dvander@174
   144
        return (T **)&thing_;
dvander@11
   145
    }
dvander@174
   146
    T * const *address() const {
dvander@174
   147
        return (T * const *)&thing_;
dvander@11
   148
    }
dvander@54
   149
    T **ref() {
dvander@54
   150
        return &thing_;
dvander@54
   151
    }
dvander@11
   152
    operator T *() {
dvander@11
   153
        return thing_;
dvander@11
   154
    }
dvander@11
   155
dvander@191
   156
    Local &operator =(const Local &other) {
dvander@191
   157
        thing_ = other.thing_;
dvander@191
   158
        return *this;
dvander@191
   159
    }
dvander@191
   160
dvander@11
   161
  private:
dvander@11
   162
    // Disallow heap allocation.
dvander@11
   163
    void *operator new(size_t size);
dvander@11
   164
    void *operator new[](size_t size);
dvander@11
   165
dvander@11
   166
    // Disallow copy construction.
dvander@11
   167
    Local(const Local<T> &other);
dvander@28
   168
};
dvander@28
   169
dvander@27
   170
// A ScopedRoot is a special kind of handle for storing references on the
dvander@27
   171
// heap in bulk.
dvander@27
   172
template <typename T>
dvander@27
   173
class ScopedRoot
dvander@27
   174
{
dvander@29
   175
    T **thingp_;
dvander@27
   176
dvander@27
   177
  private:
dvander@29
   178
    // This is implemented in Zone.h.
dvander@29
   179
    inline T **make(T *other);
dvander@29
   180
dvander@29
   181
    void assign(T *other) {
dvander@34
   182
        *thingp_ = other;
dvander@27
   183
    }
dvander@27
   184
dvander@27
   185
  public:
dvander@53
   186
    ScopedRoot();
dvander@29
   187
dvander@29
   188
    // This is implemented in Zone.h.
dvander@29
   189
    inline ScopedRoot(T *thing);
dvander@29
   190
dvander@27
   191
    ScopedRoot &operator =(const ScopedRoot<T> &other) {
dvander@27
   192
        assign(*other);
dvander@27
   193
        return *this;
dvander@27
   194
    }
dvander@29
   195
    ScopedRoot &operator =(T *other) {
dvander@27
   196
        assign(other);
dvander@27
   197
        return *this;
dvander@27
   198
    }
dvander@27
   199
    T *operator ->() const {
dvander@27
   200
        return operator *();
dvander@27
   201
    }
dvander@27
   202
    T *operator *() const {
dvander@29
   203
        return *thingp_;
dvander@29
   204
    }
dvander@29
   205
    operator T *() const {
dvander@34
   206
        return *thingp_;
dvander@27
   207
    }
dvander@27
   208
    operator bool () const {
dvander@53
   209
        return !!*thingp_;
dvander@34
   210
    }
dvander@34
   211
    T **address() const {
dvander@34
   212
        return thingp_;
dvander@27
   213
    }
dvander@28
   214
};
dvander@28
   215
dvander@11
   216
template <typename T> template <typename S> inline
dvander@11
   217
Handle<T>::Handle(const Local<S> &local)
dvander@11
   218
{
dvander@11
   219
    typeCheck<S>();
dvander@34
   220
    thingp_ = reinterpret_cast<T * const *>(local.address());
dvander@34
   221
}
dvander@34
   222
dvander@34
   223
template <typename T> template <typename S> inline
dvander@34
   224
Handle<T>::Handle(const ScopedRoot<S> &root)
dvander@34
   225
{
dvander@34
   226
    typeCheck<S>();
dvander@34
   227
    thingp_ = reinterpret_cast<T * const *>(root.address());
dvander@28
   228
}
dvander@28
   229
dvander@28
   230
}
dvander@28
   231
dvander@28
   232
#endif // _include_jitcraft_rooting_h_