Ebu
Ebu

Reputation: 163

Are NSOperations executed on run-loops? Are there run-loops in every thread? What about OpenGL?

Recently I realized I don't fully understand what gets run on a run-loop and what does not. So here's a bunch of questions:

  1. Is a run-loop something that is only run on the main thread?

  2. Does the OpenGL main loop that underlies the entire GUI run on the thread 0 run-loop? (By analogy, in GLUT this would be what calls drawScene()...)

  3. Does every thread have a run-loop?

  4. Where do NSOperations run?

  5. It seems to me that GCD is entirely separate from the run-loops because it is a C library (libdispatch). How does GCD relate to the main GUI run loop?

  6. If I use an NSOperationQueue to run multiple NSOperations at once, does each have a run-loop or do I have to write that code (and why would I)?

Thanks

Upvotes: 1

Views: 232

Answers (1)

Ken Thomases
Ken Thomases

Reputation: 90671

Questions 1 and 3 are the same. Every thread has a run loop, but not every thread runs its run loop.

A run loop is an object. Like objects generally, it has state and it has methods which cause it do something, based on that state. It doesn't magically do stuff except when it is invoked. Its state consists of input sources (like network connections or the steam of UI events it gets from the window server) and timers, organized into modes. When the run loop is asked to run, it sleeps in such a way that the OS will wake it up at a particular time or when any of its input sources is ready. It then goes through all of the input sources and timers that are ready to fire and calls the handler function for each. Depending on how it was asked to run, it may loop back and sleep again or it may return. That's all.

Some parts of Cocoa run a run loop on your behalf. Most notably, the application object runs one to wait for events. But on threads other than the main thread, the run loop is not typically running.

There's no "OpenGL main loop" unless you write one, in which case it works however you write it to. GLUT does have a main loop and it's built on the main run loop (which is the run loop of the main thread, which is the original thread of the process). You can see the implementation in the legacy GLUT code in Apple's documentation. Look for the -run method.

NSOperations don't run on their own. Something has to invoke -start on an operation object to run that operation. Like everything else in a program, that happens on some thread. Which thread is up to the caller. What the operation does from there is up to the operation object itself. It may be synchronous and do all of its work right there before returning from -start, in which case it runs on the thread where it was called. Or, it might be asynchronous and start work on some other thread and then return from -start before that work is completed.

It is common to submit operations to operation queues (instance of NSOperationQueue). The main operation queue (returned from [NSOperationQueue mainQueue]) starts all of its operations on the main thread and thus depends on the code in that thread giving time to its run loop. That's usually done by returning out of whatever methods the framework has called, but it can also happen when some APIs run the run loop or event loop within them (for example, -[NSTask waitUntilExit] or -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]).

Other operation queues run operations on worker threads that it controls. This may or may not involve run loops. That would be an implementation detail.

Run loops are not tied to Objective-C. There's a C API for them, CFRunLoop. The main dispatch queue (obtained using dispatch_get_main_queue()) is associated with the main run loop in a program which runs it, like any normal Cocoa app. However, it can instead be associated with whatever thread calls dispatch_main() for a program which doesn't run a run loop on the main thread. Whether non-main dispatch queues are related to run loops is, again, an implementation detail (but they aren't ;).

NSOperations don't have run loops, because run loops are associated with threads. When an NSOperation is running, it runs on some thread. All threads have run loops associated with them, but, as I said, not all threads run their run loops. You do not "need" to write code related to run loops for an NSOperation. Generally, you shouldn't. Sometimes people have their operations run the run loop of the thread they're on in order to allow some run-loop-based API to be notified when some source is ready or event has occurred. There's usually another way to do what they're trying to do that is more efficient with resources.

Upvotes: 2

Related Questions