Actions memory management: when are they released? - cocos2d-iphone

When you add an action to a sprite, since most things in Cocos are autoreleased, is it then released after it completes? Or, because you added it to a node, is it retained by the node?
If the action then ends, either due to completing on its own or because you stop it yourself, is it then released or is it still available to be run later?
I ask because I want to know if you need to recreate actions to reuse them, or if you can simply reference their tag and start and stop them at will whenever you want. Of if they repeat, if you can simply get them by tag number and then run them again; it's not clear the "correct" way to go about this. Thanks for help.

My understanding is that when you create and run an action on a sprite, the action is added to CCActionManager, which is a singleton that will manage the actions for you. This includes releasing all of them when the CCACtionManager itself is released and also when the action is done.
This is the relevant code about the latter (from CCActionManager.m):
-(void) update: (ccTime) dt
{
for(tHashElement *elt = targets; elt != NULL; ) {
...
if( ! currentTarget->paused ) {
// The 'actions' ccArray may change while inside this loop.
for( currentTarget->actionIndex = 0; currentTarget->actionIndex < currentTarget->actions->num; currentTarget->actionIndex++) {
....
if( currentTarget->currentActionSalvaged ) {
....
[currentTarget->currentAction release];
} else if( [currentTarget->currentAction isDone] ) {
....
CCAction *a = currentTarget->currentAction;
currentTarget->currentAction = nil;
[self removeAction:a];
}
.....
}
}
After doing some research, it seems that the topic of reusing and action is on shaky grounds. Anyway, you can read here what the cocos2d best practices suggest. IMO, I would not try and reuse an action...

Actions are one-shot classes. Once the action is "done" or has been stopped or the node that runs the action is deallocated the action will be (auto-)released.
If you need to re-use actions, there's only a rather scary solution available: you need to send the corresponding init… message to the existing action again. You will also have to manually retain the action.
Actions are very lightweight classes, their runtime performance is comparable to allocating a new NSObject instance. Personally, I think if you're in performance trouble because you're creating and releasing many actions, I would say that you're using actions too much and should look for a better solution.

When you pass the reference to the CCNode with the runAction message it hands it to a CCActionManager which sends the action a retain message. Once the action is completes it sends a release message. If you want to keep using an action you should keep a reference to it and send your own retain and release messages.
The actions are designed to be lightweight "fire and forget" objects. I wouldn't worry about it unless you're noticing performance problems and trace it back to them.

Related

Implementing a custom async task type and await

I am developing a C++ app in which i need to receive messages from an MQ and then parsing them according to their type and for a particular reason I want to make this process (receiving a single message followed by processing it) asynchronous. Since, I want to keep things as simple as possible in a way that the next developer would have no problem continuing the code, I have written a very small class to implement Asynchrony.
I first raise a new thread and pass a function to the thread:
task = new thread([&] {
result = fn();
isCompleted = true;
});
task->detach();
and in order to await the task I do the following:
while (!isCompleted && !(*cancelationToken))
{
Sleep(5);
}
state = 1; // marking the task as completed
So far there is no problem and I have not faced any bug or error but I am not sure if this is "a good way to do this" and my question is focused on determining this.
Read about std::future and std::async.
If your task runs in another core or processor, the variable isCompleted may become un-synchronized having two copies in core cache. So you may be waiting more than needed.
If you have to wait for something it is better to use a semaphore.
As said in comments, using standard methods is better anyway.

Correct way to stop asynchronous ISearchJob

I am going to use WUA API and begin execution of an asynchronous search for updates in this way:
CComPtr<SearchCallbackImpl> iscc_; <<-- Note you need to CreateInstance
CComPtr<ISearchJob> pUpJob_;
pUpJob_ = NULL;
pUpSearcher_->BeginSearch(
CComVariant(criteria.c_str()).bstrVal,
iscc_,
CComVariant(L"Scanning"),
&pUpJob_);
When I need to stop my program, but ISearchJob has not completed yet, I use this code:
if (pUpJob_)
{
CComVariant isStopped;
pUpJob_->get_IsCompleted(&isStopped.boolVal);
if (isStopped.boolVal == VARIANT_FALSE)
{
if (SUCCEEDED(pUpJob_->RequestAbort()))
{
pUpJob_->CleanUp();
pUpJob_.Release();
}
}
}
Generally this code works but sometime it hangs on pUpJob_->CleanUp(); and I do not have ability to stop my programm correctly.
So my questions are:
What is the correct way to stop asynchronous search job for updates?
Also i misunderstood what is difference between ISearchJob::CleanUp and ISearchJob::RequestAbort and how to use this methods to stop asynchronous search correctly?
Should this methods be used together or separately?
RequestAbort() is also asynchronous (the hint to that is in the name). After calling it, you should call pUpSearcher_->EndSearch(); it will return an ISearchResult with ResultCode equal to orcAborted if the abort was successful. Then you can free your resources.
I'm not fully sure how CleanUp() is supposed to be used, but this page seems to imply it's intended for scripts that have callbacks, and that you're not supposed to call CleanUp() from within a callback. Not sure where your code for cancelling is run.

Polymer not unlistening properly

I use Polymer.Templatizer to stamp templates of paper-input collections into a custom-element which has a listener 'change':'_doStuff'.
Basically when I stamp 20 paper-inputs via Polymer.dom(this).appendChild(template.root) a bunch of listeners are added , as you can see in the graph.
Then I call another function that goes through all of those elements and does Polymer.dom(paperInput.parentNode).removeChild(paperInput) and adds another set of inputs. But it just doesn't detach listeners on those for some reason and the heap is growing with every iteration...
The listener change on the host element, I believe, is neither detached.
What am I doing wrongly?
EDIT: I know what it is, it's not garbage collection problem, but Polymer creates anonymous Polymer.Base instances when templatizing and actually puts all template's children into those. of course the instances are not removed in any way. I wish I knew how to kill those not to reduce performance of the app. By defining custom elements instead? Looks like an overhead to me...
A way to free your memory could be to unlisten all of your listeners before you detach your elements, in order them to be unreferenced first. For example :
for (var i = 0; i < inputList.length; i++) {
this.unlisten(inputList[i], 'change', 'doStuff');
Polymer.dom(inputList[i].parentNode).removeChild(inputList[i]);
}

Having to pass a lot of information about using inheritance, am I using it correctly?

In a turn-based combat game, all actions that characters can perform inherit from this class. It started off looking like this:
using ActionPtr = std::shared_ptr<Action>;
class Action {
public:
Action(Entity actor, std::uint32_t time) { ... }
virtual ActionPtr execute() = 0;
...
std::uint32_t time; // time that the action will occur. For e.g 10 if it occurs in tick 10 of combat
Entity actor; // the character performing the action
};
Upon entering combat, everyone gets a DecideAction that allows characters to decide what to do (either bring up menus for the player, or the AI choosing actions).
The combat system's maintains a timeline of actions; sorted by the time that actions should occur and the speed of actors to break ties. Its update function does something like this:
sortTimeline();
ActionPtr followUpAction = timeline.front()->execute();
timeline.removeFront();
timeline.push_back(followUpAction);
For example, the AiDecideAction executing returns the follow-up action (i.e what that entity chose to do). An attack action's execution would return a decide action set to happen after attack-dependent cooldowns. These actions get added and processed in the next tick.
Since actions can create other actions, I'm finding that I have to push all the possible info that actions may require to execute to the Action class, the root of the inheritance hierarchy. This is so that it can properly construct follow-up actions. For e.g
AttackAction::execute() {
...
return ActionPtr(new AiDecide(actor, nextActionTime, allies, enemies);
// allow this entity to decide what to do after attacking
}
The attack action needs access to allies and enemies just to supply it to constructors; so I ended up modifying the constructor of Action to take in all possible info that derived actions may require to try solving this problem.
Is there a better way of doing this? I'm wondering if inheritance is the right way to model this problem. I've had to modify all actions several times so that information required for constructing other actions is present, which isn't ideal.

Asynchronous network calls

I made a class that has an asynchronous OpenWebPage() function. Once you call OpenWebPage(someUrl), a handler gets called - OnPageLoad(reply). I have been using a global variable called lastAction to take care of stuff once a page is loaded - handler checks what is the lastAction and calls an appropriate function. For example:
this->lastAction == "homepage";
this->OpenWebPage("http://www.hardwarebase.net");
void OnPageLoad(reply)
{
if(this->lastAction == "homepage")
{
this->lastAction = "login";
this->Login(); // POSTs a form and OnPageLoad gets called again
}
else if(this->lastAction == "login")
{
this->PostLogin(); // Checks did we log in properly, sets lastAction as new topic and goes to new topic URL
}
else if(this->lastAction == "new topic")
{
this->WriteTopic(); // Does some more stuff ... you get the point
}
}
Now, this is rather hard to write and keep track of when we have a large number of "actions". When I was doing stuff in Python (synchronously) it was much easier, like:
OpenWebPage("http://hardwarebase.net") // Stores the loaded page HTML in self.page
OpenWebpage("http://hardwarebase.net/login", {"user": username, "pw": password}) // POSTs a form
if(self.page == ...): // now do some more checks etc.
// do something more
Imagine now that I have a queue class which holds the actions: homepage, login, new topic. How am I supposed to execute all those actions (in proper order, one after one!) via the asynchronous callback? The first example is totally hard-coded obviously.
I hope you understand my question, because frankly I fear this is the worst question ever written :x
P.S. All this is done in Qt.
You are inviting all manner of bugs if you try and use a single member variable to maintain state for an arbitrary number of asynchronous operations, which is what you describe above. There is no way for you to determine the order that the OpenWebPage calls complete, so there's also no way to associate the value of lastAction at any given time with any specific operation.
There are a number of ways to solve this, e.g.:
Encapsulate web page loading in an immutable class that processes one page per instance
Return an object from OpenWebPage which tracks progress and stores the operation's state
Fire a signal when an operation completes and attach the operation's context to the signal
You need to add "return" statement in the end of every "if" branch: in your code, all "if" branches are executed in the first OnPageLoad call.
Generally, asynchronous state mamangment is always more complicated that synchronous. Consider replacing lastAction type with enumeration. Also, if OnPageLoad thread context is arbitrary, you need to synchronize access to global variables.