Advertisement

CScriptAny and [ ] operator, Questions about ref counting

Started by June 01, 2012 01:06 AM
2 comments, last by WitchLord 12 years, 6 months ago
Hi,

after learning that i cant pass objects as pure pointers, i chose to use any ad-don.

i have an hashmap implementation like this,


r = engine->RegisterObjectType("hashmap2D", sizeof(hashmap2D), asOBJ_VALUE | asOBJ_APP_CLASS_C); assert( r >= 0 );

r = engine->RegisterObjectMethod("hashmap2D", "any @opIndex(const Vector2 &in)", asFUNCTION(hashmap2D::hashmap2DopIndex), asCALL_CDECL_OBJLAST) ; assert( r >= 0 );

r = engine->RegisterObjectMethod("hashmap2D", "any @Get(const Vector2 &in)", asMETHOD(hashmap2D, Get), asCALL_THISCALL); assert( r >= 0 );

r = engine->RegisterObjectMethod("hashmap2D", "void Set(const Vector2 &in, any @value)", asMETHOD(hashmap2D, Set), asCALL_THISCALL); assert( r >= 0 );




Destructor of hashmap2D is this. it calls release on all any objects

// this is called only once. when engine->Release(); called
for(Hash2D::iterator it = values.begin(); it != values.end();)
{
it->second->Release(); // refCount is -17891602, any is already destroyed, but why?
it = values.erase(it);
}


Set function

void Set(const Vector2 &pos, CScriptAny *obj)
{
obj->AddRef(); // addRef since i am storing it
values[pos] = obj;
}


get function

CScriptAny *Get(const Vector2 &pos)
{
if(!values.count(pos))
return 0;

return values[pos];
}



[ ] implemented like this

static CScriptAny * hashmap2DopIndex(const Vector2 &index, hashmap2D *self)
{
if( self->values.count(index) )
{
return self->values.at(index);
}
return 0;
}


script function calling [ ] operator is this


hashmap2D map; // global

void SomeFunc()
{
Vector2 pos(1,1);
any coord;
coord.store(Vector2(54, 84));
//refCount of any is 3
map.Set(pos, coord);
//refCount of any is 4 ( me + GC + SomeFunc + ?? ) // who owns 4th ref?

any coord2;
//refCount of any is 4
coord2 = map.Get(pos);
//refCount of any is 4
Vector2 stored;
coord2.retrieve(stored);

Vector2 v;
//refCount of any is 3, ???? why did it decrease?
any va = map[pos];
//refCount of any is 3
va.retrieve(v);
ConsoleOutput("Stored vector x: " + v.x + " y: " + v.y); // value accessed correctly
}



During program termition, it ends with a Heap corruption.
it seems i am over destroying it, but hashmap2D destructor is called only once.

it does not cause heap when i just call only [ ] or only Get. it does crash when i call both.

i am very confused on how hashmap2D is destroyed.
i hope i made the issue clear enough.

thank you.
When you receive a handle, it has already been grabbed. When you return a handle, it needs to be grabbed before being returned. If you use auto-handles ( @+ instead of @ ), your current code should work, but will be a bit slower than doing it yourself.
Advertisement

When you receive a handle, it has already been grabbed. When you return a handle, it needs to be grabbed before being returned. If you use auto-handles ( @+ instead of @ ), your current code should work, but will be a bit slower than doing it yourself.


as understand it Get and [] calls here decreases ref count of the any object.
i need to register them as "any @+opIndex " and "any @+Get"

this works.
but so does calling AddRef at each Get and [ ] calls. i will call AddRef since you said @+ is slower.
problem solved :) thank you

i have a little questions tho,

what's the diffrence between
any @coord2; @coord2 = map.Get(pos); // coord2 is a handle?
and
any coord2;coord2 = map.Get(pos); // coord2 is a value copied from @Get?, if so why do i have to increase its reference
?

is it same since any is asOBJ_REF?
It seems you already got your answer, but just in case it is still not clear:


Your Set() method should not call AddRef(). If it didn't store the handle, it should call Release().

Your Get() and opIndex() methods should call AddRef() before returning the handle.


@+ in the parameter lists will tell AngelScript to automatically release the handle after the function returns. So if you use this when registering your Set() method, then you don't need to change the code.

@+ in the return value will tell AngelScript to automatically call AddRef on the returned handle after the function returns. If you use it with your Get() and opIndex() methods you also do not need to change the code.

This is detailed in the manual.


With your last question: map.Get(pos) still returns a handle to the any object that will be released by AngelScript after it has been value copied to the local variable. That is why you have to increase its reference.

Regards,
Andreas

AngelCode.com - game development and more - Reference DB - game developer references
AngelScript - free scripting library - BMFont - free bitmap font generator - Tower - free puzzle game

This topic is closed to new replies.

Advertisement