How do you prevent access to a mutually accessible variable? - objective-c

I have a function that accepts an integer pointer as an argument, which it then alters. I have several instances of the function running on separate threads - some that have the same integer as the argument.
I need to pause the instance of the function if the argument is being altered by another instance of the function on another thread and resume when the other instance has completed altering the variable.
The seemingly obvious solution that to this kind of problem would be an NSLock or a POSIX mutex, however this would prevent all instances of the function from continuing, even if the integer argument is different.
For a more intuitive idea of what I mean consider the following:
void theFunction (int *argument)
{
NSLock *theLock = [NSLock new];
[theLock lock];
(*argument) ++;
[theLock unlock];
}
The above code would prevent all instances of the function from running, however I only need to pause the instances of the function where the integer argument is the same. How can I lock the variable specifically, as to pause any instances attempting to read or write to it until it is unlocked?

If you have the int*, consider using the atomic increment operation (see man on OSAtomicAdd32). It's pretty cheap to per-value locking that you want.

Use a separate lock for each argument?

Related

objective-c How to prevent an action while a thread is being executed

I've been using Multithreading for a while I thought I got it but my program is crashing now.
I have a method that has to download data for the server and access memory depending on the data, that process takes long, so I execute it from a secondary thread like this:
-(void)showPeople{
dispatch_queue_t pintaOcupantes = dispatch_queue_create("Pinta Ocupantes", NULL);
dispatch_async(pintaOcupantes, ^{
//BUNCH OF CODE
[self isPersonIn:jid];
//MORE CODE that include methods calling isPersonIn
});
Inside that block there's isPersonIn. It crashes if I press too fast the button that executes showPeople. IsPersonIn is something like:
-(int)isPersonIn:(XMPPJID *)jid{
int i = 0;
for(NSDictionary *card in self.listaGente){
NSLog(#"la jid es: %#", [card objectForKey:#"jid"]);
NSLog(#"la jid del usuario es: %#", jid.user);
if([[card objectForKey:#"jid"] isEqualToString:jid.user]){
return i;
}
i++;
}
return -1;
}
It compares a XMPPJID with an array which is a instance variable.
isPersonIn is called several times from different methods but all the methods that call it belong to the block, so as I understand it, all the executions of isPersonIn should be serialized, FIFO, right?
But if I press the button that executes showPeople, the one containing the block, many times very fast the app crashes on isPersonIn, sometimes without any message. I can see the threads when it crashes and I see at least 2 threads with isPersonIn last in the stack, which doesn`t make sense, since the block should be executed one at a time, not several threads at the same time, right?
Any help will be very much appreaciated.
Thanks!
[EDIT]
Also the instance array, self.listaGente, is modified outside the block.
I'm not a GCD expert, but I suspect the reason you're getting multiple threads is that you're creating a new dispatch queue each time showPeople is called.
So rather than having a single serial queue with multiple blocks, I think you are ending up with multiple queues each executing a single block.
[EDIT] If the collection is modified outside of the block but during execution of the block, this could be the source of your crash. From Fast Enumeration Documentation:
Enumeration is “safe”—the enumerator has a mutation guard so that if you attempt to modify the collection during enumeration, an exception is raised.
In this case protecting the array, that was provoking my app to crash, fixed the problem.
using:
#syncronized(theArray){
//CODE THAT WILL ACCESS OR WRITE IN THE ARRAY
}
This way threads will stop before if there's a thread already executing that code, like a mutex or semaphore

How to get hold of the currently executing NSOperation?

Is there an equivalent to [NSOperationQueue currentQueue] or [NSThread currentThread] for NSOperation?
I have a fairly complex domain model where the heavy processing happens quite deep down in the call stack. In order to timely cancel an operation I would need to pass the NSOperation as a parameter to every method until I get to the point where I want to interrupt a longer running loop. Using threads I could use [[NSThread currentThread] isCancelled] so it would seem convenient if there is an equivalent for NSOperation, unfortunately there is only the seemingly useless [NSOperationQueue currentQueue].
Came up with an extension in swift that returns the running operations
extension NSOperationQueue {
public var runningOperations: [NSOperation] {
return operations.filter {$0.executing && !$0.finished && !$0.cancelled}
}
}
You can then pick up the first one
if let operation = aQueue.runningOperations.first {}
No, there's no method to find the currently executing operation.
Two ways to solve your problem:
Operations are objects. If you need object A to talk to object B, you'll need to arrange for A to have a reference to B. There are lots of ways to do that. One way is to pass the operation along to each object that needs to know about it. Another is to use delegation. A third is to make the operation part of some larger "context" that's passed along to each method or function. If you find that you need to pass a reference from one object through several others just to get it to the object that will finally use it, that's a clue that you should think about rearranging your code.
Have the "heavy lifting" method return some value that gets passed up the call chain. You don't necessarily need the heavy lifting method to call [currentOperation cancel] to accomplish your goal. In fact, it would be better to have it return some value that the operation will understand to mean "work is done, stop now" because it can check that return value and exit immediately rather than having to call -isCancelled once in a while to find out whether it has been cancelled.
This isn't a good idea. Operations are usually canceled by their queue. Within the operation's main() method, you can periodically check if self is cancelled (say, every n trips through a loop, or at the start of every major block of commands) and abort if so.
To respond to a cancellation (say, some UI element tied to the operation's or queue's status), you use key value observing (KVO) to have your controller observe the operations' started, completion, and cancelled properties (as needed), then set your UI's state (always on the main thread) when those keys are updated. Per JeremyP's comments, it's important to note the KVO notifications come from the op's thread and UI should (almost) always be manipulated on the main thread, so you'll need to use -performSelectorOnMainThread... methods to update your actual UI when you receive a state change KVO note about your operations.
What are you really trying to do? That is, why do you feel other parts of your app need to know directly about the current operation?
You could store the current operation in the thread dictionary. Just remember to get rid of it before you exit. You can safely use the thread dict if you created the object.
You can use a combination of [NSOperationQueue currentQueue] & [NSThread currentThread] to accomplish this.
Essentially, you need to loop through the operations on the currentQueue and find the operation running on the currentThread.
NSOperation doesn't provide access to the thread it is running on, so you need to add that property yourself and assign it.
You're probably already subclassing NSOperation and providing a main, so add a 'thread' property to that subclass:
#interface MyOperation : NSOperation
#property(nonatomic,strong) NSThread *thread ;
#end
Then, in your 'main' assign the current thread to that property
myOperation.thread = [NSThread currentThread]
You can then add a 'currentOperation' method:
+(MyOperation *)currentOperation
{
NSOperationQueue *opQueue = [NSOperationQueue currentQueue] ;
NSThread *currentThread = [NSThread currentThread] ;
for( MyOperation *op in opQueue.operations ) {
if( [op isExecuting] && [op respondsToSelector:#selector(thread)] ) {
if( op.thread == currentThread ) {
return ( op ) ;
}
}
}
}
return nil ;
}
How do you know which operation you want to cancel?
When you get to the point that you want to cancel, just call [myQueue operations] and go through the operations until you find ones that you now want to cancel. I guess if you have millions of operations (or thousands) this might not work.
[myQueue operations] is thread safe - a snapshot of the Queue contents. You can dive through it pretty quick cancelling at will.
Another way:
NSOperationQueue is not a singleton, so you can create a Q that has say 200 jobs on it, and then cancel all 20 by just getting that Q and cancelling them all. Store the Q's in a dictionary on the main thread, and then you can get the jobs you want canceled from the dict and cancel them all. i.e. you have 1000 kinds of operations and at the point in the code where you realize you don't need a certain task, you just get the Q for that kind, and look through it for jobs to cancel.

Two threads call one function > Does local variable access need to be synchronized?

If two threads call one function "simultaneously,"
do variables local to the function (not ivars) need to be protected in a mutex/synchronization block to keep other threads from altering/munging them?
Or, does each thread get its own copy of the local variables on the stack, like a recursive call would/should?
Use the extremely fake and pointless function below as an example of what I'm not sure is thread-safe:
- (TicketResponseObj *)createTicketResponse:(NSHTTPURLResponse *)httpResponse {
//local variable declaration and assignment
NSInteger localVar_RespCode = [httpResponse statusCode];
//local object ptr declaration, obj allocation, and ptr assignment
TicketResponseObj *localObj_TicketResponse = [[TicketResponseObj alloc] initWithCode:localVar_RespCode];
//return ptr to instance of local object
return localObj_TicketResponse;
}
Please assume that TicketResponseObj's initWithCode is threadsafe. I'm using LLVM-GCC 4.2 as my compiler, and I'm targeting the armv7 architecture.
(This example function could easily be static too, if that matters?)
Sorry, I know this is potentially a stupid question, but my friend suggested the answer depends entirely on the compiler/architecture, etc.
Thanks for your help and patience!
No, they do not need to be synchronized. Local variables and variable references exist on the stack, and as such each thread maintains its own stack. The runtime already takes care of allowing concurrent access to the heap allocator, for cases of alloc and new.
Each thread gets its own copy of the local variables on the stack, like a recursive call would.

How do I determine if a thread has a lock?

I am writing an Objective-C class that I want to be thread safe. To do this I am using pthreads and a pthread_rwlock (using #synchronized is overkill and I want to learn a bit more about pthreads). The lock is inited in the objects designated init method and destroyed in dealloc. I have three methods for manipulating the lock; readLock, writeLock, unlock. These three methods simply invoke the related pthread functions and currently nothing else.
Here are two of the objects methods, both of which require a writeLock:
-(void)addValue:(const void *)buffer
{
[self writeLock];
NSUInteger lastIndex = self.lastIndex;
[self setValue:buffer atIndex:(lastIndex == NSNotFound) ? 0 : lastIndex+1];
[self unlock];
}
-(void)setValue:(const void *)buffer atIndex:(NSUInteger)index
{
[self writeLock];
//do work here
[self unlock];
}
Invoking setAddValue: will first obtain a write lock and then invoke setValue:atIndex: which will also attempt to obtain a write lock. The documentation states that the behaviour is undefined when this occurs. Therefore, how do I check if a thread has a lock before attempting to obtain a lock?
(I could ensure that critical section make no invocation that trigger another lock request, but that would mean code repetition and I want to keep my code DRY).
Not entirely clear what kind of lock you're using. You indicate you're using pthreads, and read/write lock, so I'm concluding that you're using a pthread_rwlock.
If that's true, then you should be able to use pthread_rwlock_trywrlock on the lock. From the man page,
If successful, the pthread_rwlock_wrlock() and pthread_rwlock_trywrlock()
functions will return zero. Otherwise, an error number will be returned
to indicate the error.
And, one of the errors is:
[EDEADLK] The calling thread already owns the read/write lock
(for reading or writing).
Therefore, I believe you should be able to call pthread_rwlock_trywrlock() and you will either be successful, it will return EBUSY if another thread has the lock, or you will get EDEADLK if the current thread has the lock.
First, a critical section containing only one operation is useless. The point is to synchronize different things relative to each other. (You do effectively make the integer atomic, but that is probably not the full intent.)
Second, you already know you have the write lock inside the latter critical section, so there is no need to check that it exists or not. Simply do not attempt a read lock while writing.
The solution is probably to move the readLock and writeLock calls up into the calling functions, but without knowing more it's impossible to say.
(This will also likely reduce the performance cost of locking by reducing the number of total operations, as you will not be locking and then immediately unlocking. Probably you do not need to work directly at the pthreads level.)
A portable program cannot rely on the implementation to tell the caller it already holds the write lock. Instead, you need to do something like this to wrap rwlocks with a recursive write lock:
int wrlock_wrap(pthread_rwlock_t *l, int *cnt)
{
int r = *cnt ? 0 : pthread_rwlock_wrlocK(l);
if (!r) ++*cnt;
return r;
}
int wrunlock_wrap(pthread_rwlock_t *l, int *cnt)
{
--*cnt;
return pthread_rwlock_unlock(l);
}
You can keep the count beside the pthread_rwlock_t wherever it's stored, e.g. as a member of your struct/class/whatever.

How can I make sure an object has finished initialising before using it?

Writing some Objective-C in one method, I call +alloc, then -init to set up an object.
object = [[MyClass alloc] init];
[object useFor:whatever];
The next few lines of code use the newly created object. If the aforementioned -init takes too long, I’m sure the program won’t “wait” before starting to use the new object, will it? If not, is there a quick way to assure the -init is completed?
I sometimes see programmers who write something along the lines of
if(object = [[MyClass alloc] init]) {
[object useFor:whatever];
}
Is this what I should go for?
When you call init the program will not go on to the next line until the init method returns. By the time you've reached the second line, the init method has completed. It may not have completed successfully, but it will have completed.
The second form is a test. First the if statement calls the init method. If a valid object is returned then the test is true and then the next statement is executed. This is why you see init methods that return self when they are successful and nil when there is a problem; so that tests like these can be run to be sure that the object has been successfully initialised before continuing.
commands are executed in sequential order and not paralell
(dude, learn some basics ;)
As a rule, statements in C and Objective-C functions (and methods) are executed in sequence, in the order you write them. If you write one thing before another in a function, the first one must complete execution before the next one can execute.
The compiler may reorder statements if it believes that doing so will not change the behavior of the program (which it can predict very well in situations that don't involve concurrency), but this is an optimization. The C standard treats statements as being sequential, but allows compilers to implement this any way they like as long as the behavior of the actual program is the same as if the statements had been executed in the sequence in which they were written.
All this is a long way of saying: Your init method will complete before the calling method can resume execution.