Update to latest angelscript

This commit is contained in:
Marianne Gagnon
2015-05-11 19:40:43 -04:00
parent f269b44208
commit c48037984d
71 changed files with 11405 additions and 6307 deletions

View File

@@ -44,11 +44,6 @@ asIScriptObject *ScriptObjectFactory(const asCObjectType *objType, asCScriptEngi
int r = 0;
bool isNested = false;
// TODO: runtime optimize: There should be a pool for the context so it doesn't
// have to be allocated just for creating the script object
// TODO: It must be possible for the application to debug the creation of the object too
// Use nested call in the context if there is an active context
ctx = asGetActiveContext();
if( ctx )
@@ -63,9 +58,13 @@ asIScriptObject *ScriptObjectFactory(const asCObjectType *objType, asCScriptEngi
if( ctx == 0 )
{
r = engine->CreateContext(&ctx, true);
if( r < 0 )
// Request a context from the engine
ctx = engine->RequestContext();
if( ctx == 0 )
{
// TODO: How to best report this failure?
return 0;
}
}
r = ctx->Prepare(engine->scriptFunctions[objType->beh.factory]);
@@ -74,7 +73,7 @@ asIScriptObject *ScriptObjectFactory(const asCObjectType *objType, asCScriptEngi
if( isNested )
ctx->PopState();
else
ctx->Release();
engine->ReturnContext(ctx);
return 0;
}
@@ -105,7 +104,7 @@ asIScriptObject *ScriptObjectFactory(const asCObjectType *objType, asCScriptEngi
ctx->Abort();
}
else
ctx->Release();
engine->ReturnContext(ctx);
return 0;
}
@@ -117,7 +116,7 @@ asIScriptObject *ScriptObjectFactory(const asCObjectType *objType, asCScriptEngi
if( isNested )
ctx->PopState();
else
ctx->Release();
engine->ReturnContext(ctx);
return ptr;
}
@@ -241,7 +240,7 @@ asCScriptObject::asCScriptObject(asCObjectType *ot, bool doInitialize)
objType = ot;
objType->AddRef();
isDestructCalled = false;
weakRefFlag = 0;
extra = 0;
hasRefCountReachedZero = false;
// Notify the garbage collector of this object
@@ -250,7 +249,7 @@ asCScriptObject::asCScriptObject(asCObjectType *ot, bool doInitialize)
// Initialize members to zero. Technically we only need to zero the pointer
// members, but just the memset is faster than having to loop and check the datatypes
memset(this+1, 0, objType->size - sizeof(asCScriptObject));
memset((void*)(this+1), 0, objType->size - sizeof(asCScriptObject));
if( doInitialize )
{
@@ -299,15 +298,40 @@ void asCScriptObject::Destruct()
this->~asCScriptObject();
// Free the memory
#ifndef WIP_16BYTE_ALIGN
userFree(this);
#else
// Script object memory is allocated through asCScriptEngine::CallAlloc()
// This free call must match the allocator used in CallAlloc().
userFreeAligned(this);
#endif
}
asCScriptObject::~asCScriptObject()
{
if( weakRefFlag )
if( extra )
{
weakRefFlag->Release();
weakRefFlag = 0;
if( extra->weakRefFlag )
{
extra->weakRefFlag->Release();
extra->weakRefFlag = 0;
}
if( objType->engine )
{
// Clean the user data
for( asUINT n = 0; n < extra->userData.GetLength(); n += 2 )
{
if( extra->userData[n+1] )
{
for( asUINT c = 0; c < objType->engine->cleanScriptObjectFuncs.GetLength(); c++ )
if( objType->engine->cleanScriptObjectFuncs[c].type == extra->userData[n] )
objType->engine->cleanScriptObjectFuncs[c].cleanFunc(this);
}
}
}
asDELETE(extra, SExtra);
}
// The engine pointer should be available from the objectType
@@ -361,8 +385,8 @@ asILockableSharedBool *asCScriptObject::GetWeakRefFlag() const
// If the object's refCount has already reached zero then the object is already
// about to be destroyed so it's ok to return null if the weakRefFlag doesn't already
// exist
if( weakRefFlag || hasRefCountReachedZero )
return weakRefFlag;
if( (extra && extra->weakRefFlag) || hasRefCountReachedZero )
return extra->weakRefFlag;
// Lock globally so no other thread can attempt
// to create a shared bool at the same time.
@@ -373,12 +397,77 @@ asILockableSharedBool *asCScriptObject::GetWeakRefFlag() const
// Make sure another thread didn't create the
// flag while we waited for the lock
if( !weakRefFlag )
weakRefFlag = asNEW(asCLockableSharedBool);
if( !extra )
extra = asNEW(SExtra);
if( !extra->weakRefFlag )
extra->weakRefFlag = asNEW(asCLockableSharedBool);
asReleaseExclusiveLock();
return weakRefFlag;
return extra->weakRefFlag;
}
void *asCScriptObject::GetUserData(asPWORD type) const
{
if( !extra )
return 0;
// There may be multiple threads reading, but when
// setting the user data nobody must be reading.
// TODO: runtime optimize: Would it be worth it to have a rwlock per object type?
asAcquireSharedLock();
for( asUINT n = 0; n < extra->userData.GetLength(); n += 2 )
{
if( extra->userData[n] == type )
{
void *userData = reinterpret_cast<void*>(extra->userData[n+1]);
asReleaseSharedLock();
return userData;
}
}
asReleaseSharedLock();
return 0;
}
void *asCScriptObject::SetUserData(void *data, asPWORD type)
{
// Lock globally so no other thread can attempt
// to manipulate the extra data at the same time.
// TODO: runtime optimize: Instead of locking globally, it would be possible to have
// a critical section per object type. This would reduce the
// chances of two threads lock on the same critical section.
asAcquireExclusiveLock();
// Make sure another thread didn't create the
// flag while we waited for the lock
if( !extra )
extra = asNEW(SExtra);
// It is not intended to store a lot of different types of userdata,
// so a more complex structure like a associative map would just have
// more overhead than a simple array.
for( asUINT n = 0; n < extra->userData.GetLength(); n += 2 )
{
if( extra->userData[n] == type )
{
void *oldData = reinterpret_cast<void*>(extra->userData[n+1]);
extra->userData[n+1] = reinterpret_cast<asPWORD>(data);
asReleaseExclusiveLock();
return oldData;
}
}
extra->userData.PushLast(type);
extra->userData.PushLast(reinterpret_cast<asPWORD>(data));
asReleaseExclusiveLock();
return 0;
}
asIScriptEngine *asCScriptObject::GetEngine() const
@@ -417,14 +506,14 @@ int asCScriptObject::Release() const
// is ok to check the existance of the weakRefFlag without locking here
// because if the refCount is 1 then no other thread is currently
// creating the weakRefFlag.
if( refCount.get() == 1 && weakRefFlag )
if( refCount.get() == 1 && extra && extra->weakRefFlag )
{
// Set the flag to tell others that the object is no longer alive
// We must do this before decreasing the refCount to 0 so we don't
// end up with a race condition between this thread attempting to
// destroy the object and the other that temporary added a strong
// ref from the weak ref.
weakRefFlag->Set(true);
extra->weakRefFlag->Set(true);
}
// Call the script destructor behaviour if the reference counter is 1.
@@ -491,10 +580,13 @@ void asCScriptObject::CallDestructor()
if( ctx == 0 )
{
// Setup a context for calling the default constructor
asCScriptEngine *engine = objType->engine;
int r = engine->CreateContext(&ctx, true);
if( r < 0 ) return;
// Request a context from the engine
ctx = objType->engine->RequestContext();
if( ctx == 0 )
{
// TODO: How to best report this failure?
return;
}
}
}
@@ -538,7 +630,10 @@ void asCScriptObject::CallDestructor()
ctx->Abort();
}
else
ctx->Release();
{
// Return the context to engine
objType->engine->ReturnContext(ctx);
}
}
}
@@ -726,9 +821,13 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other)
if( ctx == 0 )
{
r = engine->CreateContext(&ctx, true);
if( r < 0 )
// Request a context from the engine
ctx = engine->RequestContext();
if( ctx == 0 )
{
// TODO: How to best report this failure?
return *this;
}
}
r = ctx->Prepare(engine->scriptFunctions[objType->beh.copy]);
@@ -737,7 +836,8 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other)
if( isNested )
ctx->PopState();
else
ctx->Release();
engine->ReturnContext(ctx);
// TODO: How to best report this failure?
return *this;
}
@@ -773,14 +873,20 @@ asCScriptObject &asCScriptObject::operator=(const asCScriptObject &other)
ctx->Abort();
}
else
ctx->Release();
{
// Return the context to the engine
engine->ReturnContext(ctx);
}
return *this;
}
if( isNested )
ctx->PopState();
else
ctx->Release();
{
// Return the context to the engine
engine->ReturnContext(ctx);
}
}
}