objective C what should I do for making these function threadsafe? - objective-c

Here is the case.
I got a singleton class call DBManager with sqlite3. And insert,delete,select are done via this class.
suppose now ClassA need to insert a record to table a and ClassB need to select a record from table a. So the presudo code is like this.
Class A
[[DBManager getInstance] insertRecord:#"12345"];
Class B
-(void)processData{
Record r = [[DBManager getInstance] getRecord];
// working with record r. after that doing some layout update
[self.lbTitle setText:r.name];
}
cause in my project, there are 4-5 class will access the db. So sometime a Database is locked error is throw and my app crashed.
I know one of the solution is using GCD dispatch_async(CUSTOM_DB_QUEUE,block)
using these block for all the codes related to the db.
But if so, i need to also modify Class B like this. Am I right?
Class B
-(void)processData{
dispatch_async(CUSTOM_DB_QUEUE,{
[[DBManager getInstance] getRecord onRecordGot:^(Record* r) {
// working with record r. after that doing some layout update
dispatch_async(MAIN_QUEUE,{
[self.lbTitle setText:r.name];
)};
}];
)};
}
Is this approach correct?? so i need to change all my code in DBManager to return the result using block coding??
Is there any simple way for queue up the hold DBManager class??

There's a better approach. Do not make any changes to your code that calls DBManager. All changes should be made inside your DBManager class. And there is no reason to use dispatch_async. Use dispatch_sync.
This code stays the same:
Class A
[[DBManager getInstance] insertRecord:#"12345"];
Class B
-(void)processData{
Record r = [[DBManager getInstance] getRecord];
// working with record r. after that doing some layout update
[self.lbTitle setText:r.name];
}
In your insertRecord: method you change it to something like:
- (void)insertRecord:(NSString *)record {
dispatch__barrier_sync(CUSTOM_DB_QUEUE, ^{
// original code to insert record
};
}
And your getRecord method becomes:
- (Record *)getRecord {
__block Record *result = nil;
dispatch_sync(CUSTOM_DB_QUEUE, ^{
// original code that sets result
};
return result;
}
By using dispatch_sync and dispatch_barrier_sync, this code allows for any number of concurrent calls to getRecord but only one call to insertRecord. It also ensures calls to getRecord are blocked while insertRecord: is being run.

To make it thread safe, you can use pthread_mutex_t as a global instance. Lock/unlock this mutex according to its usage
e.g.
pthread_mutex_t *dbLock;
Class A
pthread_mutex_lock(dbLock);
[[DBManager getInstance] insertRecord:#"12345"];
pthread_mutex_unlock(dbLock);
Class B
-(void)processData{
pthread_mutex_lock(dbLock);
Record r = [[DBManager getInstance] getRecord];
// working with record r. after that doing some layout update
[self.lbTitle setText:r.name];
pthread_mutex_unlock(dbLock);
}

Related

State machine to handle sequential and async events

I created this state machine to handle events. I'm unsure about my implementation firstly because I don't use a transition table or anything like that, instead, I simply input the next event/state that needs to happen. I think this is cleaner than calling method to handle event b inside the method to handle event a, right?
Secondarily, since some of the methods have parameters - and this is not swift where enum members can have associated values, I added a param for that via withObj argument. I don't see a problem with this but want to know if this is confusing/violating something from your perspective.
I also found this useful for async task, so after the task completes I set resulting value to a local variable then update state to packData using that stored value amongst many other values already existing. This value is packed in a byte array which cannot be used in blocks so this was a useful workaround - although I haven't tested yet.
States are defined via enum like so:
typedef NS_ENUM(NSUInteger, ExampleState) {
ExampleStateIdle,
ExampleStateWaitingForAsyncTask,
ExampleStateReadyToPack,
ExampleStateRespond,
ExampleStateSomethingInProgress,
ExampleStateSomething2InProgress,
ExampleStateComplete
};
Here I define a method to handle each event using helper methods. I also have an extra argument for any state that might have an associated value.
- (void)updateState:(ExampleState)state withObj:(id)obj {
self.currentState = state;
switch (state) {
case ExampleStateWaitingForAsyncTask:
[self getAsyncInfo];
break;
case ExampleStateReadyToPack:
[self packData];
break;
case ExampleStateRespond:
[self respond:obj];
break;
case ExampleStateComplete:
[self showPopup];
break;
default:
break;
}
}
Example usage:
-(void)packData {
NSData *data = [NSData dataWithBytes:&result length:resultIndex];
// next step is to respond to `client`/`central` with data
[self updateState:ExampleStateRespond withObj:data];
}

NSManagedObject custom accessors / get

I have two objects, forms and customers. A job has forms a form can have child forms. What I'd like to do is, because the form relationship is recursive and only the top form has the relationship to the job, in my Form NSManagedObject I'd like to return the topmost 'parentForm.job' if self.job is nil.
import "Form.h"
import "Job.h"
#implementation Form
// Insert code here to add functionality to your managed object subclass
Usually in non managed objects I'd do
-(Job *)job
{
if (!_job && self.parentForm)
return self.parentForm.job;
return _job;
}
But alas no _properties due to being dynamic... Obviously I can't do this
-(Job *)job
{
if (!self.job && self.parentForm)
return self.parentForm.job;
return self.job;
}
How do I create an accessor for dynamic properties in this instance?
Thanks a bunch.
from Avi's comment
-(Job *)job
{
Job *job = [self primitiveValueForKey:#"job"];
if (!job && self.parentForm)
return self.parentForm.job;
return job;
}

How to Implement a Decision Table in Objective-C

I am a novice programmer, and I've just started reading about decision tables. I have read Chapter 18 in Code Complete and it was very enlightening. I looked around the web to try to find any kind of example of decision tables in Objective-C and I was unable to find any boilerplate or real world examples of how to implement this.
I am programming a game in Objective-C in my spare time, and I have been dealing with increasing complexity for the rules of the game. There are a handful of somewhat deeply nested if-else statements, as well as a few switch statements that already have 10 or more cases to deal with. I think it would be easier to work with decision tables, but I have no idea how to implement this in Objective-C for something non-trivial like the logic of a game.
For example, I need different methods to execute for different combinations of states. How would I implement a decision table in Objective-C that could take different combinations of states as keys, and run specific logic based on the combination of them?
Well I thought about decision tables in Objective-C some more and came up with a solution to implement a basic one. I will not post the entire code here, just the snippets that make the decision table work and their basic purpose. I posted this over at Code Review SE if you want to see the full code and some great suggestions for how to improve it. I'm posting this now because someone posted a comment requesting that I do so, but I will definitely end up improving this and integrating the suggestions from the review. Anyway, here is the code.
First before the initialization method I establish a number of NSString constants that will be used as the keys in an NSDictionary.
//Two options for the decision table, either access the dictionary directly with 0-x, the enum values, or make strings for their names
//the advantage of strings is that it is more extensible, and the position in the enum doesnt matter
NSString* const kEnemyMovementStateJustSpawned = #"enemyMovementStateJustSpawned";
NSString* const kEnemyMovementStateIdle = #"enemyMovementStateIdle";
NSString* const kEnemyMovementStateNeedsMoving = #"enemyMovementStateNeedsMoving";
NSString* const kEnemyMovementStateToFloor = #"enemyMovementStateToFloor";
NSString *const kEnemyMovementStateAtDestinationFloor = #"enemyMovementStateAtDestinationFloor";
NSString* const kEnemyMovementStateToFloorExit = #"enemyMovementStateToFloorExit";
NSString* const kEnemyMovementStateToAttackWalls = #"enemyMovementStateToAttackWalls";
NSString* const kEnemyMovementStateToAttackFloor = #"enemyMovementStateToAttackFloor";
NSString* const kEnemyMovementStateToAttackRoom = #"enemyMovementStateToAttackRoom";
Then I use these constants along with the names of methods in the class to build the NSDictionary:
-(void) setupDecisionTable {
//the string objects are the names of methods in the class
_decisionTable = #{kEnemyMovementStateJustSpawned: #"doEnemyJustSpawned",
kEnemyMovementStateIdle: #"doEnemyIdle",
kEnemyMovementStateNeedsMoving: #"doEnemyNeedsMoving",
kEnemyMovementStateToFloorExit: #"doFloorMovement",
kEnemyMovementStateToFloor: #"doVerticalMovement",
kEnemyMovementStateAtDestinationFloor: #"doEnemyAtDestinationFloor",
kEnemyMovementStateToAttackWalls: #"doFloorMovement",
kEnemyMovementStateToAttackFloor: #"doFloorMovement",
kEnemyMovementStateToAttackRoom: #"doFloorMovement"
};
}
Then every tick I call this method, which executes the method with the name of the object pulled from the dictionary:
-(void) doMovement {
//the selector is formed from a string inside the decision table dictionary
SEL methodToCallName = NSSelectorFromString([_decisionTable objectForKey:[self stringForState:self.state]]);
if (methodToCallName) {
IMP functionPointer = [self methodForSelector:methodToCallName];
void (*methodToCall)(id, SEL) = (void *)functionPointer;
methodToCall(self, methodToCallName);
}
}
-(NSString *) stringForState:(EnemyMovementState)state {
switch (state) {
case EnemyMovementStateJustSpawned:
return kEnemyMovementStateJustSpawned;
case EnemyMovementStateIdle:
return kEnemyMovementStateIdle;
case EnemyMovementStateNeedsMoving:
return kEnemyMovementStateNeedsMoving;
case EnemyMovementStateToFloor:
return kEnemyMovementStateToFloor;
case EnemyMovementStateAtDestinationFloor:
return kEnemyMovementStateAtDestinationFloor;
case EnemyMovementStateToFloorExit:
return kEnemyMovementStateToFloorExit;
case EnemyMovementStateToAttackWalls:
return kEnemyMovementStateToAttackWalls;
case EnemyMovementStateToAttackFloor:
return kEnemyMovementStateToAttackFloor;
case EnemyMovementStateToAttackRoom:
return kEnemyMovementStateToAttackRoom;
default:
return nil;
}
}
Finally here are a couple of the methods that execute, just for a complete example:
-(void) doEnemyIdle {
if ([self checkFloorsForJobs]) {
self.state = EnemyMovementStateNeedsMoving;
} else {
[self doIdleMovement];
}
}
-(void) doEnemyNeedsMoving {
[self calculateFloorExitPositionByFloor];
self.state = EnemyMovementStateToFloorExit;
}
This is a pretty simple implementation. Currently it can only deal with one input, and a better decision table would be able to evaluate multiple inputs and provide the proper output. I think it could be extended by having an intermediate method that took the state combined with other variables to choose the proper object from the dictionary.
After doing all this, I'm not sure that decision tables are worth the effort in Objective-C. I do not know if the code is easier to understand than a switch statement. In order to add new logic to the code, it has to be modified in more places than a switch statement would seem to require. I provide this code as an example, and it would be cool to see other versions of decision tables in Objective-C if anyone has one.

qt5 proxy model updating too soon before main model update is done

I have a setup with a main model (QStandardModel), a proxy model which changes the output of the DisplayRole, and a separate tableview displaying each model. Inside the main model data is a user role that stores a pointer to another QObject which is used by the proxy model to get the desired display value.
I'm running into problems when the object pointed to by that variable is deleted. I am handling deletion in the main model via the destroyed(QObject*) signal. Inside the slot, I search through the model looking for any items that are pointing to the object and delete the reference.
That part works fine on its own but I also have connected to the onDataChanged(...) signal of the proxy model, where I call resizeColumnsToContents() on the proxy model. This then calls the proxy's data() function. Here I check to see if the item has a pointer and, if it does, get some information from the object for display.
The result of all this becomes:
Object about to be deleted triggers destroyed(...) signal
Main model looks for any items using the deleted object and calls setData to remove the reference
Tableview catches onDataChanged signal for the proxy model and resizes columns
Proxy model's data(...) is called. It checks if the item in the main model has the object pointer and, if so, displays a value from the object. If not, it displays something else.
The problem is, at step 4 the item from the main model apparently still hasn't been deleted; the pointer address is still stored. The object the pointer was referencing, though, has been deleted by this point resulting in a segfault.
How can I fix my setup to make sure the main model is finished deleting pointer references before the proxy model tries to update?
Also, here is pseudo-code for the relevant sections:
// elsewhere
Object *someObject = new QObject();
QModelIndex index = mainModel->index(0,0);
mainModel->setData(index, someObject, ObjectPtrRole);
// do stuff
delete someObject; // Qt is actually doing this, I'm not doing it explicitly
// MainModel
void MainModel::onObjectDestroyed(QObject *obj)
{
// iterating over all model items
// if item has pointer to obj
item->setData(QVariant::fromValue(NULL), ObjectPtrRole));
}
// receives onDataChanged signal
void onProxyModelDataChanged(...)
{
ui->tblProxyView->reseizeColumnsToContents();
}
void ProxyModel::data(const QModelIndex &index, int role) const
{
QModelIndex srcIndex = mapToSource(index);
if(role == Qt::DisplayRole)
{
QVariant v = sourceModel()->data(srcIndex, ObjectPtrRole);
Object *ptr = qvariant_cast<Object*>(v);
if(ptr != NULL)
return ptr->getDisplayData();
else
return sourceModel->data(srcIndex, role);
}
}
The problem is ptr is not NULL, but the referenced object is deleted, at the time ProxyModel::data(...) is called so I end up with a segfault.
To avoid dangling pointer dereferences with instances of QObject, you can do one of two things:
Use object->deleteLater - the object will be deleted once the control returns to the event loop. Such functionality is also known as autorelease pools.
Use a QPointer. It will set itself to null upon deletion of the object, so you can check it before use.

#synchronized not working on NSMutableArray

I am trying to remove and object from an mutable array - an array which is iterated through every frame (see tick: method).
I am getting
* Collection <__NSArrayM: 0xaa99cb0> was mutated while being enumerated.
exceptions.
So I added #synchronized() to lock it from being touched by other threads, but its still failing.
- (void)addEventSubscriber:(id <EventSubscriber>)eventSubscriber
{
[_eventSubscribers addObject:eventSubscriber];
}
- (void)removeEventSubscriber:(id <EventSubscriber>)eventSubscriber
{
#synchronized(_eventSubscribers) // Not working.
{
[_eventSubscribers removeObject:eventSubscriber];
}
}
- (void)tick:(ccTime)dt
{
for (id <EventSubscriber> subscriber in _eventSubscribers)
{
if ([subscriber respondsToSelector:#selector(tick:)])
{
[subscriber tick:dt];
}
}
}
You need to lock updates to the array completely while iterating. Adding synchronized blocks to both methods addEventSubscriber: and removeEventSubscriber: will not work because the array can change while being iterated over because the iteration is not synchronized. Simply put, only one of those three methods can run at a time.
You can use #synchronized, or an NSLock to manually lock array updates while it is being iterated over.
Alternatively, you could use GCD with a serial dispatch queue to ensure that only one method is executing at a time. Here's how that would work:
You could also store the queue as a property of the class object in which you're doing this processing.
// Create the queue
dispatch_queue_t myQueue = dispatch_queue_create("myQueue", NULL);
- (void)addEventSubscriber:(id <EventSubscriber>)eventSubscriber
{
dispatch_sync(myQueue, ^{
[_eventSubscribers addObject:eventSubscriber];
});
}
- (void)removeEventSubscriber:(id <EventSubscriber>)eventSubscriber
{
dispatch_sync(myQueue, ^{
[_eventSubscribers removeObject:eventSubscriber];
});
}
- (void)tick:(ccTime)dt
{
dispatch_sync(myQueue, ^{
for (id <EventSubscriber> subscriber in _eventSubscribers)
{
if ([subscriber respondsToSelector:#selector(tick:)])
{
[subscriber tick:dt];
}
}
});
}
You are only obtaining a lock while removing items from your array, not while enumerating items. The error suggests that within an enumeration you're trying to remove an item, which is allowed by your locking but not enumeration.
Simply locking the array before enumerating may not work either. The same thread can lock an object recursively, but if your enumeration and remove are on different threads then trying to remove within an enumeration would cause deadlock. If you are in this situation you'll need to rethink your model.
I run into this problem a lot. I have no experience with thread handling / synchronization beyond an undergraduate OS course, so this is what I came up with.
Every time you iterate over the list of objects and want to remove something - instead add that object to a global "objectsToRemove" array. In your update method, remove everything from the objectsToRemove, then clean up the array to avoid over-removing an object on the next update.
Cocos2D has a CCArray which is essentially an NSMutableArray with some added functionality– like being able to remove an item while iterating. I haven't read through the code myself, so I'm not sure how it is implemented and therefore I don't use it.
you need add synchronized in this functin too.
- (void)tick:(ccTime)dt
{
#synchronized(_eventSubscribers){
for (id <EventSubscriber> subscriber in _eventSubscribers)
{
if ([subscriber respondsToSelector:#selector(tick:)])
{
[subscriber tick:dt];
}
}
}
}