Servicing socket in Cocoa (Threads)

Before 2013rx I was sticking to Carbon, and on a Mac I had to poll http sockets to get the events to fire. If I do that under Carbon I eventually get a crash in the .poll, but with Cocoa under “normal” circumstances the events seem to fire nicely by themselves and I am no longer polling. I have an app that takes in commands via http socket and then occasionally triggers a treaded file copy based on the contents from the http socket. Before starting the file copy the socket is very responsive, but once I start the threaded copy (I am not using .copyto, but instead .read/.write in blocks) the http socket does not seem to be getting serviced and my receiveprogress event rarely get fired, sometimes for many seconds, even though I know the host at the other end is sending data. I think this is about http sockets because I have timers to update my GUI and those slow down a little during the copy but fire many more times than the .receiveprogress event. The CPU usage is also pretty low during all of this. It makes no difference if I set the priority of the copy thread as well. I am hesitant to start throwing in polling again based on crashes under Carbon. (and no, I have not filed that as a bug report yet)

Open to ideas or suggestions for different methods to keep things responsive.

tf

Todd, your design sounds right. Is there any chance that the event which starts the copy is not exiting? Remember that although threads will time-share with each other, the event model is such that until an event exits, no other events will fire. (The fact that you have UI timers that seem to work during the copy suggests that my suspicion is not correct, however).

Other idea: yield more often in your file copy. Although threads will yield at loop boundaries, I’ve sometimes found that’s not enough. E.g. instead of:

CopyThread.Run:
  for i = 0 to fileCopyLength
     copy a block
  next

try adding more yield time:

CopyThread.Run:
  for i = 0 to fileCopyLength
     copy a block
     app.sleepCurrentThread(5, true) // sleep for 5 milliseconds, but wake early if nothing is happening.
  next