Update to latest angelscript
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user