What are the potential repercussions of a lazy property getting initialised more than once? - swift

The Apple doc says that
If a property marked with the lazy modifier is accessed by multiple
threads simultaneously and the property has not yet been initialized,
there is no guarantee that the property will be initialized only once.
My question is what are the potential repercussions of a property getting initialized more than once?
And in case of a property getting initialized more than once, which one of it will be used? How Swift manages them?
I went through some of the answers.
Is it normal that lazy var property is initialized twice?
But they are just saying that lazy properties can get initialized more than once. I want to know what are the repercussions of this.
Thanks in advance.

(See my comment to rmaddy's answer regarding my concern about thread-safety on writing the pointer itself. My gut is that memory corruption is not possible, but that object duplication is. But I can't prove so far from the documentation that memory corruption isn't possible.)
Object duplication is a major concern IMO if the lazy var has reference semantics. Two racing threads can get different instances:
Thread 1 begins to initialize (object A)
Thread 2 begins to initialize (object B)
Thread 1 assigns A to var and returns A to caller
Thread 2 assigns B to var and returns B to caller
This means that thread 1 and thread 2 have different instances. That definitely could be a problem if they are expecting to have the same instance. If the type has value semantics, then this shouldn't matter (that being the point of value semantics). But if it has reference semantics, then this very likely be a problem.
IMO, lazy should always be avoided if multi-threaded callers are possible. It throws uncertainty into what thread the object construction will occur on, and the last thing you want in a thread-safe object is uncertainty about what thread code will run on.
Personally I've rarely seen good use cases for lazy except for where you need to pass self in the initializer of one of your own properties. (Even then, I typically use ! types rather than lazy.) In this way, lazy is really just a kludgy work-around a Swift init headache that I wish we could solve another way, and do away with lazy, which IMO has the same "doesn't quite deliver what it promises, and so you probably have to write your own version anyway" problem as #atomic in ObjC.
The concept of "lazy initialization" is only useful if the type in question is both very expensive to construct, and unlikely to ever be used. If the variable is actually used at some point, it's slower and has less deterministic performance to make it lazy, plus it forces you to make it var when it is most often readonly.

The answer completely depends on the code you have inside the implementation of the lazy property. The biggest problem would arise from any side effects you've put in the code since they might be called more than once.
If all you do is create a self-contained object, initialize it, and return it, then there won't be any issues.
But if also do things like add a view, update an array or other data structure, or modify other properties, then you have an issue if the lazy variable is created more than once since all of those side effects will happen more than once. You end up adding two views or adding two objects to the array, etc.
Ensure that the code in your lazy property only creates and initializes an object and does not perform any other operations. If you do that, then your code won't cause any issues if the lazy property gets created multiple times from multiple threads.

Related

How to delete object using blueprints (not actor)

Ok I've created some class which inherits from UObject. I can created it in level BP (using Construct object node) and store reference in my BP variable. When I'm creating object I'm setting Outer as self. So level BP owning newly created object. Now my question is how to delete this object from memory? I tried to set BP variable to null but it seems that I need to destroy level to release this object. Any idea how to do it without destorying level?
I have no access to UE4 at this moment but I hope this can help/hint you to a right direction:
UObjects are managed by the garbage collector. To create a UObject appropriately, use NewObject(), NewNamedObject() and ConstructObject(). It is possible to configure the way UObjects will be handled by garbage collector at the time of creation with Object Flags enumeration. (If you like to learn more about UObject Instance Creation, you can go here: hhttps://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Objects/Creation/index.html )
This way, you should not call new or delete on UObjects. If UObject is no longer needed, it usually means that there are no references to it (this may, however differ, depending on the context and garbage collection flags used at the moment of UObject creation). In this situation, you can run ForceGarbageCollection() function:
GetWorld()->ForceGarbageCollection(true);
Please note, that calling this method may cause crashes in some situations, particularly when object is already being destroyed by garbage collector or has a value of null.
Also, if you like to learn more about Unreal Object Handling, you can go here: hhttps://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Objects/Optimizations/index.html
Credit : https://answers.unrealengine.com/questions/219430/explicitely-delete-a-uobject.html
Ps. StackOverflow doesn't allow me to post more than two links because I don't have enough reputation ... so remove the first 'h' from my broken links, it'll work.
I managed to resolve this, I also got some clues given on unreal answer hub: https://answers.unrealengine.com/questions/337525/how-to-delete-object-using-blueprints.html
So basically answer is: set reference variable to null, and at some moment GC will release it. But don't expect to have this instantly.

what is the difference between `doc.AddMember("key1",1,document.GetAllocator())` and `doc["key1"]=1`?

I want to create a json object in cocos2d-x 3.4 with rapidjson and convert it to a string:
rapidjson::Document doc;
doc.SetObject();
doc.AddMember("key1",1,doc.GetAllocator());
doc["key2"]=2;
rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
doc.Accept(writer);
CCLOG("%s",sb.GetString());
but the output is {"key1":1} not {"key1":1,"key2":2}, why?
In old (0.1x) versions of RapidJSON, doc["key2"] returns a Value singleton representing Null. doc["key2"] = 2 actually writes to that singleton.
In newer versions of RapidJSON (v1.0.x), this behavior has been changed. It basically make assertion fail for a key that is not found in a JSON object, in order to solve exact problem you mentioned.
As a reminder, when an operation potentially requires allocating memory (such as AddMember or PushBack, an Allocator object must be appeared. Since operator[] normally only has one parameter, it cannot add new members as in STL. This is quite weird and not very user-friendly, but this is a tradeoff in RapidJSON's design for performance and memory overheads.

Arguments and selectors

Is this:
[self showInWindow:window];
what get called after delay by this code:
[self performSelector:#selector(showInWindow:)
withObject:window
afterDelay:delay];
or am I misunderstanding the method?
Edit: the problem I'm having is that the method showInWindow get called after the delay but behaves like [self showInWindow:nil]. Any suggestion?
Yes, that's what gets called. (After the delay, of course.)
The documentation doesn't really explain what it means to "perform the selector", but what it means is exactly what you suspect.
There is one small difference between using performSelector:withObject: type methods and sending the message directly: they only work if the object is actually an object (that is, an id, a pointer to an Objective C object). But window obviously is an object.
(Strictly speaking, this isn't quite true. If you pass something that's the same size as an id or smaller, it will often work. In some cases it won't. In some cases it will work, but is illegal. In some cases, it will work and is legal but Apple strongly recommends against it. There are no cases where it's a good idea—so instead of learning the specific rules, just assume it never works. The only reason to bring this up is that this used to be common practice in Objective C back in the NeXT days, so you may occasionally still see it in other people's today.)
For more information about the performSelector: family, see the NSObject Protocol Reference, and the SO question Using -performSelector: vs. just calling the method. (For information specifically about the afterDelay: variants, see the documentation linked above.)
From the later edit to the question:
the problem I'm having is that the method showInWindow get called after the delay but behaves like [self showInWindow:nil]. Any suggestion?
First, in what way does it "behave like" the parameter is nil? Is the parameter actually nil? (Just log it in the showInWindow: implementation; if you haven't overridden the base implementation, just add an override that logs and calls the base.)
Second, if it actually is nil, was it nil at the time you sent performSelector:withObject:afterDelay:? If so, obviously it'll still be nil when the selector is sent. Also, make sure window really is an id rather than some other type. (Note that if you've got members, properties, globals, and/or locals sharing the name window, it can be confusing which one you're referring to. This is a common source of problems.)
If it's actually not nil when you schedule it, but is nil when it arrives, there are a few ways that could happen, but they're all less likely, and trickier to debug, than these two cases, so let's rule them out first.
Yes, that's what it does... Although keep in mind that it may take longer than the delay to execute. This method basically sets up an NSTimer in the current thread's run loop, so if your thread gets busy doing heavy duty work and the run loop takes longer than your delay to come back, your method will get executed later.

How many Objective-C messages per second are possible on the iPhone 4?

When implementing algorithms and other things while trying to maintain reusability and separation patterns, I regularly get stuck in situations like this:
I communicate back and forth with an delegate while traversing a big graph of objects. My concern is how much all this messaging hurts, or how much I must care about Objective-C messaging overhead.
The alternative is to not separate anything and always put the individual code right into the algorithm like for example this graph traverser. But this would be nasty to maintain later and is not reusable.
So: Just to get an idea of how bad it really is: How many Objective-C messages can be sent in one second, on an iPhone 4?
Sure I could write a test but I don't want to get it biased by making every message increment a variable.
There's not really a constant number to be had. What if the phone is checking email in the background, or you have a background thread doing IO work?
The approach to take with things like this is, just do the simple thing first. Call delegates as you would, and see if performance is OK.
If it's not, then figure out how to improve things. If messaging is the overhead you could replace it with a plan C function call.
Taking the question implicitly to be "at what point do you sacrifice good design patterns for speed?", I'll add that you can eliminate many of the Objective-C costs while keeping most of the benefits of good design.
Objective-C's dynamic dispatch consults a table of some sort to map Objective-C selectors to the C-level implementations of those methods. It then performs the C function call, or drops back onto one of the backup mechanisms (eg, forwarding targets) and/or ends up throwing an exception if no such call exists. In situations where you've effectively got:
int c = 1000000;
while(c--)
{
[delegate something]; // one dynamic dispatch per loop iteration
}
(which is ridiculously artificial, but you get the point), you can instead perform:
int c = 1000000;
IMP methodToCall = [delegate methodForSelector:#selector(something)];
while(c--)
{
methodToCall(delegate, #selector(something));
// one C function call per loop iteration, and
// delegate probably doesn't know the difference
}
What you've done there is taken the dynamic part of the dispatch — the C function lookup — outside the inner loop. So you've lost many dynamic benefits. 'delegate' can't method swizzle during the loop, with the side effect that you've potentially broken key-value observing, and all of the backup mechanisms won't work. But what you've managed to do is pull the dynamic stuff out of the loop.
Since it's ugly and defeats many of the Objective-C mechanisms, I'd consider this bad practice in the general case. The main place I'd recommend it is when you have a tightly constrained class or set of classes hidden somewhere behind the facade pattern (so, you know in advance exactly who will communicate with whom and under what circumstances) and you're able to prove definitively that dynamic dispatch is costing you significantly.
For full details of the inner workings at the C level, see the Objective-C Runtime Reference. You can then cross-check that against the NSObject class reference to see where convenience methods are provided for getting some bits of information (such as the IMP I use in the example).

Asking if an object is invalid

I am trying to determine if an object is valid. The program has (at least) two threads and one of the threads might invalidate the object by removing it from an NSMutableArray. I need the other thread to check either its existence or validity before acting on it.
You can't. The only way to check if the memory your object pointer has still represents a valid object is to dereference it, but dereferencing an "invalid" object (by which I assume you mean one that has been dealloced) will result in either accessing the memory of a new object that has been allocated in the same location, garbage data that may or may not be identical to a normal object, or an unmapped memory page that will result in an immediate EXEC_BAD_ACCESS.
Any time you are holding a reference to an object you might use in the future you must retain it. If you don't you have not shown any interest or ownership in the object and the system may throw it away at any time.
Using objective C accessors and properties instead of directly setting ivars and using retain/release simplifies doing the right thing quite a bit.
Multi-threaded programming is hard. Hard does not begin to capture how difficult it is. This is the kind of hard in which a general, useable, 'reasonably qualified' way of deterministically adding two different numbers together that are being mutated and shared by multiple threads in bounded time without the use of any special assistance from the CPU in the form of atomic instructions would be a major breakthrough and the thesis of your PhD. A deity of your choice would publicly thank you for your contribution to humanity. Just for adding two numbers together. Actually, multi-threaded programming is even harder than that.
Take a look at: Technical Note TN2059
Using collection classes safely with multithreaded applications. It covers this topic in general, and outlines some of the non-obvious pitfalls that await you.
You say
I need the other thread to check either its existence or validity before acting on it.
The easiest way is to hold on to the index of the object in the NSMutableArray and then do the following
if( myObject == [myArray objectAtIndex: myObjectIndex] ) {
// everything is good !
}
else {
// my object is not what I think it is anymore
}
There are clear problem with this approach however
insertion, and deletion will stuff you up
The approach is not thread safe since the array can be changed while you are reading it
I really recomend using a different way to share this array between the two threads. Does it have to be mutable? If it doesn't then make it immutable and then you no longer have to worry about the threading issues.
If it does, then you really have to reconsider your approach. Hopefully someone can give an cocoa way of doing this in a thread safe way as I don't have the experience.