include/keima.h
author David Anderson <dvander@alliedmods.net>
Sun Jul 08 11:33:12 2012 -0700 (2012-07-08)
changeset 61 864e4b02a4c1
parent 60 581a9c793062
child 62 e04c5be84792
permissions -rw-r--r--
Added global root API.
dvander@60
     1
/*
dvander@60
     2
 * Copyright (C) 2004-2012 David Anderson
dvander@60
     3
 *
dvander@60
     4
 * This file is part of SourcePawn.
dvander@60
     5
 *
dvander@60
     6
 * SourcePawn is free software: you can redistribute it and/or modify it under
dvander@60
     7
 * the terms of the GNU General Public License as published by the Free
dvander@60
     8
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@60
     9
 * any later version.
dvander@60
    10
 * 
dvander@60
    11
 * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@60
    12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@60
    13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@60
    14
 *
dvander@60
    15
 * You should have received a copy of the GNU General Public License along with
dvander@60
    16
 * SourcePawn. If not, see http://www.gnu.org/licenses/.
dvander@60
    17
 */
dvander@60
    18
#ifndef _include_sourcepawn3_api_h_
dvander@60
    19
#define _include_sourcepawn3_api_h_
dvander@60
    20
dvander@60
    21
#include <stddef.h>
dvander@60
    22
dvander@60
    23
namespace ke {
dvander@60
    24
dvander@60
    25
class Zone;
dvander@60
    26
class Object;
dvander@60
    27
class HandleScope;
dvander@60
    28
class HeapRoot;
dvander@60
    29
dvander@60
    30
}
dvander@60
    31
dvander@60
    32
namespace Ke {
dvander@60
    33
dvander@60
    34
/*
dvander@60
    35
 * A Handle is a safe pointer that holds an object reference, such that it
dvander@60
    36
 * can be scanned and potentially moved by the garbage collector.
dvander@60
    37
 */
dvander@60
    38
template <typename T>
dvander@60
    39
class Handle
dvander@60
    40
{
dvander@60
    41
  protected:
dvander@60
    42
    template <typename S> void typeCheck() {
dvander@60
    43
        while (false) {
dvander@60
    44
            T *v1 = NULL;
dvander@60
    45
            S *v2 = NULL;
dvander@60
    46
            v1 = v2;
dvander@60
    47
            (void)v1;
dvander@60
    48
        }
dvander@60
    49
    }
dvander@60
    50
dvander@60
    51
  public:
dvander@60
    52
    Handle()
dvander@60
    53
      : obj_(NULL)
dvander@60
    54
    {
dvander@60
    55
    }
dvander@60
    56
dvander@60
    57
    template <typename S> Handle(Handle<S> other)
dvander@60
    58
      : obj_(reinterpret_cast<S *>(*other))
dvander@60
    59
    {
dvander@60
    60
        typeCheck<S>();
dvander@60
    61
    }
dvander@60
    62
 
dvander@60
    63
    explicit Handle(T *obj)
dvander@60
    64
      : obj_(obj)
dvander@60
    65
    {
dvander@60
    66
    }
dvander@60
    67
dvander@60
    68
    T *operator ->() const {
dvander@60
    69
        return obj_;
dvander@60
    70
    }
dvander@60
    71
    T *operator *() const {
dvander@60
    72
        return obj_;
dvander@60
    73
    }
dvander@60
    74
    operator bool () const {
dvander@60
    75
        return !!obj_;
dvander@60
    76
    }
dvander@60
    77
dvander@60
    78
  private:
dvander@60
    79
    T *obj_;
dvander@60
    80
};
dvander@60
    81
dvander@60
    82
/*
dvander@60
    83
 * A local variable that roots an object. Locals are owned by the nearest
dvander@60
    84
 * HandleScope, and as soon as that HandleScope dies, all its Locals are
dvander@60
    85
 * no longer available.
dvander@60
    86
 */
dvander@60
    87
template <typename T>
dvander@60
    88
class Local : public Handle<T>
dvander@60
    89
{
dvander@60
    90
  public:
dvander@60
    91
    Local()
dvander@60
    92
      : Handle<T>()
dvander@60
    93
    {
dvander@60
    94
    }
dvander@60
    95
dvander@60
    96
    template <typename S> Local(Local<S> other)
dvander@60
    97
      : Handle<T>(reinterpret_cast<T *>(*other))
dvander@60
    98
    {
dvander@60
    99
        typeCheck<S>();
dvander@60
   100
    }
dvander@60
   101
dvander@60
   102
    template <typename S> Local(S *other)
dvander@60
   103
      : Handle<T>(other)
dvander@60
   104
    {
dvander@60
   105
    }
dvander@60
   106
};
dvander@60
   107
dvander@60
   108
/*
dvander@60
   109
 * A non-local variable that outlives HandleScopes. A Root is reference-
dvander@60
   110
 * counted. When its reference count reaches 0, the Root is removed.
dvander@60
   111
 */
dvander@60
   112
template <typename T>
dvander@60
   113
class Root : public Handle<T>
dvander@60
   114
{
dvander@60
   115
  public:
dvander@60
   116
    Root()
dvander@60
   117
      : Handle<T>()
dvander@60
   118
    {
dvander@60
   119
    }
dvander@60
   120
dvander@60
   121
    template <typename S> Root(const Root<S> &other)
dvander@60
   122
      : Handle<T>(reinterpret_cast<T *>(*other))
dvander@60
   123
    {
dvander@60
   124
        typeCheck<S>();
dvander@60
   125
        incref();
dvander@60
   126
    }
dvander@60
   127
dvander@61
   128
    explicit Root(ke::HeapRoot *obj)
dvander@60
   129
      : Handle<T>(reinterpret_cast<T *>(obj))
dvander@60
   130
    {
dvander@60
   131
        incref();
dvander@60
   132
    }
dvander@60
   133
dvander@61
   134
    static inline Root<T> New(Handle<T> other);
dvander@60
   135
dvander@60
   136
    ~Root() {
dvander@60
   137
        decref();
dvander@60
   138
    }
dvander@60
   139
dvander@60
   140
    template <typename S>
dvander@60
   141
    Root<T> &operator =(Root<S> other) {
dvander@60
   142
        decref();
dvander@60
   143
        new (this) Root<T>(other);
dvander@60
   144
        return *this;
dvander@60
   145
    }
dvander@60
   146
dvander@60
   147
  private:
dvander@60
   148
    void incref();
dvander@60
   149
    void decref();
dvander@60
   150
};
dvander@60
   151
dvander@60
   152
/*
dvander@60
   153
 * A HandleScope is where Local roots are allcoated. When the HandleScope
dvander@60
   154
 * is destroyed, all Handles created under it are also destroyed. HandleScopes
dvander@60
   155
 * may only be allocated on the stack, in LIFO order.
dvander@60
   156
 */
dvander@60
   157
class HandleScope
dvander@60
   158
{
dvander@60
   159
  protected:
dvander@60
   160
    ke::Zone *zone_;
dvander@60
   161
    ke::Object **position_;
dvander@60
   162
    HandleScope *prev_;
dvander@60
   163
dvander@60
   164
    HandleScope(ke::Zone *zone, ke::Object **position, HandleScope *prev)
dvander@60
   165
      : zone_(zone),
dvander@60
   166
        position_(position),
dvander@60
   167
        prev_(prev)
dvander@60
   168
    {
dvander@60
   169
    }
dvander@60
   170
dvander@60
   171
  public:
dvander@60
   172
    HandleScope();
dvander@60
   173
    ~HandleScope();
dvander@60
   174
dvander@60
   175
    static ke::Object **CreateHandle(ke::Object *obj);
dvander@60
   176
dvander@60
   177
  private:
dvander@60
   178
    // Disallow silly stuff.
dvander@60
   179
    HandleScope(const HandleScope &);
dvander@60
   180
    void operator =(const HandleScope &);
dvander@60
   181
    void *operator new (size_t size);
dvander@60
   182
    void operator delete(void *, size_t);
dvander@60
   183
};
dvander@60
   184
dvander@60
   185
class Module;
dvander@60
   186
dvander@60
   187
/*
dvander@60
   188
 * Initializes the Keima engine. This must be called exactly once before any
dvander@60
   189
 * other Keima functions are called. After this, it is safe to use Keima
dvander@60
   190
 * on the calling thread.
dvander@60
   191
 */
dvander@60
   192
extern bool Initialize();
dvander@60
   193
dvander@60
   194
/*
dvander@60
   195
 * Shuts down the Keima engine and frees data structures on all threads.
dvander@60
   196
 */
dvander@60
   197
extern void Shutdown();
dvander@60
   198
dvander@60
   199
/*
dvander@60
   200
 * Compiles a file and returns a Module.
dvander@60
   201
 */
dvander@60
   202
extern Local<Module> Compile(const char *path);
dvander@60
   203
dvander@61
   204
class Internals
dvander@61
   205
{
dvander@61
   206
    template <typename T> friend class Root;
dvander@61
   207
dvander@61
   208
  private:
dvander@61
   209
    static ke::HeapRoot *NewHeapRoot(ke::Object **objp);
dvander@61
   210
    static void IncRef(ke::HeapRoot *root);
dvander@61
   211
    static void DecRef(ke::HeapRoot *root);
dvander@61
   212
};
dvander@61
   213
dvander@61
   214
template <typename T> Root<T>
dvander@61
   215
Root<T>::New(Handle<T> other)
dvander@61
   216
{
dvander@61
   217
    if (!other)
dvander@61
   218
        return Root<T>(NULL);
dvander@61
   219
    ke::Object **ptr = reinterpret_cast<ke::Object **>(*other);
dvander@61
   220
    return Root<T>(Internals::NewHeapRoot(ptr));
dvander@61
   221
}
dvander@61
   222
dvander@61
   223
template <typename T> void
dvander@61
   224
Root<T>::incref()
dvander@61
   225
{
dvander@61
   226
    if (!*this)
dvander@61
   227
        return;
dvander@61
   228
    ke::HeapRoot *ptr = reinterpret_cast<ke::HeapRoot *>(**this);
dvander@61
   229
    Internals::IncRef(ptr);
dvander@61
   230
}
dvander@61
   231
dvander@61
   232
template <typename T> void
dvander@61
   233
Root<T>::decref()
dvander@61
   234
{
dvander@61
   235
    if (!*this)
dvander@61
   236
        return;
dvander@61
   237
    ke::HeapRoot *ptr = reinterpret_cast<ke::HeapRoot *>(**this);
dvander@61
   238
    Internals::DecRef(ptr);
dvander@61
   239
}
dvander@61
   240
dvander@60
   241
}
dvander@60
   242
dvander@60
   243
#endif // _include_sourcepawn3_api_h_