NSThread waking up - objective-c

I would like to know how I can achieve the following in objective-c,
I am doing communication with FTDI232R modem using serial communication,So I am using POSIX call to open,write and read from the path of the modem(dev/tty/nameOfModem).
The POSIX calls are synchronous calls so while read I don't want to block my main thread hence I am thinking to do read call in separate thread.
I don't want this secondary thread to run continuously but wake up only when there is something to read and after read is completed it should sleep.I went through the documentation and read about providing an input source to the NSRunLoop and adding that runloop to the secondary thread,but couldn't figure out how to do it.
Thank you in advance for all your help.

You typically have a BOOL to indicate your run state, and then a date to run until. When doing socket-y things, I tend to do something like:
NSDate *beforeDate = [NSDate dateWithTimeIntervalSinceNow:.1];
while (self.isActive && [[NSRunLoop currentRunLoop] runMode: NSRunLoopCommonModes beforeDate:beforeDate]) {
beforeDate = [NSDate dateWithTimeIntervalSinceNow:.1];
}
And then when you disconnect from your modem, you can set isActive to NO to let the runloop spin down.
While not exactly what you want, Apple's docs on threading with NSOperation might be interesting for you to skim.

You should probably use GCD dispatch sources for this. Here's example code copied directly out of that article:
dispatch_source_t ProcessContentsOfFile(const char* filename)
{
// Prepare the file for reading.
int fd = open(filename, O_RDONLY);
if (fd == -1)
return NULL;
fcntl(fd, F_SETFL, O_NONBLOCK); // Avoid blocking the read operation
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ,
fd, 0, queue);
if (!readSource)
{
close(fd);
return NULL;
}
// Install the event handler
dispatch_source_set_event_handler(readSource, ^{
size_t estimated = dispatch_source_get_data(readSource) + 1;
// Read the data into a text buffer.
char* buffer = (char*)malloc(estimated);
if (buffer)
{
ssize_t actual = read(fd, buffer, (estimated));
Boolean done = MyProcessFileData(buffer, actual); // Process the data.
// Release the buffer when done.
free(buffer);
// If there is no more data, cancel the source.
if (done)
dispatch_source_cancel(readSource);
}
});
// Install the cancellation handler
dispatch_source_set_cancel_handler(readSource, ^{close(fd);});
// Start reading the file.
dispatch_resume(readSource);
return readSource;
}

Related

How to synchronously wait for reply block when using NSXPCConnection

I'm using NSXPCConnection and one of my interface call has a reply block, like this:
- (void)addItem:(NSData *) withLabel:(NSString *) reply:(void (^)(NSInteger rc))reply;
Which I call like this:
__block NSInteger status;
[proxy addItem:data withLabel:#"label" reply:^(NSInteger rc)
{
status = rc;
}
];
My understanding is that the reply block run asynchronously, and potentially after the method returns.
I want to test the return code synchronously, what's the best way to do it?
To clarify further the snippet above: the proxy object is the remote object obtained from an NSXPCConnection object using the remoteObjectProxy method. This is an important detail as this impact on which queue the reply block is invoked.
I just found out a probably better way to do this:
Use synchronousRemoteObjectProxyWithErrorHandler instead of remoteObjectProxy when creating the remote object.
No need for semaphore or group.
This is what dispatch groups were made for.
NSTimeInterval timeout = 120; // in seconds
__block NSInteger status;
dispatch_group_t syncGroup = dispatch_group_create();
dispatch_group_enter(syncGroup);
[proxy addItem:data withLabel:#"label" reply:^(NSInteger rc)
{
status = rc;
dispatch_group_leave(syncGroup);
}
];
dispatch_time_t waitTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(NSEC_PER_SEC * timeout));
if(dispatch_group_wait(syncGroup, waitTime) != 0)
{
// complain about a request timing out
}
// enjoy your status
if you chose to use remoteObjectProxyWithErrorHandler to get your proxy, then you need to remember to also put a call to dispatch_group_leave(syncGroup) in your error handler.
I propose to use dispatch_semaphore.
// Create it before the block:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block NSInteger status = 0;
[proxy addItem:data withLabel:#"label" reply:^(NSInteger rc) {
status = rc;
// In the block you signal the semaphore:
dispatch_semaphore_signal(semaphore);
}
];
// here wait for signal
// I dont remember exactly function prototype, but you should specify here semaphore and the time waiting (INFINITE)
dispatch_semaphore_wait(...);
// in non-ARC environment dont forget to release semaphore
dispatch_release(semaphore);
return status;
I want to test the return code synchronously, what's the best way to
do it?
You really don't want it to run synchronously. That'll just block the queue/thread that the block is running on and generally cause havoc to crashes.
Instead, after the status = rc; line, make a call to something that can process the fact that it is done. Let the method return, let the queue or event loop run, then do the work needed whenever addItem:withLabel: is done.
Like this:
__block NSInteger status;
[proxy addItem:data withLabel:#"label" reply:^(NSInteger rc) {
status = rc;
// like this ...
[someObject processReturnedStatus];
}
];

monitoring ifstream read progress from separate thread in Obj-C

This is the code I'm using to write and read a file in the background using GCD.
#import "AppDelegate.h"
#import <dispatch/dispatch.h>
#import <iostream>
#import <fstream>
size_t fileSize = 1024 * 1024 * 10;
std::ofstream *osPtr = 0;
std::ifstream *isPtr = 0;
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
const float framerate = 40;
const float frequency = 1.0f/framerate;
[NSTimer scheduledTimerWithTimeInterval:frequency
target:self selector:#selector(doSomething)
userInfo:nil repeats:YES];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
std::ofstream os("myFile", std::ios::binary);
if (os) {
osPtr = &os;
for (int i = 0; i<fileSize; i++) {
os << 'c';
}
osPtr = 0;
os.close();
printf("write done\n");
}
std::ifstream is("myFile", std::ios::binary);
if (is) {
is.seekg(0, std::ifstream::end);
fileSize = (size_t)is.tellg();
is.seekg(0, std::ifstream::beg);
isPtr = &is;
while ( is.good() )
{
char c;
is >> c;
}
isPtr = 0;
is.close();
printf("read done\n");
}
});
}
- (void)doSomething
{
// write file progress indicator
if (osPtr)
printf("%5.1f\n", (float)osPtr->tellp()/fileSize*100.0f);
// read file progress indicator
if (isPtr)
printf("%5.1f\n", (float)isPtr->tellg()/fileSize*100.0f);
}
#end
It writes ok, but when reading big files (5 mb or more) an EXEC_BAD_ACCESS error is thrown, within the streambuf class code.
template <class _CharT, class _Traits>
inline _LIBCPP_INLINE_VISIBILITY
typename basic_streambuf<_CharT, _Traits>::int_type
basic_streambuf<_CharT, _Traits>::sbumpc()
{
if (__ninp_ == __einp_)
return uflow();
return traits_type::to_int_type(*__ninp_++); //<---EXEC_BAD_ACCESS
}
This is the project test.zip
Does the documentation of std::of stream say that it is thread safe? I don't think so.
My bet would be that you always get a crash if your progress function is called while the osPtr or isPtr exists. But for small files, the writing/reading is so fast that they are both gone before your progress method is ever called.
The best way to read and write files asynchronously would be to use the GCD IO functions...
There is a convenience read function (and a similar write function).
void dispatch_read(
dispatch_fd_t fd,
size_t length,
dispatch_queue_t queue,
void (^handler)(dispatch_data_t data, int error));
Your handler block would be called back each time the system had some data ready to be read, and you could update your progress indicator.
You could use dispatch_after with the same queue, and they would be automatically seriallized (as long as you used a serial queue).
However, just to be clear: your problem is that you are accessing the stream objects from multiple threads at the same time. One thread is running the queue code block, and another is running your timer call. They are both trying to access the same stream objects. Bad news.
If you want to continue to use your method of IO, you need to serialize access in one of several ways. You can create a class that provides safe access to an IOStream across multiple threads, or you can serialize the access yourself with locks. Both C++ and Obj-C provide many synchronization APIs.
However, there is a very common idiom used in lots of apple code: the delegate.
In your case, a simple progress delegate, with a method that sends the current progress, would suffice. This way the delegate is called from within the context of the long running task, which means you have synchronized access to any shared data.
If you want, you can dispatch any GUI work to the main thread with GCD.
So this would be my approach.
I need to subclass std::streambuf, even when it can be overkill (like it is posted here or here), at least for a feature that should be quite common in multithreaded applications.

How to do structured programming using blocks in Objective-C

When using methods which return blocks they can be very convenient.
However, when you have to string a few of them together it gets messy really quickly
for instance, you have to call 4 URLs in succession:
[remoteAPIWithURL:url1 success:^(int status){
[remoteAPIWithURL:url2 success:^(int status){
[remoteAPIWithURL:url3 success:^(int status){
[remoteAPIWithURL:url2 success:^(int status){
//succes!!!
}];
}];
}];
}];
So for every iteration I go one level deeper, and I don't even handle errors in the nested blocks yet.
It gets worse when there is an actual loop. For instance, say I want to upload a file in 100 chunks:
- (void) continueUploadWithBlockNr:(int)blockNr
{
if(blocknr>=100)
{
//success!!!
}
[remoteAPIUploadFile:file withBlockNr:blockNr success:^(int status)
{
[self continueUploadWithBlockNr:blockNr];
}];
}
This feels very unintuitive, and gets very unreadable very quick.
In .Net they solved all this using the async and await keyword, basically unrolling these continuations into a seemingly synchronous flow.
What is the best practice in Objective C?
Your question immediately made me think of recursion. Turns out, Objective-c blocks can be used in recursion. So I came up with the following solution, which is easy to understand and can scale to N tasks pretty nicely.
// __block declaration of the block makes it possible to call the block from within itself
__block void (^urlFetchBlock)();
// Neatly aggregate all the urls you wish to fetch
NSArray *urlArray = #[
[NSURL URLWithString:#"http://www.google.com"],
[NSURL URLWithString:#"http://www.stackoverflow.com"],
[NSURL URLWithString:#"http://www.bing.com"],
[NSURL URLWithString:#"http://www.apple.com"]
];
__block int urlIndex = 0;
// the 'recursive' block
urlFetchBlock = [^void () {
if (urlIndex < (int)[urlArray count]){
[self remoteAPIWithURL:[urlArray objectAtIndex:index]
success:^(int theStatus){
urlIndex++;
urlFetchBlock();
}
failure:^(){
// handle error.
}];
}
} copy];
// initiate the url requests
urlFetchBlock();
One way to reduce nesting is to define methods that return the individual blocks. In order to facilitate the data sharing which is done "auto-magically" by the Objective C compiler through closures, you would need to define a separate class to hold the shared state.
Here is a rough sketch of how this can be done:
typedef void (^WithStatus)(int);
#interface AsyncHandler : NSObject {
NSString *_sharedString;
NSURL *_innerUrl;
NSURL *_middleUrl;
WithStatus _innermostBlock;
}
+(void)handleRequest:(WithStatus)innermostBlock
outerUrl:(NSURL*)outerUrl
middleUrl:(NSURL*)middleUrl
innerUrl:(NSURL*)innerUrl;
-(WithStatus)outerBlock;
-(WithStatus)middleBlock;
#end
#implementation AsyncHandler
+(void)handleRequest:(WithStatus)innermostBlock
outerUrl:(NSURL*)outerUrl
middleUrl:(NSURL*)middleUrl
innerUrl:(NSURL*)innerUrl {
AsyncHandler *h = [[AsyncHandler alloc] init];
h->_innermostBlock = innermostBlock;
h->_innerUrl = innerUrl;
h->_middleUrl = middleUrl;
[remoteAPIWithURL:outerUrl success:[self outerBlock]];
}
-(WithStatus)outerBlock {
return ^(int success) {
_sharedString = [NSString stringWithFormat:#"Outer: %i", success];
[remoteAPIWithURL:_middleUrl success:[self middleBlock]];
};
}
-(WithStatus)middleBlock {
return ^(int success) {
NSLog("Shared string: %#", _sharedString);
[remoteAPIWithURL:_innerUrl success:_innermostBlock];
};
}
#end
Note: All of this assumes ARC; if you are compiling without it, you need to use Block_copy in the methods returning blocks. You would also need to do a copy in the calling code below.
Now your original function can be re-written without the "Russian doll" nesting, like this:
[AsyncHandler
handleRequest:^(int status){
//succes!!!
}
outerUrl:[NSURL #"http://my.first.url.com"]
middleUrl:[NSURL #"http://my.second.url.com"]
innerUrl:[NSURL #"http://my.third.url.com"]
];
Iterative algorithm:
Create a __block variable (int urlNum) to keep track of the current URL (inside an NSArray of them).
Have the onUrlComplete block fire off the next request until all URLs have been loaded.
Fire the first request.
When all URLs have been loaded, do the "//success!" dance.
Code written without the aid of XCode (meaning, there may be compiler errors -- will fix if necessary):
- (void)loadUrlsAsynchronouslyIterative:(NSArray *)urls {
__block int urlNum = 0;
void(^onUrlComplete)(int) = nil; //I don't remember if you can call a block from inside itself.
onUrlComplete = ^(int status) {
if (urlNum < urls.count) {
id nextUrl = urls[urlNum++];
[remoteAPIWithURL:nextUrl success:onUrlComplete];
} else {
//success!
}
}
onUrlComplete(0); //fire first request
}
Recursive algorithm:
Create a method to load all the remaining URLs.
When remaining URLs is empty, fire "onSuccess".
Otherwise, fire request for the next URL and provide a completion block that recursively calls the method with all but the first remaining URLs.
Complications: we declared the "onSuccess" block to accept an int status parameter, so we pass the last status variable down (including a "default" value).
Code written without the aid of XCode (bug disclaimer here):
- (void)loadUrlsAsynchronouslyRecursive:(NSArray *)remainingUrls onSuccess:(void(^)(int status))onSuccess lastStatus:(int)lastStatus {
if (remainingUrls.count == 0) {
onSuccess(lastStatus);
return;
}
id nextUrl = remainingUrls[0];
remainingUrls = [remainingUrls subarrayWithRange:NSMakeRange(1, remainingUrls.count-1)];
[remoteAPIWithUrl:nextUrl onSuccess:^(int status) {
[self loadUrlsAsynchronouslyRecursive:remainingUrls onSuccess:onSuccess lastStatus:status];
}];
}
//fire first request:
[self loadUrlsAsynchronouslyRecursive:urls onSuccess:^(int status) {
//success here!
} lastStatus:0];
Which is better?
The iterative algorithm is simple and concise -- if you're comfortable playing games with __block variables and scopes.
Alternatively, the recursive algorithm doesn't require __block variables and is fairly simple, as recursive algorithms go.
The recursive implementation is more re-usable that the iterative one (as implemented).
The recursive algorithm might leak (it requires a reference to self), but there are several ways to fix that: make it a function, use __weak id weakSelf = self;, etc.
How easy would it be to add error-handling?
The iterative implementation can easily be extended to check the value of status, at the cost of the onUrlComplete block becoming more complex.
The recursive implementation is perhaps not as straight-forward to extend -- primarily because it is re-usable. Do you want to cancel loading more URLs when the status is such-and-such? Then pass down a status-checking/error-handling block that accepts int status and returns BOOL (for example YES to continue, NO to cancel). Or perhaps modify onSuccess to accept both int status and NSArray *remainingUrls -- but you'll need to call loadUrlsAsynchronouslyRecursive... in your onSuccess block implementation.
You said (in a comment), “asynchronous methods offer easy asynchronisity without using explicit threads.” But your complaint seems to be that you're trying to do something with asynchronous methods, and it's not easy. Do you see the contradiction here?
When you use a callback-based design, you sacrifice the ability to express your control flow directly using the language's built-in structures.
So I suggest you stop using a callback-based design. Grand Central Dispatch (GCD) makes it easy (that word again!) to perform work “in the background”, and then call back to the main thread to update the user interface. So if you have a synchronous version of your API, just use it in a background queue:
- (void)interactWithRemoteAPI:(id<RemoteAPI>)remoteAPI {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// This block runs on a background queue, so it doesn't block the main thread.
// But it can't touch the user interface.
for (NSURL *url in #[url1, url2, url3, url4]) {
int status = [remoteAPI syncRequestWithURL:url];
if (status != 0) {
dispatch_async(dispatch_get_main_queue(), ^{
// This block runs on the main thread, so it can update the
// user interface.
[self remoteRequestFailedWithURL:url status:status];
});
return;
}
}
});
}
Since we're just using normal control flow, it's straightforward to do more complicated things. Say we need to issue two requests, then upload a file in chunks of at most 100k, then issue one more request:
#define AsyncToMain(Block) dispatch_async(dispatch_get_main_queue(), Block)
- (void)uploadFile:(NSFileHandle *)fileHandle withRemoteAPI:(id<RemoteAPI>)remoteAPI {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
int status = [remoteAPI syncRequestWithURL:url1];
if (status != 0) {
AsyncToMain(^{ [self remoteRequestFailedWithURL:url1 status:status]; });
return;
}
status = [remoteAPI syncRequestWithURL:url2];
if (status != 0) {
AsyncToMain(^{ [self remoteRequestFailedWithURL:url2 status:status]; });
return;
}
while (1) {
// Manage an autorelease pool to avoid accumulating all of the
// 100k chunks in memory simultaneously.
#autoreleasepool {
NSData *chunk = [fileHandle readDataOfLength:100 * 1024];
if (chunk.length == 0)
break;
status = [remoteAPI syncUploadChunk:chunk];
if (status != 0) {
AsyncToMain(^{ [self sendChunkFailedWithStatus:status]; });
return;
}
}
}
status = [remoteAPI syncRequestWithURL:url4];
if (status != 0) {
AsyncToMain(^{ [self remoteRequestFailedWithURL:url4 status:status]; });
return;
}
AsyncToMain(^{ [self uploadFileSucceeded]; });
});
}
Now I'm sure you're saying “Oh yeah, that looks great.” ;^) But you might also be saying “What if RemoteAPI only has asynchronous methods, not synchronous methods?”
We can use GCD to create a synchronous wrapper for an asynchronous method. We need to make the wrapper call the async method, then block until the async method calls the callback. The tricky bit is that perhaps we don't know which queue the async method uses to invoke the callback, and we don't know if it uses dispatch_sync to call the callback. So let's be safe by calling the async method from a concurrent queue.
- (int)syncRequestWithRemoteAPI:(id<RemoteAPI>)remoteAPI url:(NSURL *)url {
__block int outerStatus;
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
[remoteAPI asyncRequestWithURL:url completion:^(int status) {
outerStatus = status;
dispatch_semaphore_signal(sem);
}];
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
dispatch_release(sem);
return outerStatus;
}
UPDATE
I will respond to your third comment first, and your second comment second.
Third Comment
Your third comment:
Last but not least, your solution of dedicating a separate thread to wrap around the synchronous version of a call is more costly than using the async alternatives. a Thread is an expensive resource, and when it is blocking you basically have lost one thread. Async calls (the ones in the OS libraries at least) are typically handled in a much more efficient way. (For instance, if you would request 10 urls at the same time, chances are it will not spin up 10 threads (or put them in a threadpool))
Yes, using a thread is more expensive than just using the asynchronous call. So what? The question is whether it's too expensive. Objective-C messages are too expensive in some scenarios on current iOS hardware (the inner loops of a real-time face detection or speech recognition algorithm, for example), but I have no qualms about using them most of the time.
Whether a thread is “an expensive resource” really depends on the context. Let's consider your example: “For instance, if you would request 10 urls at the same time, chances are it will not spin up 10 threads (or put them in a threadpool)”. Let's find out.
NSURL *url = [NSURL URLWithString:#"http://1.1.1.1/"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
for (int i = 0; i < 10; ++i) {
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSLog(#"response=%# error=%#", response, error);
}];
}
So here I am using Apple's own recommended +[NSURLConnection sendAsynchronousRequest:queue:completionHandler:] method to send 10 requests asynchronously. I've chosen the URL to be non-responsive, so I can see exactly what kind of thread/queue strategy Apple uses to implement this method. I ran the app on my iPhone 4S running iOS 6.0.1, paused in the debugger, and took a screen shot of the Thread Navigator:
You can see that there are 10 threads labeled com.apple.root.default-priority. I've opened three of them so you can see that they are just normal GCD queue threads. Each calls a block defined in +[NSURLConnection sendAsynchronousRequest:…], which just turns around and calls +[NSURLConnection sendSynchronousRequest:…]. I checked all 10, and they all have the same stack trace. So, in fact, the OS library does spin up 10 threads.
I bumped the loop count from 10 to 100 and found that GCD caps the number of com.apple.root.default-priority threads at 64. So my guess is the other 36 requests I issued are queued up in the global default-priority queue, and won't even start executing until some of the 64 “running” requests finish.
So, is it too expensive to use a thread to turn an asynchronous function into a synchronous function? I'd say it depends on how many of these you plan to do simultaneously. I would have no qualms if the number's under 10, or even 20.
Second Comment
Which brings me to your second comment:
However, when you have: do these 3 things at the same time, and when 'any' of them is finished then ignore the rest and do these 3 calls at the same time and when 'all' of them finish then succes.
These are cases where it's easy to use GCD, but we can certainly combine the GCD and async approaches to use fewer threads if you want, while still using the languages native tools for control flow.
First, we'll make a typedef for the remote API completion block, just to save typing later:
typedef void (^RemoteAPICompletionBlock)(int status);
I'll start the control flow the same way as before, by moving it off the main thread to a concurrent queue:
- (void)complexFlowWithRemoteAPI:(id<RemoteAPI>)remoteAPI {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
First we want to issue three requests simultaneously and wait for one of them to succeed (or, presumably, for all three to fail).
So let's say we have a function, statusOfFirstRequestToSucceed, that issues any number of asynchronous remote API requests and waits for the first to succeed. This function will provide the completion block for each async request. But the different requests might take different arguments… how can we pass the API requests to the function?
We can do it by passing a literal block for each API request. Each literal block takes the completion block and issues the asynchronous remote API request:
int status = statusOfFirstRequestToSucceed(#[
^(RemoteAPICompletionBlock completion) {
[remoteAPI requestWithCompletion:completion];
},
^(RemoteAPICompletionBlock completion) {
[remoteAPI anotherRequestWithCompletion:completion];
},
^(RemoteAPICompletionBlock completion) {
[remoteAPI thirdRequestWithCompletion:completion];
}
]);
if (status != 0) {
AsyncToMain(^{ [self complexFlowFailedOnFirstRoundWithStatus:status]; });
return;
}
OK, now we've issued the three first parallel requests and waited for one to succeed, or for all of them to fail. Now we want to issue three more parallel requests and wait for all to succeed, or for one of them to fail. So it's almost identical, except I'm going to assume a function statusOfFirstRequestToFail:
status = statusOfFirstRequestToFail(#[
^(RemoteAPICompletionBlock completion) {
[remoteAPI requestWithCompletion:completion];
},
^(RemoteAPICompletionBlock completion) {
[remoteAPI anotherRequestWithCompletion:completion];
},
^(RemoteAPICompletionBlock completion) {
[remoteAPI thirdRequestWithCompletion:completion];
}
]);
if (status != 0) {
AsyncToMain(^{ [self complexFlowFailedOnSecondRoundWithStatus:status]; });
return;
}
Now both rounds of parallel requests have finished, so we can notify the main thread of success:
[self complexFlowSucceeded];
});
}
Overall, that seems like a pretty straightforward flow of control to me, and we just need to implement statusOfFirstRequestToSucceed and statusOfFirstRequestToFail. We can implement them with no extra threads. Since they are so similar, we'll make them both call on a helper function that does the real work:
static int statusOfFirstRequestToSucceed(NSArray *requestBlocks) {
return statusOfFirstRequestWithStatusPassingTest(requestBlocks, ^BOOL (int status) {
return status == 0;
});
}
static int statusOfFirstRequestToFail(NSArray *requestBlocks) {
return statusOfFirstRequestWithStatusPassingTest(requestBlocks, ^BOOL (int status) {
return status != 0;
});
}
In the helper function, I'll need a queue in which to run the completion blocks, to prevent race conditions:
static int statusOfFirstRequestWithStatusPassingTest(NSArray *requestBlocks,
BOOL (^statusTest)(int status))
{
dispatch_queue_t completionQueue = dispatch_queue_create("remote API completion", 0);
Note that I will only put blocks on completionQueue using dispatch_sync, and dispatch_sync always runs the block on the current thread unless the queue is the main queue.
I'll also need a semaphore, to wake up the outer function when some request has completed with a passing status, or when all requests have finished:
dispatch_semaphore_t enoughJobsCompleteSemaphore = dispatch_semaphore_create(0);
I'll keep track of the number of jobs not yet finished and the status of the last job to finish:
__block int jobsLeft = requestBlocks.count;
__block int outerStatus = 0;
When jobsLeft becomes 0, it means that either I've set outerStatus to a status that passes the test, or that all jobs have completed. Here's the completion block where I'll the work of tracking whether I'm done waiting. I do it all on completionQueue to serialize access to jobsLeft and outerStatus, in case the remote API dispatches multiple completion blocks in parallel (on separate threads or on a concurrent queue):
RemoteAPICompletionBlock completionBlock = ^(int status) {
dispatch_sync(completionQueue, ^{
I check to see if the outer function is still waiting for the current job to complete:
if (jobsLeft == 0) {
// The outer function has already returned.
return;
}
Next, I decrement the number of jobs remaining and make the completed job's status available to the outer function:
--jobsLeft;
outerStatus = status;
If the completed job's status passes the test, I set jobsLeft to zero to prevent other jobs from overwriting my status or singling the outer function:
if (statusTest(status)) {
// We have a winner. Prevent other jobs from overwriting my status.
jobsLeft = 0;
}
If there are no jobs left to wait on (because they've all finished or because this job's status passed the test), I wake up the outer function:
if (jobsLeft == 0) {
dispatch_semaphore_signal(enoughJobsCompleteSemaphore);
}
Finally, I release the queue and the semaphore. (The retains will be later, when I loop through the request blocks to execute them.)
dispatch_release(completionQueue);
dispatch_release(enoughJobsCompleteSemaphore);
});
};
That's the end of the completion block. The rest of the function is trivial. First I execute each request block, and I retain the queue and the semaphore to prevent dangling references:
for (void (^requestBlock)(RemoteAPICompletionBlock) in requestBlocks) {
dispatch_retain(completionQueue); // balanced in completionBlock
dispatch_retain(enoughJobsCompleteSemaphore); // balanced in completionBlock
requestBlock(completionBlock);
}
Note that the retains aren't necessary if you're using ARC and your deployment target is iOS 6.0 or later.
Then I just wait for one of the jobs to wake me up, release the queue and the semaphore, and return the status of the job that woke me:
dispatch_semaphore_wait(enoughJobsCompleteSemaphore, DISPATCH_TIME_FOREVER);
dispatch_release(completionQueue);
dispatch_release(enoughJobsCompleteSemaphore);
return outerStatus;
}
Note that the structure of statusOfFirstRequestWithStatusPassingTest is fairly generic: you can pass any request blocks you want, as long as each one calls the completion block and passes in an int status. You could modify the function to handle a more complex result from each request block, or to cancel outstanding requests (if you have a cancellation API).
While researching this myself I bumped into a port of Reactive Extensions to Objective-C. Reactive Extensions is like having the ability to querying a set of events or asynchronous operations. I know it has had a big uptake under .Net and JavaScript, and now apparently there is a port for Objective-C as well
https://github.com/blog/1107-reactivecocoa-for-a-better-world
Syntax looks tricky. I wonder if there is real world experience with it for iPhone development and if it does actually solve this issue elegantly.
I tend to wrap big nested block cluster f**** like you describe in subclasses of NSOperation that describe what the overall behaviour that your big nest block cluster f*** is actually doing (rather than leaving them littered throughout other code).
For example if your following code:
[remoteAPIWithURL:url1 success:^(int status){
[remoteAPIWithURL:url2 success:^(int status){
[remoteAPIWithURL:url3 success:^(int status){
[remoteAPIWithURL:url2 success:^(int status){
//succes!!!
}];
}];
}];
}];
is intended to get an authorise token and then sync something perhaps it would be an NSAuthorizedSyncOperation… I'm sure you get the gist. Benefits of this are nice tidy bundles of behaviour wrapped up in a class with one place to edit them if things change down the line. My 2¢.
In NSDocument the following methods are available for serialization:
Serialization
– continueActivityUsingBlock:
– continueAsynchronousWorkOnMainThreadUsingBlock:
– performActivityWithSynchronousWaiting:usingBlock:
– performAsynchronousFileAccessUsingBlock:
– performSynchronousFileAccessUsingBlock:
I'm just digging into this, but it seems like this would be a good place to start.
Not sure if that is want you where looking for? Though all objects in the array need different times to complete the all appear in the order the where submitted to the queue.
typedef int(^SumUpTill)(int);
SumUpTill sum = ^(int max){
int i = 0;
int result = 0;
while (i < max) {
result += i++;
}
return result;
};
dispatch_queue_t queue = dispatch_queue_create("com.dispatch.barrier.async", DISPATCH_QUEUE_CONCURRENT);
NSArray *urlArray = #[ [NSURL URLWithString:#"http://www.google.com"],
#"Test",
[sum copy],
[NSURL URLWithString:#"http://www.apple.com"]
];
[urlArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
dispatch_barrier_async(queue, ^{
if ([obj isKindOfClass:[NSURL class]]) {
NSURLRequest *request = [NSURLRequest requestWithURL:obj];
NSURLResponse *response = nil;
NSError *error = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"index = %d, response=%# error=%#", idx, response, error);
}
else if ([obj isKindOfClass:[NSString class]]) {
NSLog(#"index = %d, string %#", idx, obj);
}
else {
NSInteger result = ((SumUpTill)obj)(1000000);
NSLog(#"index = %d, result = %d", idx, result);
}
});
}];

High CPU consumption and latency while reading serial data

I have two functions in my software that cause important latency problems. The software is written in Objective-C. I receive serial data from an usb device and my goal is to encapsulate them and then to send them to another object which will process the data.
This section of the program causes large cpu and latency issues and I don't know how to solve this at all. The device only sends data when its state changes, thus when lots of changes occur well everything becomes laggy..
- (void)getSerialData {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[self getSerialDataLoop];
});
}
- (void)getSerialDataLoop {
readThreadRunning = YES;
char byte_buffer[2]; // buffer for holding incoming data
int numBytes=0; // number of bytes read during read
NSString *text;
// this will loop untilthe serial port closes
while(TRUE) {
// read() blocks until some data is available or the port is closed
numBytes = (int)read(serialFileDescriptor, byte_buffer, 1); // read up to the size of the buffer
if(numBytes>0) {
///text = [NSString stringWithCString:byte_buffer encoding:NSSymbolStringEncoding];
if(![text isEqualToString:#""]){
text = [NSString stringWithUTF8String:byte_buffer];
[self performSelectorOnMainThread:#selector(processNSStringData:) withObject:text waitUntilDone:YES];
}
} else {
break; // Stop the thread if there is an error
}
}
// make sure the serial port is closed
if (serialFileDescriptor != -1) {
close(serialFileDescriptor);
serialFileDescriptor = -1;
}
// mark that the thread has quit
readThreadRunning = FALSE;
}
Do you have any ideas or pointers?
You've basically reinvented NSStream here. I would first recommend that you investigate this already available solution that ties into the run loop.
You also could easily be overwhelming yourself with calls to getSerialData. Nothing in your system prevents multiple calls to this routine, and if you make multiple calls, you'll get dueling concurrent operations. Using NSStream would address that. In any case, though, you shouldn't keep creating new read blocks if one is already running.
You're also reading one byte at time and processing it. This is likely your biggest impact. Calling back to the main thread for every byte is likely quite expensive. If nothing else you're creating a new NSString object for every byte.
Note that your code is very dangerous and could crash. You never initialize byte_buffer, and you only read one byte into it. When you call stringWithUTF8String:, you're assuming that the second byte is \0, which depends on the current state of the stack.

How do you test an asynchronous method?

I have an object that fetches XML or JSON over a network. Once this fetching is complete it calls a selector, passing in the returned data. So, for example I'd have something like:
-(void)testResponseWas200
{
[MyObject get:#"foo.xml" withTarget:self selector:#selector(dataFinishedLoading:)];
}
I tried the route of implementing dataFinishedLoading in the Test class and attempting to test inside that method, but the test suite is just locking up. This seems like it's a case for mocking, but I'm wondering if others have encountered this and how they handled it.
FYI: I'm using gh-unit for testing and any method prefixed with test* is executed automatically.
Three ways that come to mind are: NSRunLoop, semaphores, and groups.
NSRunLoop
__block bool finished = false;
// For testing purposes we create this asynchronous task
// that starts after 3 seconds and takes 1 second to execute.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0UL);
dispatch_time_t threeSeconds = dispatch_time(DISPATCH_TIME_NOW, 3LL * NSEC_PER_SEC);
dispatch_after(threeSeconds, queue, ^{
sleep(1); // replace this with your task
finished = true;
});
// loop until the flag is set from inside the task
while (!finished) {
// spend 1 second processing events on each loop
NSDate *oneSecond = [NSDate dateWithTimeIntervalSinceNow:1];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:oneSecond];
}
A NSRunLoop is a loop that processes events like network ports, keyboard, or any other input source you plug in, and returns after processing those events, or after a time limit. When there are no events to process, the run loop puts the thread to sleep. All Cocoa and Core Foundation applications have a run loop underneath. You can read more about run loops in Apple's Threading Programming Guide: Run Loops, or in Mike Ash Friday Q&A 2010-01-01: NSRunLoop Internals.
In this test, I'm just using the NSRunLoop to sleep the thread for a second. Without it, the constant looping in the while would consume 100% of a CPU core.
If the block and the boolean flag are created in the same lexical scope (eg: both inside a method), then the flag needs the __block storage qualifier to be mutable. Had the flag been a global variable, it wouldn't need it.
If the test crashes before setting the flag, the thread is stuck waiting forever. Add a time limit to avoid that:
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:2];
while (!finished && [timeout timeIntervalSinceNow]>0) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}
if (!finished) NSLog(#"test failed with timeout");
If you are using this code for unit testing, an alternative way to insert a timeout is to dispatch a block with an assert:
// taken from https://github.com/JaviSoto/JSBarrierOperationQueue/blob/master/JSBarrierOperationQueueTests/JSBarrierOperationQueueTests.m#L118
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, 2LL * NSEC_PER_SEC);
dispatch_after(timeout, dispatch_get_main_queue(), ^(void){
STAssertTrue(done, #"Should have finished by now");
});
Semaphore
Similar idea but sleeping until a semaphore changes, or until a time limit:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// signal the semaphore after 3 seconds using a global queue
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0UL);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3LL*NSEC_PER_SEC), queue, ^{
sleep(1);
dispatch_semaphore_signal(semaphore);
});
// wait with a time limit of 5 seconds
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, 5LL*NSEC_PER_SEC);
if (dispatch_semaphore_wait(semaphore, timeout)==0) {
NSLog(#"success, semaphore signaled in time");
} else {
NSLog(#"failure, semaphore didn't signal in time");
}
dispatch_release(semaphore);
If instead we waited forever with dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); we would be stuck until getting a signal from the task, which keeps running on the background queue.
Group
Now imagine you have to wait for several blocks. You can use an int as flag, or create a semaphore that starts with a higher number, or you can group the blocks and wait until the group is finished. In this example I do the later with just one block:
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0UL);
// dispatch work to the given group and queue
dispatch_group_async(group,queue,^{
sleep(1); // replace this with your task
});
// wait two seconds for the group to finish
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, 2LL*NSEC_PER_SEC);
if (dispatch_group_wait(group, timeout)==0) {
NSLog(#"success, dispatch group completed in time");
} else {
NSLog(#"failure, dispatch group did not complete in time");
}
dispatch_release(group);
If for some reason (to clean up resources?) you want to run a block after the group is finished, use dispatch_group_notify(group,queue, ^{/*...*/});
Asynchronous callbacks often require a message loop to run. It is a frequent pattern to stop the message loop after callback was called in the test code. Otherwise the loop is just waiting for next tasks, and there will be none.
#jano Thank you I made of this little util from your post
In PYTestsUtils.m
+ (void)waitForBOOL:(BOOL*)finished forSeconds:(int)seconds {
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:seconds];
while (!*finished && [timeout timeIntervalSinceNow]>0) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:1]];
}
}
in my test file
- (void)testSynchronizeTime
{
__block BOOL finished = NO;
[self.connection synchronizeTimeWithSuccessHandler:^(NSTimeInterval serverTime) {
NSLog(#"ServerTime %f", serverTime);
finished = YES;
} errorHandler:^(NSError *error) {
STFail(#"Cannot get ServerTime %#", error);
finished = YES;
}];
[PYTestsUtils waitForBOOL:&finished forSeconds:10];
if (! finished)
STFail(#"Cannot get ServerTime within 10 seconds");
}
variation
add in PYTestsUtils.m
+ (void)execute:(PYTestExecutionBlock)block ifNotTrue:(BOOL*)finished afterSeconds:(int)seconds {
[self waitForBOOL:finished forSeconds:seconds];
if (! *finished) block();
}
usage:
- (void)testSynchronizeTime
{
__block BOOL finished = NO;
[self.connection synchronizeTimeWithSuccessHandler:^(NSTimeInterval serverTime) {
NSLog(#"ServerTime %f", serverTime);
finished = YES;
} errorHandler:^(NSError *error) {
STFail(#"Cannot get ServerTime %#", error);
finished = YES;
}];
[PYTestsUtils execute:^{
STFail(#"Cannot get ServerTime within 10 seconds");
} ifNotTrue:&finished afterSeconds:10];
}
One of the best ways to test asynchronous and multi-threaded code is with event logging. Your code should log events at interesting or useful times. Often an event alone is enough information to prove that logic is working correctly. Somtimes events will need payloads, or other meta information so they can be paired or chained.
This is most useful when the run-time or the operating system supports an efficient and robust eventing mechanism. This enables your product to ship with events in the 'retail' version. In this scenario, your events are only enabled when you need to debug a problem, or run a unit test to prove thins are working correctly.
Having the events in the retail (production) code lets you test and debug on any platform. This is huge benefit over debug or 'checked' code.
Note, like asserts, be careful where you put events - they can be expensive if logged to often. But the good news is that modern OSes and some application frameworks support eventing mechanisms that support 10's of thousands of events easily. Some support taking a stack trace on selected events. This can be very powerful, but usually requires that symbols are available at some point in time - either at logging, or trace post processing time on the target system.