> On 1 May 2015, at 10:18 am, Quincey Morris 
> <quinceymor...@rivergatesoftware.com> wrote:
> 
> On Apr 30, 2015, at 16:39 , Graham Cox <graham....@bigpond.com> wrote:
>> 
>> As I mentioned it’s the spinning busy indicator, which is always 
>> indeterminate.
> 
> The circular style isn’t always indeterminate, though (I forgot) it looks 
> different when it’s not indeterminate.

Well, the docs say:

> This method only has an effect if style returns NSProgressIndicatorBarStyle. 
> If style returns NSProgressIndicatorSpinningStyle, the indicator is always 
> indeterminate, regardless of what you pass to this method.

However, I’m now fairly convinced that this is a red herring, and is a side 
effect of the more serious bug.

> 
> My app also hits a breakpoint at _dispatch_semaphore_wait_slow when I click 
> on a menu bar menu, also in the middle of talking to another process via XPC, 
> so I don’t think that’s a cause of your problem.
> 
> Instead, I suspect you have a memory management error that’s corrupting 
> something. Or a thread safety error that’s causing this as a side effect.


I’m starting to think that as well.

I’m using ARC - I keep trying to get on board with ARC, and every time I do I 
seem to run into this sort of difficult to track down issue. At this stage I’ll 
try and persist with it, because I’m not getting any problems when I use any of 
the memory managment debugging aids such as zombies and guard malloc, etc. So 
perhaps as you suggest it’s more of a thread safety issue. I can well believe 
it could be, as I’m just exploring using NSOperationQueue for this kind of 
processing, and maybe I’ve just done it wrong.

The app here is only an experiment - if I can get it to work properly it’ll be 
useful experience that I can apply to other situations. So I’m drawing a 
portion of the Mandelbrot set in a view. I tile the view into a number of tiles 
and each one is given the appropriate coordinates and goes away and does the 
calculation work in a block added to an NSOperationQueue. Plotting the 
Mandelbrot set is a good experiment because it is eminently parallisable 
without any co-dependencies between tiles - it just needs to keep track of 
which part of the overall view it belongs to.

When the calculation for a tile is finished, it calls its delegate to tell it 
it has finished. The delegate is the original view. I use 
-performSelectorOnMainThread: to notify the delegate. In response, it takes a 
bitmap that the tile created and filled in, and draws it in the view (well, 
it’s a little more complex. When the delegate of the tile gets the ‘finished’ 
notification, it adds the tile to a dictionary of tiles that can be drawn, 
keyed by a string version of the tile’s coordinates, then it calls 
-setNeedsDisplayInRect: for that tile. When -drawRect is called, it iterates 
through the dictionary drawing tiles that intersect the dirty region of the 
view.) That all works fine - as each tile completes, I see the view plot that 
tile, so gradually the view fills with the complete image.

Pursuing the corruption/thread safety angle, if I set it to just use 1 tile for 
the view, all is well. The spinner spins and the menubar doesn’t block. If I go 
to 2x2 tiles, it’s still OK. Any more than that and the menubar click blocks 
the main thread and the spinner doesn’t animate. Thus the problem is sensitive 
to the number of tasks I add to the NSOperationQueue.

The code that schedules the work is:

        if( !self.busy )
        {
                mBusy = YES;
                
                [[[self class] mandelGeneratorQueue] addOperationWithBlock:^
                {
                        [self createBitmapIfNeeded];
                        
                        if([self.delegate 
respondsToSelector:@selector(mandelGeneratorWillStartCalculation:)])
                                [self.delegate 
performSelectorOnMainThread:@selector(mandelGeneratorWillStartCalculation:) 
withObject:self waitUntilDone:NO];
                        
                        NSUInteger              x, y, xm, ym;
                        size_t                  index;
                        NSRect                  dr = self.destinationRect;
                        
                        x = xm = NSWidth( dr );
                        y = ym = NSHeight( dr );

                        while( y-- )
                        {
                                x = xm;
                                
                                while( x-- )
                                {
                                        CGFloat ev = [self 
calculateEscapeValueAtX:x y:y];
                                        [self plotEscapeValue:ev atX:x y:y];
                                }
                        }
                        
                        mBusy = NO;

                        if([self.delegate 
respondsToSelector:@selector(mandelGeneratorDidFinishCalculation:)])
                                [self.delegate 
performSelectorOnMainThread:@selector(mandelGeneratorDidFinishCalculation:) 
withObject:self waitUntilDone:NO];
                }];
        }


If I replace the work done in the inner loop with usleep( 10 ), I still see the 
same problem, so whatever the cause of the issue it isn’t a fault with the 
actual Mandelbrot calculation, but with the whole tile plotting on a thread 
architecture.

Stumped.

—GRaham












_______________________________________________

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to