Hi Tim
> I've poked through the ASIHTTPRequest code some over the last few
> months, and I've poked around the docs for NSOperation,
> NSOperationQueue, and some of the CFNetwork stuff. I've done non-
> blocking I/O stuff in Ruby and in Java, and I'm interested in your
> advice on how to learn more about the Cocoa approach to non-blocking I/
> O and how that relates to NSOperationQueues (and also how ASI stuff is
> setup).
>
> For example, I don't seem to get why the NSOperation docs say that you
> can mark you operation concurrent if it calls a non-blocking syscall,
> but that you really only do that if you call it without putting it in
> a queue.
The concurrency programming guide uses an example where a concurrent operation creates its own thread to do work. If you did this, there wouldn't be as much value in using queue (though queue management and dependencies would still be useful) , but I don't think you have to use concurrent operations this way.
NSOperationQueue creates the thread to allow your non-concurrent operation to run without blocking the main thread. ASIHTTPRequests are non-concurrent NSOperations, so they rely on a queue to make them run asynchronously.
It would be interesting to experiment with using a concurrent NSOperation for ASIHTTPRequest. Rather than creating its own thread, a request would continue to leave that up to the queue. It could just start the runloop, and use a timer that gets reset every time a network event happens for the timeout. That way, we could eliminate the main loop, though I'm guessing requests would still need something similar to the current approach to ensure synchronous requests still worked.
> In Ruby's EventMachine framework everything's on one thread,
> and all I/O is evented, so you tend to go about making a bunch of
> async requests one after the other, and then handling them each as
> they complete.
CFNetwork works in a similar way - you schedule a request on the run loop, and it generates events as things happen. You *can* schedule lots of requests on the same run loop / thread, but ASIHTTPRequest doesn't do that.
> With using a blocking NSOperation, like ASI does and
> what the docs suggest, it seems like even by using a non-blocking call
> you don't let the thread keep busy by pushing more requests out but
> instead force operation #2 to sit and wait for op #1 to fully complete
> as if it were synchronous (to the queue's thread).
Each request has its own thread. Requests don't know anything about each other, or how many (if any) requests are running at the same time. Only the queue can start new requests, and it will only do so when a slot becomes free (how many can run at once is defined by the queue's maxConcurrentOperationCount).
Obviously, network requests can't be load-balanced in quite the same way as CPU-bound operations. If a request hasn't received any data recently, it might be because the connection is slow, so the very worst thing to do would be to start off more requests.
> This is just one example of how I'm a novice at working with either
> async operations in cocoa or with network system calls in Obj-C. How
> can I wrap my head around the model right so I approach problems with
> the right kind of idiomatic approach for Obj-C?
I don't think it fundamentally works any differently to what you've been used to. If some things seem confusing, it's probably because NSOperationQueue and asynchronous networking have slightly different models for how things should work.
ASIHTTPRequest 's design is less about the conventions of Obj-C than it is about about creating the API that I think will make me (and hopefully other people) more productive. I think about the API I want to have for my programs, and build that. In some cases, this may mean that its mental model doesn't map directly onto the underlying APIs it uses... :)
As a side note, I really appreciate people taking the time to ask about stuff like this. Some of the design decisions in ASIHTTPRequest were made a couple of years ago, based around the needs I had for a project I was working on then. It has improved because so many people have asked good questions and have been prepared to question the implementation.
Best,
Ben