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