Re: drawing in a separate thread
Re: drawing in a separate thread
- Subject: Re: drawing in a separate thread
- From: Jean-Daniel Dupas <email@hidden>
- Date: Fri, 2 May 2008 13:20:23 +0200
You can have a look at DistributedObject. I think you can publish a
drawer object in your drawing thread and then, just call draw fro your
main thread.
To be more generic, a worker thread may do this:
- start and setup thread.
- create IPC objects. (publish an object using Distributed object for
example)
- wait and dispatch messages. ([[NSRunLoop currentRunLoop] run]);
- release resources.
- end.
Le 2 mai 08 à 13:07, Graham Cox a écrit :
On 2 May 2008, at 6:13 pm, Kyle Sluder wrote:
On Fri, May 2, 2008 at 3:13 AM, Graham Cox <email@hidden>
wrote:
I realise these questions must sound rather fundamental, but
nothing in the
Cocoa Drawing Guide or Thread Guide really addresses them. I have
used
threads before to perform tasks not involving drawing, so I'm not
completely
unfamiliar with them, but I haven't tried drawing on a secondary
thread
before.
The reason these questions aren't addressed in the guide is because
they are highly dependent on just what you are doing. Only you can
determine when something needs to be updated.
Well the current single-threaded app already does all of that, and
so I end up with setNeedsDisplayInRect: calls being made to the view
as usual. Then I get a drawRect: to draw whatever accumulated on the
previous loop. It's the actual rendering that I'm hoping to offload
onto another thread - and so use a separate core, leaving the main
thread to continue handling user input which *should* make the app
feel faster even though the amount of drawing going on is the same
(Corollary question: does Quartz thread any of its drawing anyway?
Maybe there's no advantage in this if it does).
I found this old posting by John C Randolph:
"In a multithreaded application, the main thread is still responsible
for redisplaying dirty views through the same process as a
single-threaded application. The drawRect: method of every dirty view
is called in the main thread. If the drawing needs to be done in
another thread, the drawRect: method for the view should arrange for
the secondary thread to do the drawing and not do any drawing in
drawRect:."
So what I guess needs to happen is that when the view gets a
drawRect: call it needs to flag to the secondary thread that it
should go ahead and perform the redraw, instead of doing it
synchronously itself, so something like:
- (void) drawRect:(NSRect) updateRect
{
if( threaded )
[thread doDrawingWithRect:updateRect inView:self]; // thread wakes
up and calls [view doDrawingWithRect:] then sleeps
else
[self doDrawingWithRect:updateRect]; // standard synchronous drawing
}
All of my drawing is completely within the rules, in that it's
performed within drawRect:, and any updates needed end up in
setNeedsDisplayInRect:, so it seems to me that the drawing in the
second thread should be straightforward enough (and also easy to
switch between the two "modes" of operation). At this stage I
consider it an experiment to see what the benefits or difficulties
might be.
As for spawning multiple threads, you want your drawing to be
performed really quickly. I would strongly advocate keeping a thread
around for the life of your view and having it sit an a loop that
ends
with it performing a blocking read on some IPC port. That way it
gets
scheduled off the processor but you don't suffer the thread-creation
or -destruction penalty every time you perform a draw.
From what you're saying, I should have a worker thread that waits
for a request to draw, do the drawing, then go back to sleep until
next time. What isn't clear is if this thread should be per-view, or
used by all views that work this way, and how exactly it should be
flagged to do the drawing (and all the sleep issues, etc). I'm not
sure what an IPC port is (I will look it up) but I get the general
idea. If you can point me in the right direction to answer some of
these, I'm happy to experiment with what's needed on the drawing
side of things (and I'm hoping it's relatively little different from
the single-threaded case).
So my question at this stage isn't about drawing but about setting
up and controlling the worker thread, (I think).
Drawing from a secondary thread isn't an easy task, so perhaps you
might want to consider whether it's possible to avoid doing so.
Maybe
you can draw into an image on the secondary thread, and then when
necessary use -performSelectorOnMainThread:withObject:waitUntilDone:
to send the view a -setNeedsDisplay: message when after your thread
has completed its drawing. Then the view can overwrite its own
buffer
with it. Be careful of synchronization issues, of course.
HTH,
--Kyle Sluder
_______________________________________________
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
_______________________________________________
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