Instantiating in Array - actionscript-3

I have these three objects that i need to add on stage, when I extract them from the array on a later stage of the program.
I can't write var mall: Mall = new Mall (); because somebody told me before that, This will add in the object in the memory and will be really bad if a lot of objects are being handled. I will have a lot more objects to work with later on.
So I would like to know a way that when i run a for loop or an event listener i can add ... = new object (); automatically and then call addchild to make an instance of the object.
var mall:Mall;
var library:Library;
var music:Music;
var choices:Array = new Array ();
choices.push(mall,library,music);
test Code for Garbage Collection :
var waking: WakingUp = new WakingUp ();
addChild (waking);
waking.y=-30;
waking.addEventListener (Event.ENTER_FRAME, waking_up);
function waking_up (g:Event){
if (waking.currentFrame == waking.totalFrames)
{
waking.stop ();
waking.removeEventListener (Event.ENTER_FRAME,waking_up);
removeChild (waking);
removeChild(alarm_slide);
gotoAndStop (6);
}
}
This is all the ref I have to this code :D

Specific to instantiating your array with elements, you can:
var choices:Array = [ mall, library, music ];
Flash Player runtime uses both reference counting as well as mark and sweep.
So, any reference to the instance adds a count - collections, display list, event listeners, class members... as instances are dereferenced, the memory will ultimately be freed.
Reference Counting
Each object on the heap keeps track of the number of things pointing to it. Each time you create a reference to an object, the
object's reference count is incremented. When you delete a reference,
the object's reference count is decremented. If the object has a zero
reference count (nothing is pointing to it), it is added to the Zero
Count Table (ZCT). When the ZCT is full, the stack is scanned to find
any references from the stack to an object on the ZCT. Any object on
the ZCT without a stack reference is deleted.
One of the problems of deferred reference counting is circular references. If ObjectA and ObjectB refer to each other but no other
objects in the system point to them, they will never have a zero
reference count and will therefore never be eligible for garbage
collection using reference counting. This is where mark and sweep
garbage collection helps.
Mark/Sweep
Applications that run in Flash Player or AIR have multiple GCRoots.
You can think about a GCRoot as the trunk of a tree with the objects
of the application as the branches. The Stage is a GCRoot. Loaders are
GCRoots. Certain menus are GCRoots. Every object that is still in use
by the application is reachable from one of the GCRoots within the
application. GCRoots are never garbage collected.
Every object in an application has a "mark bit." When the Mark phase
of garbage collection begins, all of those mark bits are cleared. The
MMgc keeps track of all GCRoots in the application. The garbage
collector starts from those roots, traces through each object and sets
the mark bit for every object it reaches. Any object that is no longer
reachable from any of the roots is no longer reachable from anywhere
in the application – its mark bit does not get set during the Mark
phase. Once the collector is done marking all of the objects it finds,
the Sweep phase begins. Any object that doesn't have a set mark bit is
destroyed and its memory reclaimed.

addChild does not make an instance of the object, it simply adds the object to the displaylist of the current display container.
Using new Mall() is fine - just ensure that you remove references to it when it's no longer required so that it may be garbage collected. Alternatively you can just hold an array of primitives.

Related

Set event.target to null

I want to nullify the event.target for garbage collection as the moveclip is no longer needed. What I have roughly is this:
mc.addEventListener(MouseEvent.CLICK, destroy);
public function destroy(event:MouseEvent):void {
event.target.parent.removeChild(event.target);
event.target.removeEventListener(MouseEvent.CLICK, destroyShape);
event.target = null; //THIS IS WHAT I WANT TO ACHIEVE
}
I'm sure this is relatively simple but I'm not sure how to do it.
thanks
You can't change MouseEvent.target value. It's a read only property. If your MovieClip doesn't exist (removeChild) and you removed event handler
mc.removeEventListener(MouseEvent.CLICK, destroy);
then the garbage collector automatically will remove it.
What you are trying to achieve (if it was even possible) would achieve nothing in term of Garbage Collection.
Unless redispatched the event will be garbage collected as soon as the method is done running. All properties of the event will also be discarded. This garbage collection of the event itself and its properties will have absolutely NO EFFECT on the object they point to in term of Garbage collection.
In the scope at which the event was dispatched in the first place the object will continue to exist after the event itself has been discarded. That is at that scope that the object reference must be nullified, not at the event listener scope where it will have no effect since the object still exists at the dispatching scope.
The solution accepted also does nothing. It is as relevant as applying a bandage to a wooden leg. Any local variable in function/method qualify for GC immediately after the method runs. Nullifying those variables has no effect whatsoever and does not constitute a valid answer to any problem and certainly not a GC problem. That those variables are GC does also not constitute a guaranty that the object they point to will be GC.
This is a case where a question about an inexistent and misunderstood problem is asked and answered by posting a false and irrelevant solution.
Case in point: Only a DisplayObject currently in a display list and attached to the stage has the ability to be the target of a MouseEvent. It is simply impossible for that object to become available for garbage collection before it is removed from the display list it belongs to. For those reasons that object cannot qualify for GC at the time the MouseEvent listener runs since that object still has at least one strong reference because it is attached to a display list. This is the proof that what the PO asks is misguided and any code examples are misguided as well since they cannot qualify the object for GC at that point in time.
As #subdan states, the target property of any Event is a readonly property.
You can still null your movie clip but not like in your sample.
mc.addEventListener(MouseEvent.CLICK, destroy);
public function destroy(event:MouseEvent):void
{
var myMC:MovieClip = event.target as MovieClip;
if( myMC )
{
myMC.removeEventListener(MouseEvent.CLICK, destroyShape);
myMC.parent.removeChild(myMC);
myMC = null; //THIS IS WHAT I WANT TO ACHIEVE
}
}

Can recreating a new variable inside a timer object decrease performance?

Hey everyone so I was wondering if recreating a variable movie clip inside a timer object every time it's called could decrease performance or cause a MEMORY LEAK. This is how I have it set up right now:
private function addSwimPowerUp(e:TimerEvent):void
{
var newSwimPower:mcSwimPower = new mcSwimPower();
stage.addChild(newSwimPower);
aSwimPowerUpArray.push(newSwimPower);
}
I do that with all my timer objects in my game. Should i just declare the var newSwimPower a private variable?
Creating a new instance of something and then not doing anything with it will result in its eventual garbage collection. That is, if your code was this:
private function addSwimPowerUp(e:TimerEvent):void
{
var newSwimPower:mcSwimPower = new mcSwimPower();
}
Then all of those new MovieClips will get cleant up.
With that said, you're adding those objects to the display tree as well asn an array. If you do not remove the object from both of those things, it will not get garbage collected and that will be a memory leak.
Creating a class level variable for newSwimPower and assigning to that instead won't make any difference, other than that if you don't garbage collect the class referencing it then the last instance you created will still be in memory.

Using retain and release for Objects

Are there any general guide lines for using retain and release for objects in cocos2d-X ? When creating objects in a function, is it true that the functions memory is cleaned up the second the function returns. When a object is created, calling the retain function of the object, will retain object beyond the function return ?
Kind Regards
Generally in c++ you have this behaviour:
void foo() {
Object a;
Object *pA = new Object();
(…)
}
This would result in a being destroyed automatically at function end, as it was allocated on stack. The *pA would not get destroyed, as it was allocated on the heap (thus, you only loose the reference to it, but the object itself still lives).
Cocos implements a thing called "Automatic Reference Counting" : each CCObject has a reference counter and two methods retain() and release(). The way this works is, that every time you create an object, it gets registered in cocos structers (CCPoolManager). Then with every frame (between them being drawn) there is a maintenance loop which checks the reference counter of all objects : if it is 0 this means (to cocos) that no other objects reference it, so it is safe to delete it. The retain count of an object is automatically incresead when you use this object as an argument for an addChild function.
Example :
void cocosFoo() {
CCSprite *a = CCSprite::create(…);
CCSprite *b = CCSprite::create(…);
this->addChild(b);
}
What happens here is this :
Two CCSprites are created, cocos knows about them.
The b sprite is added to this object (say a CCLayer)
The function ends, no objects are destroyed (both of them being on heap).
Somewhere between this and next frame, the maintanance gets run. Cocos chcecks both sprites and sees that a has reference count == 0, so it deletes it.
This system is quite good, as you don't need to worry about memory management. If you want to create a CCSprite (for example), but not add it as a child yet, you can call retain() on it, which will raise its reference counter, saving it from automatic deletion. But then you'd have to remember about calling release() on it (for example, when adding it as a child).
The general things you have to remeber about are :
Each call to retain() by you needs to be paired with release().
You generally shouldn't delete CCObjects yourself. If you feel that you need to, there is a conveniece macro : CC_SAFE_DELETE(object)
So to answer your questions in short :
Are there any general guide lines for using retain and release for objects in cocos2d-X ?
Yes, you should generally not need to do it.
When creating objects in a function, is it true that the functions memory is cleaned up the second the function returns.
Answer to this is the whole text above.
When a object is created, calling the retain function of the object, will retain object beyond the function return ?
Yes, as will adding it as a child to another (retained in any way) object.
Here is the thing,
cocos2dx has an autorelease pool which drains the objects which have retain count=0 which is a variable to keep in check the scope of the cocos2dx object.
Now when you create new object using the create method it is already added to the autorelease pool and you don't need to release it or delete it anywhere , its like garbage collector in java, takes care of garbage objects behind your back.
But when you create new object using 'new' you definitely need to release it in its destructor or after its use is over.
Second thing,
when your object is added to the autorelease pool but you need it somewhere else you could just retain it , this increments its retain count by one and then you have to manually release it after its use is over.
Third Thing,
Whenever you add child your object it is retained automatically but you don't need to release it rather you remove it from the parent.

Actionscript 3.0, using FlashDevelop: local variables. Can they be mistakenly created ad infinitum?

Riddle me this: I have my MouseEvent.MOUSE_DOWN which calls mouseHandler. The latter looks something like this:
public function mouseHandler(evt:MouseEvent):void
{
var p:Point = new Point(mouseX, mouseY);
var objs:Array = new Array(getObjectsUnderPoint(p));
}
Now what I want to know is thusly: will the objs array and p point be overwritten every time, simply causing the previous objs array and p point to be wiped and a new one generated, or...does it just create a new array and point over and over and over? Of course if I trace(objs) it gives me the expected results, but am I chocking up the system in the background without realising? Your expertise would be appreciated.
EDIT: well after learning a fair bit from the answerers -thanks btw- that made me think of something else and, a quick search later, found a way to theoretically reliably remove the references:
var a = null;
Now I appreciate that this is probably not needed as they'll be GCed at the end of the function, but considering it takes two ticks to write, better safe than sorry, no?
It works like this from what I understand - references for these variables will be lost after function will end. The values will be GC'ed then eventually.
If you will call the function second time, the new references will be created, and filled with new data, the values of previous references hovewer, may still exist in memory, and wait for Garbage Collector, but that may not necessarily happen! If they have attached listeners, the Flash Player will think that they are still useful, so they will exist in the memory to the end of the application run and listen, and even react to events - even if you theoretically cannot access them anymore.
Edit:
In your case whats happening is that you are creating two references that will disappear at the end of the function. They are not related to event listener, the listener creates them, but is not attached to them so it won't stop GC from collecting them after function will end. You creates an array of references, but that are just references to other objects that values are referred in other places (like the display list), if the array alone is not referred anywhere outside of this function, it should be GCted.
Since p is an object, not a primitive, the memory allocation for it will come from the Heap (and therefore need to be garbage collected) instead of the stack like local primitives (and are wiped once the function ends.
So new memory will be allocated every time this function is called, which will temporarily increase memory usage until they get GC'd, but the amount is probably insignificant (assuming that array isn't massive!).

destroy array()

How to free up memory and destroy Array, is it ok to do just like this
myarr = null
myarr = new Array
is all the old content of myarr now freed from memory?
Assuming you haven't got another reference to the array in another variable somewhere the arrays memory will be recovered when the GC gets to it.
If there are no more references to that Array Object, then it is collected by the Garbage Collection (GC) system. So when you ask "is all the old content of myarr now freed from memory?", the answer is it could be. But you have no control over when the GC runs using the Actionscript Virtual Machine.
So it is true to say, when there are no more references to an object, the next time the Garbage Collector runs, it will be collected.
Also things get more complex when you are dealing with a Array. The Array object might be collected, but that does not mean that the objects the Array references will be cleaned up too. The objects the Array references might be one of many references to those objects, for instance maybe a copy of that Array exists in your system, meaning at least two references exist to each object in each Array.
Also be aware that event listeners stop objects from being Garbage Collected, unless they are weak event listeners
myarr = nothing
Garbage Collection in .Net would sort this anyway. Thats if your in .NET.