dvander@60: /* dvander@60: * Copyright (C) 2004-2012 David Anderson dvander@60: * dvander@60: * This file is part of SourcePawn. dvander@60: * dvander@60: * SourcePawn is free software: you can redistribute it and/or modify it under dvander@60: * the terms of the GNU General Public License as published by the Free dvander@60: * Software Foundation, either version 3 of the License, or (at your option) dvander@60: * any later version. dvander@60: * dvander@60: * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY dvander@60: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@60: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@60: * dvander@60: * You should have received a copy of the GNU General Public License along with dvander@60: * SourcePawn. If not, see http://www.gnu.org/licenses/. dvander@60: */ dvander@60: #ifndef _include_sourcepawn3_api_h_ dvander@60: #define _include_sourcepawn3_api_h_ dvander@60: dvander@60: #include dvander@60: dvander@60: namespace ke { dvander@60: dvander@60: class Zone; dvander@60: class Object; dvander@60: class HandleScope; dvander@60: class HeapRoot; dvander@60: dvander@60: } dvander@60: dvander@60: namespace Ke { dvander@60: dvander@60: /* dvander@60: * A Handle is a safe pointer that holds an object reference, such that it dvander@60: * can be scanned and potentially moved by the garbage collector. dvander@60: */ dvander@60: template dvander@60: class Handle dvander@60: { dvander@60: protected: dvander@60: template void typeCheck() { dvander@60: while (false) { dvander@60: T *v1 = NULL; dvander@60: S *v2 = NULL; dvander@60: v1 = v2; dvander@60: (void)v1; dvander@60: } dvander@60: } dvander@60: dvander@60: public: dvander@60: Handle() dvander@60: : obj_(NULL) dvander@60: { dvander@60: } dvander@60: dvander@60: template Handle(Handle other) dvander@60: : obj_(reinterpret_cast(*other)) dvander@60: { dvander@60: typeCheck(); dvander@60: } dvander@60: dvander@60: explicit Handle(T *obj) dvander@60: : obj_(obj) dvander@60: { dvander@60: } dvander@60: dvander@60: T *operator ->() const { dvander@60: return obj_; dvander@60: } dvander@60: T *operator *() const { dvander@60: return obj_; dvander@60: } dvander@60: operator bool () const { dvander@60: return !!obj_; dvander@60: } dvander@60: dvander@60: private: dvander@60: T *obj_; dvander@60: }; dvander@60: dvander@60: /* dvander@60: * A local variable that roots an object. Locals are owned by the nearest dvander@60: * HandleScope, and as soon as that HandleScope dies, all its Locals are dvander@60: * no longer available. dvander@60: */ dvander@60: template dvander@60: class Local : public Handle dvander@60: { dvander@60: public: dvander@60: Local() dvander@60: : Handle() dvander@60: { dvander@60: } dvander@60: dvander@60: template Local(Local other) dvander@60: : Handle(reinterpret_cast(*other)) dvander@60: { dvander@60: typeCheck(); dvander@60: } dvander@60: dvander@60: template Local(S *other) dvander@60: : Handle(other) dvander@60: { dvander@60: } dvander@60: }; dvander@60: dvander@60: /* dvander@60: * A non-local variable that outlives HandleScopes. A Root is reference- dvander@60: * counted. When its reference count reaches 0, the Root is removed. dvander@60: */ dvander@60: template dvander@60: class Root : public Handle dvander@60: { dvander@60: public: dvander@60: Root() dvander@60: : Handle() dvander@60: { dvander@60: } dvander@60: dvander@60: template Root(const Root &other) dvander@60: : Handle(reinterpret_cast(*other)) dvander@60: { dvander@60: typeCheck(); dvander@60: incref(); dvander@60: } dvander@60: dvander@61: explicit Root(ke::HeapRoot *obj) dvander@60: : Handle(reinterpret_cast(obj)) dvander@60: { dvander@60: incref(); dvander@60: } dvander@60: dvander@61: static inline Root New(Handle other); dvander@60: dvander@60: ~Root() { dvander@60: decref(); dvander@60: } dvander@60: dvander@60: template dvander@60: Root &operator =(Root other) { dvander@60: decref(); dvander@60: new (this) Root(other); dvander@60: return *this; dvander@60: } dvander@60: dvander@60: private: dvander@60: void incref(); dvander@60: void decref(); dvander@60: }; dvander@60: dvander@60: /* dvander@60: * A HandleScope is where Local roots are allcoated. When the HandleScope dvander@60: * is destroyed, all Handles created under it are also destroyed. HandleScopes dvander@60: * may only be allocated on the stack, in LIFO order. dvander@60: */ dvander@60: class HandleScope dvander@60: { dvander@60: protected: dvander@60: ke::Zone *zone_; dvander@60: ke::Object **position_; dvander@60: HandleScope *prev_; dvander@60: dvander@60: HandleScope(ke::Zone *zone, ke::Object **position, HandleScope *prev) dvander@60: : zone_(zone), dvander@60: position_(position), dvander@60: prev_(prev) dvander@60: { dvander@60: } dvander@60: dvander@60: public: dvander@60: HandleScope(); dvander@60: ~HandleScope(); dvander@60: dvander@60: static ke::Object **CreateHandle(ke::Object *obj); dvander@60: dvander@60: private: dvander@60: // Disallow silly stuff. dvander@60: HandleScope(const HandleScope &); dvander@60: void operator =(const HandleScope &); dvander@60: void *operator new (size_t size); dvander@60: void operator delete(void *, size_t); dvander@60: }; dvander@60: dvander@60: class Module; dvander@60: dvander@60: /* dvander@60: * Initializes the Keima engine. This must be called exactly once before any dvander@60: * other Keima functions are called. After this, it is safe to use Keima dvander@60: * on the calling thread. dvander@60: */ dvander@60: extern bool Initialize(); dvander@60: dvander@60: /* dvander@60: * Shuts down the Keima engine and frees data structures on all threads. dvander@60: */ dvander@60: extern void Shutdown(); dvander@60: dvander@60: /* dvander@60: * Compiles a file and returns a Module. dvander@60: */ dvander@60: extern Local Compile(const char *path); dvander@60: dvander@61: class Internals dvander@61: { dvander@61: template friend class Root; dvander@61: dvander@61: private: dvander@61: static ke::HeapRoot *NewHeapRoot(ke::Object **objp); dvander@61: static void IncRef(ke::HeapRoot *root); dvander@61: static void DecRef(ke::HeapRoot *root); dvander@61: }; dvander@61: dvander@61: template Root dvander@61: Root::New(Handle other) dvander@61: { dvander@61: if (!other) dvander@61: return Root(NULL); dvander@61: ke::Object **ptr = reinterpret_cast(*other); dvander@61: return Root(Internals::NewHeapRoot(ptr)); dvander@61: } dvander@61: dvander@61: template void dvander@61: Root::incref() dvander@61: { dvander@61: if (!*this) dvander@61: return; dvander@61: ke::HeapRoot *ptr = reinterpret_cast(**this); dvander@61: Internals::IncRef(ptr); dvander@61: } dvander@61: dvander@61: template void dvander@61: Root::decref() dvander@61: { dvander@61: if (!*this) dvander@61: return; dvander@61: ke::HeapRoot *ptr = reinterpret_cast(**this); dvander@61: Internals::DecRef(ptr); dvander@61: } dvander@61: dvander@60: } dvander@60: dvander@60: #endif // _include_sourcepawn3_api_h_