Retain/release couple for CCObject necessary? - cocos2d-x

Can somebody explain why retain and release here? I can't see it is necessary.
Code as follows, thanks.
void CCDictionary::setObject(CCObject* pObject, const std::string& key) {
CCAssert(key.length() > 0 && pObject != NULL, "Invalid Argument!");
if (m_eDictType == kCCDictUnknown)
{
m_eDictType = kCCDictStr;
}
CCAssert(m_eDictType == kCCDictStr, "this dictionary doesn't use string as key.");
CCDictElement *pElement = NULL;
HASH_FIND_STR(m_pElements, key.c_str(), pElement);
if (pElement == NULL)
{
setObjectUnSafe(pObject, key);
}
else if (pElement->m_pObject != pObject)
{
CCObject* pTmpObj = pElement->m_pObject;
pTmpObj->retain();
removeObjectForElememt(pElement);
setObjectUnSafe(pObject, key);
pTmpObj->release();
}
}

You should see the details of what the function removeObjectForElement(pElement) does.
It is safer to retain the pTmpObj if the function removeObjectForElement would access the field of what the pointer pTmpObj points to.
If the object which pTmpObj points to is released by another procedure, you may get BAD_ACCESS error when call the removeObjectForElement method here.

Cocos2d-x containers (CCDictionary, CCArray) retains object when it's added, and release when object removed from container. Container itself is interface to another structure, ccArray or uthash, that does not use cocos2d-x's reference counting system and operates with raw data instead of CCObjects.
Most of CCObjects are autoreleased. Autoreleased object deleted at the end of update cycle, if it's reference counter hits 1 (retained only by list of autoreleased object). Autoreleased object can safely be removed from container, then added into another container inside single update cycle.
But if object is not autoreleased, it's deleted immediately when reference counter hits 0. So, when cocos2d-x container call release, object can be deleted, but object's pointer can still be stored in uthash or ccArray.
To protect object from being deleted, when data structure stores it's pointer, we retain object, then release it at the end of procedure.
This pattern also should be used, for example, when we move node from one parent to another:
node->retain();
node->removeFromParent();
newRoot->addChild(node);
node->release();
Usually, node is autoreleased, and it's safe to move it this way. But if node is not autoreleased, removeFromParent call can delete it, and node becomes garbage pointer.

Related

lua not modifying function arguments

I've been learning lua and can't seem to make a simple implementation of this binary tree work...
function createTree(tree, max)
if max > 0 then
tree = {data = max, left = {}, right = {}}
createTree(tree.left, max - 1)
createTree(tree.right, max - 1)
end
end
function printTree(tree)
if tree then
print(tree.data)
printTree(tree.left)
printTree(tree.right)
end
end
tree = {}
createTree(tree, 3)
printTree(tree)
the program just returns nil after execution. I've searched around the web to understand how argument passing works in lua (if it is by reference or by value) and found out that some types are passed by reference (like tables and functions) while others by value. Still, I made the global variable "tree" a table before passing it to the "createTree" function, and I even initialized "left" and "right" to be empty tables inside of "createTree" for the same purpose. What am I doing wrong?
It is probably necessary to initialize not by a new table, but only to set its values.
function createTree(tree, max)
if max > 0 then
tree.data = max
tree.left = {}
tree.right = {}
createTree(tree.left, max - 1)
createTree(tree.right, max - 1)
end
end
in Lua, arguments are passed by value. Assigning to an argument does not change the original variable.
Try this:
function createTree(max)
if max == 0 then
return nil
else
return {data = max, left = createTree(max-1), right = createTree(max-1)}
end
end
It is safe to think that for the most of the cases lua passes arguments by value. But for any object other than a number (numbers aren't objects actually), the "value" is actually a pointer to the said object.
When you do something like a={1,2,3} or b="asda" the values on the right are allocated somewhere dynamically, and a and b only get addresses of those. Thus, when you pass a to the function fun(a), the pointer is copied to a new variable inside function, but the a itself is unaffected:
function fun(p)
--p stores address of the same object, but `p` is not `a`
p[1]=3--by using the address you can
p[4]=1--alter the contents of the object
p[2]=nil--this will be seen outside
q={}
p={}--here you assign address of another object to the pointer
p=q--(here too)
end
Functions are also represented by pointers to them, you can use debug library to tinker with function object (change upvalues for example), this may affect how function executes, but, once again, you can not change where external references are pointing.
Strings are immutable objects, you can pass them around, there is a library that does stuff to them, but all the functions in that library return new string. So once, again external variable b from b="asda" would not be affected if you tried to do something with "asda" string inside the function.

how NamedParameterJdbcTemplate.update really works with Spring and MySQL

Ok, I've probably dug up the entire Google land and still couldn't find anything that could possibly answer my question.
I have my little foo method that does some deleting like this:
private void foo()
{
jdbcNamedParameterTemplate.update(sqlString, params); //1
jdbcNamedParameterTemplate.update(sqlString2, params2); //2
}
sqlString and sqlString2 are just delete statements like "Delete * from FooBar".
So when I get to the second call to update, do I have any guarantee that whatever operation the first one invokes in the database has already finished?
If you do that two in one session, and non multithreading, then yes the first one invokes in the database has already finished before the second update.
But if not in the same session you can check the version to check if the object already changed or not
int oldVersion = foo.getVersion();
session.load( foo, foo.getKey() ); // load the current state
if ( oldVersion != foo.getVersion()) { .... }// if true then the object has been changed

Best way to cache results of method with multiple parameters - Object as key in Dictionary?

At the beginning of a method I want to check if the method is called with these exact parameters before, and if so, return the result that was returned back then.
At first, with one parameter, I used a Dictionary, but now I need to check 3 parameters (a String, an Object and a boolean).
I tried making a custom Object like so:
var cacheKey:Object = { identifier:identifier, type:type, someBoolean:someBoolean };
//if key already exists, return it (not working)
if (resultCache[cacheKey]) return resultCache[cacheKey];
//else: create result ...
//and save it in the cache
resultCache[cacheKey] = result;
But this doesn't work, because the seccond time the function is called, the new cacheKey is not the same object as the first, even though it's properties are the same.
So my question is: is there a datatype that will check the properties of the object used as key for a matching key?
And what else is my best option? Create a cache for the keys as well? :/
Note there are two aspects to the technical solution: equality comparison and indexing.
The Cliff Notes version:
It's easy to do custom equality comparison
In order to perform indexing, you need to know more than whether one object is equal to another -- you need to know which is object is "bigger" than the other.
If all of your properties are primitives you should squash them into a single string and use an Object to keep track of them (NOT a Dictionary).
If you need to compare some of the individual properties for reference equality you're going to have a write a function to determine which set of properties is bigger than the other, and then make your own collection class that uses the output of the comparison function to implement its own a binary search tree based indexing.
If the number of unique sets of arguments is in the several hundreds or less AND you do need reference comparison for your Object argument, just use an Array and the some method to do a naive comparison to all cached keys. Only you know how expensive your actual method is, so it's up to you to decide what lookup cost (which depends on the number of unique arguments provided to the function) is acceptable.
Equality comparison
To address equality comparison it is easy enough to write some code to compare objects for the values of their properties, rather than for reference equality. The following function enforces strict set comparison, so that both objects must contain exactly the same properties (no additional properties on either object allowed) with the same values:
public static propsEqual(obj1:Object, obj2:Object):Boolean {
for(key1:* in obj1) {
if(obj2[key1] === undefined)
return false;
if(obj2[key1] != obj2[key1])
return false;
}
for(key2:* in obj2)
if(obj1[key2] === undefined)
return false;
return true;
}
You could speed it up by eliminating the second for loop with the tradeoff that {A:1, B:2} will be deemed equal to {A:1, B:2, C:'An extra property'}.
Indexing
The problem with this in your case is that you lose the indexing that a Dictionary provides for reference equality or that an Object provides for string keys. You would have to compare each new set of function arguments to the entire list of previously seen arguments, such as using Array.some. I use the field currentArgs and the method to avoid generating a new closure every time.
private var cachedArgs:Array = [];
private var currentArgs:Object;
function yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
currentArgs = { stringArg:stringArg, objArg:objArg, boolArg:boolArg };
var iveSeenThisBefore:Boolean = cachedArgs.some(compareToCurrent);
if(!iveSeenThisBefore)
cachedArgs.push(currentArgs);
}
function compareToCurrent(obj:Object):Boolean {
return someUtil.propsEqual(obj, currentArgs);
}
This means comparison will be O(n) time, where n is the ever increasing number of unique sets of function arguments.
If all the arguments to your function are primitive, see the very similar question In AS3, where do you draw the line between Dictionary and ArrayCollection?. The title doesn't sound very similar but the solution in the accepted answer (yes I wrote it) addresses the exact same techinical issue -- using multiple primitive values as a single compound key. The basic gist in your case would be:
private var cachedArgs:Object = {};
function yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
var argKey:String = stringArg + objArg.toString() + (boolArg ? 'T' : 'F');
if(cachedArgs[argKey] === undefined)
cachedArgs[argKey] = _yourMethod(stringArg, objArg, boolArg);
return cachedArgs[argKey];
}
private function _yourMethod(stringArg:String, objArg:Object, boolArg:Boolean):* {
// Do stuff
return something;
}
If you really need to determine which reference is "bigger" than another (as the Dictionary does internally) you're going to have to wade into some ugly stuff, since Adobe has not yet provided any API to retrieve the "value" / "address" of a reference. The best thing I've found so far is this interesting hack: How can I get an instance's "memory location" in ActionScript?. Without doing a bunch of performance tests I don't know if using this hack to compare references will kill the advantages gained by binary search tree indexnig. Naturally it would depend on the number of keys.

"An attempt has been made to Attach or Add an entity that is not new..." after calling ObjectChangeConflict.Resolve()

I have a pair of classes which, when updated together as shown below are guaranteed to cause a ChangeConflictException because a trigger on child object table updates a value on the parent object record. I believe I am following the correct procedure for resolving the conflict and resubmitting the update, but upon calling the second db.SubmitChanges (or even if I call db.GetChangeSet()), I get the "an attempt has been made to attach or add an entity that is not new blah blah blah" error.
using (SurveyDB db = new SurveyDB())
{
Parent p = db.Parents.Single(t => t.Id == 1);
p.Children.Add(new Child {...});
p.SomeProperty = "new value";
try
{
db.SubmitChanges();
}
catch (ChangeConflictException e)
{
foreach (ObjectChangeConflict o in db.ChangeConflicts)
o.Resolve(RefreshMode.KeepChanges, true);
db.SubmitChanges(ConflictMode.FailOnFirstConflict);
}
}
Any help greatly appreciated.
The resolution for me was to set dbml "Update Check" property for the fields set by the trigger to "Never" - this works for the situation where the application never modifies those fields. Otherwise, I'd have had to call SubmitChanges twice - once after editing the parent object and then again after adding the child object (followed by retrieving the parent-object again).

Can you have "ByRef" arguments in AS3 functions?

Any idea how to return multiple variables from a function in ActionScript 3?
Anything like VB.NET where you can have the input argument's variable modified (ByRef arguments)?
Sub do (ByRef inout As Integer)
inout *= 5;
End Sub
Dim num As Integer = 10
Debug.WriteLine (num) '10
do (num)
Debug.WriteLine (num) '50
Anything apart from returning an associative array?
return {a:"string 1", b:"string 2"}
Quoting a googled source:
In ActionScript 3.0, all arguments are passed by reference because all values are stored as objects. However, objects that belong to the primitive data types, which includes Boolean, Number, int, uint, and String, have special operators that make them behave as if they were passed by value.
Which led me to look up the canonical source.
It appears that Strings, ints, units, Booleans are passed by Value.
I tried this little snippet in Flash and the results were negative:
function func(a:String){
a="newVal";
}
var b:String = "old";
trace(b) // old
func(b);
trace(b) // old
So... is String a blacklisted data type too? Boolean too?
I mean whats a sure way of telling which types are passed by reference?
Everything in AS3 is a reference aside from [u]ints. To generalize, everything that inherits Object will be given to the function by a reference.
That being said, the only way I believe you can do it is use a container class like an Array or a String ("5" and do the conversion+math).
It's all by value, if you understand C programming you will be familiar with the concept of pointers.
Think about a pointer as pointing to something in memory, and all variable names "bob from (bob = new person();)" Are essentially pointers that you work with.
Now, when you declare a function, since they are all By Value
function Test(a:Object, b:Object):void {
a = b;
}
You can think about both "a" and "b" being new pointers, so only within the "Test" function do both "a" and "b" exist and point to something in memory.
So let's use it
var s1:Sprite = null;
var s2:Sprite = new Sprite;
Test(s1,s2);
So the s1 and s2 pointers will ALWAYS point to "null" and "a new Sprite in memory" respectively, unless they are modified as s1 and s2 within their "Scope" <- Please make sure you understand variable scope before even trying to tackle this.
And within the function we now have two new pointers "a" pointing to "null" and "b" pointing to "the same sprite in memory as s2". so Since objects and arrays are essentially collections of pointers and only two new pointers have been created by the function for use "a" and "b" any properties/exposed variables "pointers to data in memory" of "a" or "b" will still be exactly the same as the ones for "s1" and "s2" and are the exact same pointers.
So within the function when "a" gets set to be "b", really all that happens is the "a" pointer now points to the same thing as "b". But "s1" and "s2" still point to what they were pointing to before.
!!!!
If this was by reference you would not be able to think of "a" and "b" as new pointers, they would actually be "s1" and "s2" themselves, except you write them out as "a" and "b".
Wrong Wrong Wrong and Wrong.. every Argument is passed by value!!!
the fact you can change a property inside the object passed doesn't mean you can change the object itself. try the following code
function Test(a:Object, b:Object):void {
a = b;
}
function Test2():void {
var s1:Sprite = null;
var s2:Sprite = new Sprite;
Test(s1,s2);
Trace(s1);
Trace(s2);
}
and here's the trace result :
null
[object Sprite]
Note the subtle difference between DarthZorG's example and this one from the Flash docs:
function passByRef(objParam:Object):void
{
objParam.x++;
objParam.y++;
trace(objParam.x, objParam.y);
}
var objVar:Object = {x:10, y:15};
trace(objVar.x, objVar.y); // 10 15
passByRef(objVar); // 11 16
trace(objVar.x, objVar.y); // 11 16
Point Being:
You can't change what the reference is pointing to but you can change the data that the reference is pointing to, so long as that reference is an Object/Array.