Re: Synchronizing Thread Execution
Re: Synchronizing Thread Execution
- Subject: Re: Synchronizing Thread Execution
- From: Antonio Nunes <email@hidden>
- Date: Mon, 4 Dec 2006 14:14:54 +0000
On 3 Dec 2006, at 23:23, Chris Suter wrote:
I have instances of a class that can be called from two threads at
"the same time". For one method I need to ensure it is only
executed by one thread at a time, regardless of which instance of
the class is being called, and from which thread. Am I correct
that using "@synchronized(NSStringFromSelector(_cmd))" would
provide precisely this guarantee?
Yes, it would seem so.
That's what I thought too, but after some experimentation it doesn't
seem to work, or I am misunderstanding what it means. Using the above
expression it seems the objects are being modified from somewhere
else while we are in the critical region. Using @synchronized(self)
this doesn't happen. But this last expression still doesn't provide
enough protection:
The issue is that I have a possibly large number of objects which all
reference the same PDFDocument in a cache. A background thread is
spun from the main thread calling each object in turn to convert the
cache into something derived from the PDFDocument. This serialized
operation in itself is fine. The complication is that when the main
thread calls a document window's drawRect method, the drawing code
will call the same objects to draw, and if the cache has not been
converted yet for an object that will trigger the conversion routine
which accesses the PDFDocument from the main thread, re-entering the
PDFDocument. This PDFDocument doesn't like and it usually results in
severe errors. Much of this is prevented by wrapping @synchronized
(self) around the critical region. At least then the two threads
cannot simultaneously access the same object. But this is not enough,
since several objects may reference the same PDFDocument and hence it
may still be accessed from two threads simultaneously. I had hoped
that using @synchronized(NSStringFromSelector(_cmd)) would further
prevent this by only allowing one thread at a time access to this
method. Yet, I ended up getting more errors; in fact things started
going consistently wrong now, whereas with @synchronized(self) things
were mostly OK (at least on single processor/core machines, on
multiple processor/core machines the errors are more frequent).
After posting this question last night, I thought I'd try to make the
conversion triggering thread block while the main thread is drawing.
That *should* avoid the issue of the PDFDocument being re-entered. So
I tried the following:
- (NSLock *)blockConversion; <=instance variable of the NSView subclass
- (void)drawRect:(NSRect)rect {
[blockConversion lock];
// Do some drawing stuff
[blockConversion unlock];
}
Background thread spun from the main thread after importing a PDF
document:
- (void)convertPDFSourceObjectCaches:(NSArray *)objects
{
…
while ((sourceObject = [e nextObject]) && !_isSaving && !_isClosing) {
…
if ([sourceObject owner]) {
[[layoutView blockConversion] lock];
[sourceObject convertCacheToPDFDoc];
[[layoutView blockConversion] unlock];
}
}
…
}
The idea is that drawRect will draw if convertPDFSourceObjectCaches
hasn't triggered a cache conversion, and convertPDFSourceObjectCaches
will convert an object's cache only if no drawing is taking place.
But this turns out to be susceptible to (I think) racing conditions
since the both threads block when running this setup, or at any rate,
the UI freezes.
So I changed drawRect to this:
- (void)drawRect:(NSRect)rect {
[blockConversion tryLock];
…
This avoids the blocking and the background thread will only execute
when no drawing is taking place. Yet there is still a chance that
when drawRect is called the background thread has not yet finished an
ongoing conversion so we might still have a problem.
How then to solve this? Would I be better off with a condition lock?
And how would I implement that?
-António
-----------------------------------------
Forgiveness is the perfume
that the trampled flower casts
upon the heel that crushes it.
-----------------------------------------
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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