Starting and stopping operations in a thread-safe manner - objective-c

I have a simple class that looks a bit like this:
#protocol Recorder
#property(BOOL) isRunning;
- (void) start;
- (void) stop;
#end
And the method implementations:
- (void) start {
if (running)
return;
…
running = YES;
}
- (void) stop {
if (!running)
return;
…
running = NO;
}
And I started thinking about thread safety. The current solution is not thread safe, right? How about this:
- (void) start {
#synchronized(self) {
if (running)
return;
…
running = YES;
}
}
Is this correct, provided that the -stop method is also synchronized? I don’t like the extra nesting introduced by #synchronized, though. Would explicit lock work?
- (void) stop {
[startStopLock lock];
if (running)
return;
…
running = YES;
[startStopLock unlock];
}
Or could I do even this?
enum { Running, Stopped };
NSConditionLock *startStopLock;
- (void) start {
if (![startStopLock tryLockWithCondition:Stopped])
return;
…
[startStopLock unlockWithCondition:Running];
}
Is this solution correct? Would you do things differently?

What language is this? You are correct, the first version is not thread safe.
The synchronized version is thread safe. With an explicit lock you need to be careful not to miss the unlock on the early return path.
If you have access to locked xchg intrinsics, you can do it fairly easily with an atomic exchange operation. cmpxchg also works.
start() {
if (locked_xchg(running, YES) == YES) {
// the old value was YES, so nothing to do
return
}

Related

#synchronized - skip instead of wait

I've got an Objective-c app with several blocks of code where I only want one thread to be able to access it at a time. Using a #synchronized(self) block works fine for that.
However, I've got one block where I want it to skip the block, if another thread is in one of the #synchronized blocks, rather than wait. Is there a way to simply test if self (or whatever my lock object is) is being held by another synchronized block?
// block 1 - wait until lock is available
#synchronized(self) {
...
}
...
// block 2 - wait until lock is available
#synchronized(self) {
...
}
...
// block 3 - wait until lock is available
#synchronized(self) {
...
}
...
// block 4 - skip if lock is not immediately available - no waiting!
howDoISkipIfLockIsNotAvailable(self) {
...
}
What you want to achieve is possible when using NSLock or NSRecursiveLock instead of the #synchronized syntax sugar. They key feature it offers is the tryLock method:
NSRecursiveLock *lock = [[NSRecursiveLock alloc] init];
[lock lock];
#try {
// ... do synchronized stuff
}
#finally {
[lock unlock];
}
if ([lock tryLock]) {
#try {
// do synchronized stuff if possible
}
#finally {
[lock unlock];
}
}

NSThread Not Loading Selector Method

In the initialization method of a class I am declaring the thread as such:
NSThread* myThread = [[[NSThread alloc] initWithTarget:self selector:#selector(m_run_thread) object:nil] autorelease];
[myThread start];
I also have a boolean value which is set to NO. Later on in the code I set the boolean value to YES.
bool_run_progress_thread = YES;
The contents of the method m_run_thread is as follows:
-(void) m_run_thread
{
if (bool_run_progress_thread)
{
//do processing here
}
bool_run_progress_thread = NO;
}
The problem is that the method m_run_thread is never being accessed. What am I doing wrong?
P.S. I have also tried to set up the Thread using the following (and older)method:
[NSThread detachNewThreadSelector:#selector(m_run_thread)
toTarget:self
withObject:nil];
... but to no avail as well.
"...and I am only getting it to show once" Yes, that's exactly how it should be. After being started, a thread runs once from its start to its end (ignoring errors here for the moment), and having reached the end, the thread is essentially dead and gone.
If you want the thread to repeat its execution, you have to prepare for that yourself:
- (void) m_run_thread
{
for (;;)
{
if (bool_run_progress_thread)
{
//do processing here
bool_run_progress_thread = NO;
}
}
}
But there is still a lot wrong with this code: essentially, when run, the code forms a busy waiting loop. Assuming, that bool_run_progress_thread is only ever true for short periods of time, the background thread should be sleeping most of the time. Insead, if you try the code as its stands, it will instead consume CPU time (and lots of it).
A better approach to this would involve condition variables:
#class Whatsoever
{
NSCondition* cvar;
BOOL doProgress;
...
}
...
#end
and
- (void) m_run_thread
{
for (;;)
{
[cvar lock];
while (!doProgress)
{
[cvar wait];
}
doProgress = NO;
[cvar unlock];
... do work here ...
}
}
and in order to trigger the execution, you'd do:
- (void) startProgress
{
[cvar lock];
doProgress = YES;
[cvar signal];
[cvar unlock];
}
Doing things this way also takes care of another subtle problem: the visibility of the changes made to the global flag (your bool_run_progress_thread, my doProgess). Depending on the processor and its memory order, changes made without special protection might or might not become (ever) visible to other threads. This problem is taken care of by the NSCondition, too.

Synchronizing a Block within a Block?

I'm playing around with blocks in Objective-C, trying to come up with a reusable mechanism that will take an arbitrary block of code and a lock object and then execute the block of code on a new thread, synchronized on the provided lock. The idea is to come up with a simple way to move all synchronization overhead/waiting off of the main thread so that an app's UI will always be responsive.
The code I've come up with is pretty straightforward, it goes like:
- (void) executeBlock: (void (^)(void))block {
block();
}
- (void) runAsyncBlock: (void (^)(void))block withLock:(id)lock {
void(^syncBlock)() = ^{
#synchronized(lock) {
block();
}
};
[self performSelectorInBackground:#selector(executeBlock:) withObject:syncBlock];
}
So for example, you might have some methods that go like:
- (void) addObjectToSharedArray:(id) theObj {
#synchronized(array) {
[array addObject: theObj];
}
}
- (void) removeObjectFromSharedArray:(id) theObj {
#synchronized(array) {
[array removeObject: theObj];
}
}
Which works fine, but blocks the calling thread while waiting for the lock. These could be rewritten as:
- (void) addObjectToSharedArray:(id) theObj {
[self runAsyncBlock:^{
[array addObject: theObj];
} withLock: array];
}
- (void) removeObjectFromSharedArray:(id) theObj {
[self runAsyncBlock: ^{
[array removeObject: theObj];
} withLock:array];
}
Which should always return immediately, since only the background threads will compete over the lock.
The problem is, this code crashes after executeBlock: without producing any output, error message, crash log, or any other useful thing. Is there something fundamentally flawed in my approach? If not, any suggestions with respect to why this might be crashing?
Edit:
Interestingly, it works without crashing if I simply do:
- (void) runAsyncBlock: (void (^)(void))block withLock:(id)lock {
void(^syncBlock)() = ^{
#synchronized(lock) {
block();
}
};
syncBlock();
}
But of course this will block the calling thread, which largely defeats the purpose. Is it possible that blocks do not cross thread boundaries? I would think not, since that would largely defeat the purpose of having them in the first place.
remember to call [block copy] otherwise it is not correctly retained because block are created on stack and destroyed when exit scope and unless you call copy it will not move to heap even retain is called.
- (void) runAsyncBlock: (void (^)(void))block withLock:(id)lock {
block = [[block copy] autorelease];
void(^syncBlock)() = ^{
#synchronized(lock) {
block();
}
};
syncBlock = [[syncBlock copy] autorelease];
[self performSelectorInBackground:#selector(executeBlock:) withObject:syncBlock];
}

Cocoa way of doing applications with delegates

i have a method, in which i want to accomplish a given task, however, the asynchronous commands and delegates made it difficult
i can do this :
- (void) fooPart1
{
...
SomeAssynchronousMethos * assync = [[SomeAssynchronousMethos alloc] init];
assync.delegate = self;
[assync start];
}
- (void) fooPart2
{
...
possibly some other assync
}
- (void)someAssynchronousMethosDelegateDidiFinish
{
[self fooPart2];
}
But isn't there a way to do smith. like this
- (void) foo
{
...
SomeAssynchronousMethos * assync = [[SomeAssynchronousMethos alloc] init];
assync.delegate = self;
[assync start];
wait for signal, but class is not blocked
...
possibly some other assync
}
- (void)someAssynchronousMethosDelegateDidiFinish
{
continue in foo after [assync start]
}
I don't like the idea of splitting a function to 2 or more parts, but is this the way how it is done in cocoa? or is there a better practice?
why i dont like this concept and searching for a better way of doing it :
lets say, i want to use a variable only for compleating a task - if i have everything in one function, i just use it, and than the var dies as i leave the function, if its split, i have to keep the var somehow around, until it doesnt finish
the code becomes fragmented and more difficult to read and maintain
may lead to bug
i end up with a set of part function, that needs to be called in precise order to accomplish one task (for which one function would be more suitable)
i used to make a thread and do only synchronous calls there, but not everything supports a synchronous call
what would be realy nice, is to have smth, like
- (void) foo
{
...
int smth = 5;
SomeAssynchronousMethos * assync = [[SomeAssynchronousMethos alloc] init];
assync.delegate = self;
#freez([assync start]);
// when freez - the local function variables are frozen
// (next commands in function are not excuted until unfreez)
// from outer look, it looks like the function finished
// however when unfreeze, it is called from this point on
//int smth is still 5
}
- (void)someAssynchronousMethosDelegateDidiFinish
{
#unfreez([assync start]);
}
when the execution would reach freez, it would store all local vars allocated in function and when called unfreez, it would continue from that point on, when it was freez with that command
This seems like an ideal application of a completion handler block.
Alter your start method to take a parameter which is a block and call it like so:
- (void) fooPart1
{
...
SomeAssynchronousMethos * assync = [[SomeAssynchronousMethos alloc] init];
[assync startOnComplete: ^(NSError* error) // example, you can have any params or none
{
// handle error if not nil
if (error != nil)
{
// do something with it
}
// code to do on completion
}];
}
Your start method would look something like this
-(void) startOnComplete: (void(^)(NSError*)) completionBlock
{
// copy the block somewhere
theSavedCompletionBlock = [completionBlock copy];
// kick off async operation
}
-(void) someMethodThatRunsAttheEndOfTheAsyncOp
{
theSavedCompletionBlock(nilOrError);
[theSavedCompletionBlock release];
}

Objective-C / Cocoa equivalent of C# ManualResetEvent

Is there an equivalent of the .NET ManualResetEvent class available for use in Objective-C / Cocoa?
I'm not very familiar with ManualResetEvent, but based on the documentation, it looks like the NSCondition class might be what you are looking for.
NSCondition is by no means an exact equivalent, but it does provide similar signaling functionality. You might also want to read up on NSLock.
Here is a wrapper class I created which emulates ManualResetEvent using NSCondition.
#interface WaitEvent : NSObject {
NSCondition *_condition;
bool _signaled;
}
- (id)initSignaled:(BOOL)signaled;
- (void)waitForSignal;
- (void)signal;
#end
#implementation WaitEvent
- (id)initSignaled:(BOOL)signaled
{
if (self = ([super init])) {
_condition = [[NSCondition alloc] init];
_signaled = signaled;
}
return self;
}
- (void)waitForSignal
{
[_condition lock];
while (!_signaled) {
[_condition wait];
}
[_condition unlock];
}
- (void)signal
{
[_condition lock];
_signaled = YES;
[_condition signal];
[_condition unlock];
}
#end
I've done just some basic testing but I think it should get the job done with much less ceremony.
I'll give you the sample code I would have liked to find yesterday (but couldn't find anywhere). If you want to create a producer/consumer class where the consumer is asynchronous, this is what you need to do :
You need to declare and allocate the NSConditionLock.
NSArray * data = [self getSomeData];
if ( [data count] == 0 ) {
NSLog(#"sendThread: Waiting...");
[_conditionLock lockWhenCondition:1];
[_conditionLock unlockWithCondition:0];
NSLog(#"sendThread: Back to life...");
}
else {
// Processing
}
And in the main code, when you add data and you want to unlock the other thread, you just have to add :
[_conditionLock lock];
[_conditionLock unlockWithCondition:1];
Note: I don't describe here how data are exchanged between the producer and the consumer. In my program it was going through an SQLite/CoreData database, so thread sync is done at a higher level. But if you use a NSMutableDictionary, you need to add some NSLock.
Ah, those are poor man's condition variables.
You could use the NSCondition class, but I think it's better
to go straight to the source. Start with pthread_cond_init.
You gonna love it.