multithreading - Objective C wait until an asynch task has been processed -
in code, running local server (cocoahttpserver). when server receives request, creates thread , passes control method ( - (nsobject<httpresponse> *)httpresponseformethod:(nsstring *)method uri:(nsstring *)path
, perhaps irrelevant here).
i need read list of local assets , return result. api call ( [assetslibrary enumerategroupswithtypes:alassetsgroupall usingblock:^(alassetsgroup *group, bool *stop) ...
) asynchronous.
since httpresponse needs wait until api call has finished, have created flag called _isprocessing
, set before making api call. after call finished, unsetting flag , returning http request. code wait looks like:
// api call non-blocking. hence, wait in loop until command has finished samcommand->isprocessing = yes; while (samcommand->isprocessing) { usleep(100*1000); }
the api call calls delegate method upon finishing task follows:
// called @ end of asynch operation (eg: reading local asset list) - (void) commanddidfinish { // flag open lock isprocessing = no; }
this works, perhaps require performance enhancements. how can use (run-loop etc) here improve upon performance.
edit following weichsel solution using dispatch_semaphore
following weichsel's solution, created semaphore. sequence of code is:
- cocoahttpserver receives request , hence creates new thread
- it calls static method of command class execute request
- the command class creates new command object calls class (using reflection) calls alasset apis , passes command object it
- upon returning, alasset api call calls delegate method of command class
i have hence embedded semaphores in appropriate locations. however, semaphore's wait loop doesnt end sometimes. normal output should be:
2014-02-07 11:27:23:214 mm2beta[7306:1103] httpserver: started http server on port 1978 2014-02-07 11:27:23:887 mm2beta[7306:6303] created semaphore 0x1f890670->0x1f8950a0 2014-02-07 11:27:23:887 mm2beta[7306:6303] calling execute 0x1f890670 2014-02-07 11:27:23:887 mm2beta[7306:6303] starting wait loop 0x1f890670->0x1f8950a0 2014-02-07 11:27:23:887 mm2beta[7306:907] calling getassetslist delegate 0x1f890670 2014-02-07 11:27:24:108 mm2beta[7306:907] calling delegate [0x1f890670 commanddidfinish] 2014-02-07 11:27:24:108 mm2beta[7306:907] releasing semaphore 0x1f890670->0x1f8950a0 2014-02-07 11:27:24:109 mm2beta[7306:6303] ending wait loop 0x1f890670->0x0
in every few runs, last step ( ending wait loop 0x1f890670->0x0
doesnt occur). hence, wait loop never ends. code crashes too, @ same point. clue wrong here.
my code follows:
@implementation samcommand { nsdata* resultdata; dispatch_semaphore_t semaphore; // lock establish whether command has been processed } // construct object, ensuring "command" field present in jsonstring +(nsdata*) createandexecutecommandwithjsonparamsas:(nsstring *)jsonstring { samcommand* samcommand = [[samcommand alloc] init]; samcommand.commandparams = [jsonstring dictionaryfromjson]; if(component==nil || command==nil){ ddlogerror(@"command not found in %@",jsonstring); return nil; } samcommand->semaphore = dispatch_semaphore_create(0); ddloginfo(@"created semaphore %p->%p",samcommand,samcommand->semaphore); // execute command contained in jsonstring, use reflection. ddloginfo(@"calling execute %p",samcommand); [nsclassfromstring(component) performselectoronmainthread:nsselectorfromstring([nsstring stringwithformat:@"%@_%@_%@:",command,media_source,media_type]) withobject:samcommand waituntildone:no]; // above calls non-blocking. hence, wait in loop until command has finished ddloginfo(@"starting wait loop %p->%p",samcommand,samcommand->semaphore); dispatch_semaphore_wait(samcommand->semaphore, dispatch_time_forever); ddloginfo(@"ending wait loop %p->%p",samcommand,samcommand->semaphore); ddloginfo(@""); // return data return samcommand->resultdata; } // called @ end of asynch operation (eg: reading local asset list) - (void) commanddidfinish { // flag release lock ddloginfo(@"releasing semaphore %p->%p",self,semaphore); dispatch_semaphore_signal(semaphore); semaphore = nil; } @end
i got work :)
finally, seems work stably creating semaphore, , passing alasset asynch api calls, , releasing @ end of call. earlier, calling delegate method of class had created semaphore, , semaphore object somehow getting releases. unsure of happening there really.
you can use semaphore block execution of current queue until 1 returns.
basic pattern is:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); [assetslibrary enumerateassetsusingblock^(alasset *result, nsuinteger index, bool *stop):^{ ... dispatch_semaphore_signal(semaphore); }]; dispatch_semaphore_wait(semaphore, dispatch_time_forever); dispatch_release(semaphore);
you can find full example of method in apple's mtaudioprocessingtap xcode project: https://developer.apple.com/library/ios/samplecode/audiotapprocessor
relevant lines start @ myviewcontroller.m:86
Comments
Post a Comment