0

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.

subhash Amale
  • 325
  • 3
  • 4
  • 14

2 Answers2

0

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.

zadr
  • 2,505
  • 18
  • 19
0

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;
}
Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
  • Thanks for your reply and the code.I have a question about the code and that is wether this code or block will get called whenever there is data to read in file? – subhash Amale Sep 20 '14 at 04:18
  • The code does not block. When there is data available to be read on the file descriptor, the event handler block of the dispatch source will be submitted to the queue supplied when the source was created. In this example, that's one of the global concurrent queues. Also, the file descriptor has been set to non-blocking mode, so even the `read()` call within the event handler block won't block. If there's no data available, it would return -1 and set `errno` to `EAGAIN` or `EWOULDBLOCK`. That shouldn't happen because the source would not have called the event handler, so it's not handled here. – Ken Thomases Sep 20 '14 at 12:17