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:

  1. cocoahttpserver receives request , hence creates new thread
  2. it calls static method of command class execute request
  3. the command class creates new command object calls class (using reflection) calls alasset apis , passes command object it
  4. 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

Popular posts from this blog

python - Subclassed QStyledItemDelegate ignores Stylesheet -

java - HttpClient 3.1 Connection pooling vs HttpClient 4.3.2 -

SQL: Divide the sum of values in one table with the count of rows in another -