I've a TableViewController that uses the item at index N for the table view cell at row N. Since array index N may be accessed from different threads, I created a ThreadSafeMutableArray class that does the reads inside a dispatch_sync and writes under a dispatch_barrier_async.
Suppose I get the object at index N, say using Song *currSong = self.entries[N];, and then make changes to the properties of this object. Am I correct in understanding that I need to make these changes in a thread-safe way (because for e.g, tableview may ask for the object at cell N and at the same time the object in cell N may be updated because the image object for which it was received from the network)? If yes, what is the simplest way to make my custom class thread-safe?
For example : In the ThreadSafeMutableArray case, I was able to achieve it by over-riding following methods and using dispatch_sync and dispatch_barrier_async within the new implementation of the methods.
-(NSUInteger) count
-(id) objectAtIndex:(NSUInteger)index;
-(void) insertObject:(id)anObject atIndex:(NSUInteger)index;
-(void) removeObjectAtIndex:(NSUInteger)index;
-(void) addObject:(id)anObject;
-(void) removeLastObject;
-(void) replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
You need to determine what "thread safe" means in the context of your custom class/application. You might just want data integrity, meaning that no thread sees an invalid or partial stored value, e.g. Think of atomic read/write operations; or you might required model integrity, e.g. where the interrelationships of multiple items is always correct - as in your mutable array; or something between these, e.g. think of counter incrementing - it is not as involved as keeping the graph of objects representing a mutable structure consistent, but more involved than simple atomic read or write. Etc., etc., thread safety is a big topic!
Once you know what your custom object requires you can select from atomic properties for simple read/write integrity, locks for more complex combinations, combinations of GCD sync, async, barrier, sequential and concurrent queues etc.
In short there is no single simple answer. Study the various options, consider your requirements, and pick and choose. You are already using GCD to achieve thread safety, that is good! If you come up with a design and have issues with it you can always ask SO.
You might find this article interesting on the benefits, or otherwise, of atomic properties. The writer is probably being a bit harsh on atomic to make a point, but it is certainly worth a read.
HTH
The easiest way to achieve this is to create a singel access mehtod in your TableViewController and use the #syncrhonized directive to protect access.
- (void)updateObjectAt:(NSUInteger)index {
#synchronized(itemArray) {
// Everything between the braces is protected by the #synchronized directive.
itemArray[index].update();
}
}
The #synchornized directive puts a lock on the array, anything within the code block can safely access and change items in the array. If any other methods need to access the array simply wrap it in a #syncrhonized lock on the array aswell.
Related
My company finishing up a new game engine which (like most engines) is very CPU intensive. It is written in Objective-C and most of the core game items which get accessed frequently are stored in object properties. Most of these are automatically synthesized and are simply stored and read.
How much speed, if any, would we gain by changing properties in the core game engine items to be public instance variables?
So whereas it would be declared and accessed like this with a property
#property (nonatomic) CMLocation location;
node.location.x;
It would now be:
#public:
CMLocation location
node->location->x
Logically speaking, I think ivars would be much faster as it should be an almost single clock tick operation (assuming no cache miss), but perhaps the compiler tunes that sort of thing out now and synthesized properties are just as fast.
Can't answer in numbers, but try to describe mechanics "under the hood"
When we access property via node->location->x - it the fastest way, just address lookup in memory, pure c-style.
When we access via node.location.x, obj-c calls getter method for the property, and it's not just classic function call - obj-c performs objc_msgSend( node, #selector( location)), which performs selector look-up by string name. You can find pretty clear description of this process here: https://www.mulle-kybernetik.com/artikel/Optimization/opti-3.html
So, if your code is executed pretty often and it's a bottleneck for performance - yes, you should rewrite it to c-style. Also, keep in mind that struct properties are accessed directly, and when rewriting pay attention to safety - you don't have nil check anymore.
P.S. You can measure performance to find bottlenecks with Instruments and optimize just important code blocks - it's wise approach for optimization.
If a NSMutableArray is synchronized by the #synchronized, What about the elements in the array? are they also synchronized?
For example, I lock the array by the #synchronized (array) to get an element in that array, Can I ensure that the element I've got won't be changed (like changes on the value of some properties of the element) by other thread during my access of it?
Or besides locking the array, I have to lock the element again to prevent others to change the properties of the element?
Thanks
It'd be a lot better to think that locking is the means of protecting code executions, not protecting shared data.
#synchronized (mutable array) {} block doesn't protect any data, it just ensure the same block is not executed simultaneously by multiple threads. Putting a mutable array object inside of parenthesis usually denote 'scope of lock'. That is, saying "this lock object is only associated with this object".
So, most easiest and safest way to using #synchronized is #synchronized (self). And in this case, it is telling clearly, "this class is only accessed by a single thread at a time".
If a NSMutableArray is synchronized by the #synchronized, What about the elements in the array? are they also synchronized?
A: NO
No, it will only affect top-level dictionary access, provided all other code paths follow the same convention of locking the array.
In order to again exclusive access to an element in the array, you'll need to lock it explicitly, and again, all other code paths need to follow this protocol.
These two questions are quite common when we search it but yet I need to get a satisfying answer about both.When ever we search a difference between say subclass and a category we actually get definition of both not the difference.I went to an interview to a very good MNC working on iOS and I was encountered with these two questions and I gave almost all the answers I have read here but the interviewer was not satisfied.He stuck to his questions and was that-
Why do we needed category when we can use a subclass?
Why we needed blocks when we can use functions?
So please explain me what specific qualities blocks and category add in objective C that their counter part can't do.
First...
Just reading the documentation "Subclassing Notes" for NSString shows why creating categories is sometimes better than subclassing.
If you wanted to add a function -(void)reverseString (for instance) to NSString then subclassing it is going to be a massive pain in comparison to categories.
Second...
Blocks are useful for capturing scope and context. They can also be passed around. So you can pass a block into an asynchronous call which then may be passed elsewhere. TBH you don't care where the block is passed or where it is finally called from. The scope captured at the time of creating the block is captured too.
Yes, you can use methods too. But they both have different uses.
Your questions are a bit odd. It's like asking...
Why do hammers exist when we can just use wrenches?
You can't use subclassing when someone else is creating the objects. For instance, NSString is returned from hundreds of system APIs, and you can't change them to return MyImprovedString.
Functions split up the logic; blocks allow you to write it closer together. Like:
[thing doSomethingAndWhenFinishedDo: ^{ some_other_thing; }];
the same code written with functions would put the second part of the logic several lines away in the file. If you have a few nested scopes in your logic then blocks can really clean it up.
Why do we needed category when we can use a subclass?
Categories let you expand the API of existing classes without changing their type. Subclassing does the same thing but introduces a new type. Additionally subclassing lets you add state.
Why we needed blocks when we can use functions?
Block objects are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain variable bindings to automatic (stack) or managed (heap) memory. A block can therefore maintain a set of state (data) that it can use to impact behavior when executed.
You can use blocks to compose function expressions that can be passed to API, optionally stored, and used by multiple threads. Blocks are particularly useful as a callback because the block carries both the code to be executed on callback and the data needed during that execution
Category : It is used if we want to add any method on a given class whose source is not known. This is basically used when we want to alter the behaviour of any Class.
For example : If we want to add a method on NSString to reverse a string we can go for categories.
Subclassing : If we want to modify state as well as behaviour of any class or override any methods to alter the behaviour of the parent class then we go for subclassing.
For example : We subclass UIView to alter its state and behaviour in our iOS code.
Reference :
When to use categories and when to use subclassing?
What is the difference between inheritance and Categories in Objective-C
We need new method but we don't need new class so we need category.
We need function but we don't need named function so we need block.
I have a sessions property, a mutable set. I need to iterate over the collection, but at the same time I could change the collection in another method:
- (Session*) sessionWithID: (NSString*) sessionID
{
for (Session *candidate in _sessions) {
/* do something */
}
return nil;
}
- (void) doSomethingElse
{
[_sessions removeObject:…];
}
This isn’t thread-safe. A bullet-proof version would be using #synchronized or a dispatch queue to serialize the _sessions access. But how reasonable is to simply copy the set before iterating over it?
- (Session*) sessionWithID: (NSString*) sessionID
{
for (Session *candidate in [_sessions copy]) {
/* do something */
}
return nil;
}
I don’t care about the performance difference much.
But how reasonable is to simply copy the set before iterating over it?
As presented, it is not guaranteed to be thread safe. You would need to guarantee that _sessions is not mutated during -copy. Then iterating over an immutable copy is safe, and mutation of _sessions may occur on a secondary thread or in your implementation.
In many cases with Cocoa collections, you will find it is preferable to use immutable ivars and copy on set by declaring the property as copy of type NSSet. This way, you copy on write/set, and then avoid the copy on read. This has the potential to reduce copies, depending on how your program actually executes. Generally, this alone is not enough, and you will need some higher level of synchronization.
Also remember that the Sessions in the set may not be thread safe. Even once your collections accesses are properly guarded, you may need to protect access to those objects.
Your code does not look thread-safe to me because the collection might be mutated from another thread while it is copied.
You would have to protect [_sessions copy] and [_sessions removeObject:…] from
executing simultaneously.
After creating the copy, you can iterate over it without a lock (assuming that the collection elements themselves are not modified from another thread).
In one of my projects I have a background simulation that a GLView is drawn based on. In order to do the drawing in a background thread I need to copy the simulation's current frame data, then perform the drawing based on that data so that the simulation can continue in it's own thread and not distort the drawing data.
I see the copying of information to be used asynchronously as perfectly valid. Especially in devices that have multiple cores. #synchronize causes the separate threads to stop (if they are accessing the same information) and thereby can cause more of a performance loss than the copy procedure.
I'd like a critique of the following method I use to create objects:
In the interface file:
MyClass * _anObject;
...
#property (retain, nonatomic) MyClass * anObject;
In the implementation file:
#property anObject = _anObject
so far, so simple. Now let's override the default getter:
(MyClass *) anObject {
if(_anObject == nil) {
self.anObject = [[MyClass alloc] init];
[_anObject dowWhateverInitAction];
}
return _anObject;
}
EDIT:
My original question was about creating the object only (instead of the whole life-cycle), but I'm adding the following so that it doesn't through off anyone:
- (void) dealloc {
self.anObject = nil;
}
/EDIT
The main point of the exercise is that setter is used inside the getter. I've used it for all kind of objects (ViewController, myriad other types, etc.) The advantage I get is:
An object is created only when needed. It makes the app pretty fast
(for example, there are 6-7 views in an app, only one gets created in
the beginning).
I don't have to worry about creating an object before it's used... it happens automatically.
I don't have to worry about where the object will be needed the first time... I can just access the object as if it were already there and if it were not, it just gets created fresh.
Questions:
Does it happen to be an established pattern?
Do you see any drawbacks of doing this?
This pattern is quite commonly used as a lazy-loading technique, whereby the object is only created when first requested.
There could be a drawback to this approach if the object being created lazily takes a fair amount of computation to create, and is requested in a time-critical situation (in which case, it doesn't make sense to use this technique). However I would say that this is a reasonable enough thing to do should the object be quick to create.
The only thing wrong with your implementation (assuming you’re not using ARC yet) is that you’ve got a memory leak—using the setter means that your MyClass instance is getting over-retained. You should either release or autorelease _anObject after that initialization, or assign its value directly instead of calling the setter.
Aside from that, this is totally fine, and it’s a good pattern to follow when the MyClass is an object that isn’t necessarily needed right away and can be recreated easily: your response to memory warnings can include a self.anObject = nil to free up the instance’s memory.
It looks like a decent lazy initialization. Philosophically, one can argue that the drawback is that a getter has a side effect. But the side effect is not visible outside and it is kind of an established pattern.
Lazy instantiation is an established pattern, and it is used by Apple in their (terrible) Core Data templates.
The main drawback is that it is overly complex and often unnecessary. I've lost count of the number of times I've seen this where it would make more sense to simply instantiate the objects when the parent object is initialised.
If a simple solution is just as good, go with the simpler solution. Is there are particular reason why you can't instantiate these objects when the parent object is initialised? Perhaps the child objects take up a lot of memory and are only rarely accessed? Does it take a significant amount of time to create the object and you are initialising your parent object in a time-sensitive section of your application? Then feel free to use lazy instantiation. But for the most part, you should prefer the simpler approach.
It's also not thread-safe.
Regarding your advantages:
An object is created only when needed. It makes the app pretty fast (for example, there are 6-7 views in an app, only one gets created in the beginning).
Are you referring to views or view controllers? Your statement doesn't really make sense with views. I don't normally find myself needing to store view controllers in instance variables/properties at all, I instantiate them when I need to switch to them and push them onto the navigation stack, then pop them off when I'm done.
Have you tried your app without using this pattern? Conjecture about performance is often wrong.
I don't have to worry about creating an object before it's used... it happens automatically.
No, now you have to worry about writing a special getter instead. This is more complex and prone to mistakes than simple instantiation. It also makes your application logic and performance more difficult to understand and reason about.
I don't have to worry about where the object will be needed the first time... I can just access the object as if it were already there and if it were not, it just gets created fresh.
You don't have to worry about that when you instantiate it during your parent object's initialisation.
Yes this is an established pattern. I often use lazy instantiation like this as an alternative to cluttering up -init or -viewDidLoad with a bunch of setup code. I would assign the value to the instance variable instead of using the synthesized setter in the event that this object ends up being created as a result of something happening in -init.