Need some advice on multithreading
Need some advice on multithreading
- Subject: Need some advice on multithreading
- From: WT <email@hidden>
- Date: Mon, 24 Nov 2008 01:06:17 +0100
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 (email@hidden)
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:
This email sent to email@hidden