Hello,

I'm working on an application that simulates some real physical phenomena, some aspects of which being under the user's control, and I need advice on implementing some multithreaded behavior to improve responsiveness. I would like to get some advice, in particular, regarding which tasks I should implement as threads or, better yet, as NSOperation or NSInvocationOperation objects. I've read the Threading Programming Guide but still have some doubts on the best way to accomplish the goals above. I've also searched the archives and the post I found closest to what I'm trying to do, yet still not helpful enough for me, is

http://www.cocoabuilder.com/archive/message/cocoa/2008/11/5/221957

Elsewhere, I also found these two Late Night Cocoa podcasts

Concurrent Programming
http://www.mac-developer-network.com/podcasts/latenightcocoa/episode25/index.html

Lockless Thread-Safe Data Structures
http://www.mac-developer-network.com/podcasts/latenightcocoa/episode32/index.html

but I haven't had a chance to go through them yet, so I thought I'd pick people's brains until I do.

To make it more explicit, I'm going to use the example of simulating a few elastic balls moving under the action of gravity, bouncing off one another inside a container.

So, the UI has a custom NSView serving as the container where the balls are going to be drawn. The UI also has a number of controls the user can interact with to change properties that affect the simulation (for example, gravity, the degree of elasticity during collisions, etc) and the way the results are displayed (for example, the ball colors, whether or not to draw paths, and whatnot). Another control is in charge of changing the screen update rate.

The application has essentially 4 tasks:

1. passing information from the UI to the simulation engine;

2. continuously running the simulation engine, at a rate that can also be changed dynamically by the user (for instance, in the bouncing balls example, increasing gravity makes the balls move faster, thereby requiring the engine to run more often in order to preserve accuracy and to prevent anomalies such as the balls overlapping one another);

3. passing the results of the simulation to the drawing engine;

4. drawing the results on screen, at a rate that can also be changed dynamically by the user (through the control that changes the screen update rate).

I figured I'd split task 1 into two parts, first passing the UI information to an application controller object, and then passing the information to the simulation engine. The first part, passing the UI info to the application controller, is easily accomplished by binding the properties of the various UI controls to corresponding properties in the application controller.

The second part, passing the info from the application controller to the simulation engine, should be done from a separate thread so that the main thread wouldn't block when the simulation engine is busy and cannot accept changes to its parameters.

From reading the Threading Programming Guide, I suspect that the best approach here is to create an NSInvocationOperation that is dependent on the simulation engine being ready to accept changes to its parameters. Is this the right idea? Even if it is, how should I handle the case where the user changes some parameter many times very quickly (for instance, changing gravity through a slider, which sends changes continuously)? Wouldn't I be creating and accumulating a potentially large number of NSInvocationOperation objects in the operation queue?

Likewise, task 2 (running the simulation engine) should be done in a thread of its own, but I again suspect that it should be implemented either as an NSInvocationOperation or the simulation engine itself should be implemented as a custom subclass of an NSOperation. Which one is the recommended approach here?

Task 3, passing the simulation results to the drawing engine is similar to task 1, but it feels more natural to me that the results should be broadcast through a notification. Do (non-distributed) notifications always run in the main thread? Should I drop the notification idea and do something similar to task 1? I suppose I could do as in task 1 by having the simulation engine pass the results to the custom NSView object through an NSInvocationOperation that is dependent on the drawing having been completed.

Finally, task 4 (drawing the results) is similar to task 2.

After putting these thoughts down in writing, I realized that I really like the idea of using NSInvocationOperation and/or NSOperation, since it looks easy and it also lets me set dependencies so that the engine doesn't accept changes to its parameters until it's done with one full simulation cycle and the drawing doesn't accept new results until it's done with one full screen update.

Is this the right idea? Does anyone have a better suggestion? Are there any pitfalls that I'm not seeing? One concern I have is that there might be some weird interactions between running the simulation and drawing the results due to the fact that the simulation engine is running on a timer and the drawing engine is running on another timer, and their periods might not be commensurate.

Thanks in advance for any help and apologies for the long message.

Wagner
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to