Re: dispatch_apply() on an NSArray and Thread Sanitizer

2022-04-19 Thread Sean McBride via Cocoa-dev
On 19 Apr 2022, at 19:35, Rob Petrovec wrote:

> The docs for NSEnumerationConcurrent state that it is a hint and may be 
> ignored at run time.

Ah, so they do.  I had only checked in the header file.

OK, one less mystery.

Sean
___

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


Re: dispatch_apply() on an NSArray and Thread Sanitizer

2022-04-19 Thread Rob Petrovec via Cocoa-dev


> On Apr 19, 2022, at 5:26 PM, Sean McBride via Cocoa-dev 
>  wrote:
> 
> On 19 Apr 2022, at 18:47, Saagar Jha wrote:
> 
>> If Thread Sanitizer says your code has a race, it almost certainly has a 
>> race.
> 
> Yeah, that's been my general experience until now.
> 
>> Your simple code seems OK superficially, but there are a couple things that 
>> could be problematic here: either your real code is actually mutating 
>> something, or (unlikely) you are touching some internal state, perhaps a CoW 
>> optimization, that is not visible to you but is silently changing things 
>> under the hood.
> 
> In case it wasn't clear, the code snippet in my email actually reproduces the 
> issue.  I created a fresh Xcode project and it's literally just:
> 
> - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
>   NSArray* array = @[@5, @6, @7, @8, @9, @10, @11];
>   
>   [array enumerateObjectsWithOptions:NSEnumerationConcurrent 
> usingBlock:^(NSNumber* num, NSUInteger idx, BOOL* stop) {
>   array[idx];
>   }];
> } 
> 
> TSan complains with this on macOS 12.3.1 on an M1 Mac Mini with Xcode 13.3.  
> But on an Intel Mac Pro, macOS 11.6.6 with Xcode 13.2.1, TSan does not 
> complain.
> 
>> In any case, I would generally suggest using -[NSArray 
>> enumerateObjectsAtIndexes:options:usingBlock:] with the 
>> NSEnumerationConcurrent flag, which should rule out any issues with 
>> concurrent access on the array itself.
> 
> I tried enumerateObjectsWithOptions:usingBlock: and TSan doesn't complain 
> with it.  But I was suspicious of that and added an NSLog to print the index, 
> and even after adding random sleeps:
> 
>   [array enumerateObjectsWithOptions:NSEnumerationConcurrent 
> usingBlock:^(NSNumber* nub, NSUInteger idx, BOOL* stop) {
>   usleep(arc4random_uniform(100));
>   NSLog(@"idx: %d", idx);
>   array[idx];
>   }];
> 
> The thing is *not* running concurrently on the M1.  The indices are always 
> printed in order.  Weird.
The docs for NSEnumerationConcurrent state that it is a hint and may be 
ignored at run time.  If you absolutely need it to be run on multiple threads 
you should do it explicitly, IMO, with dispatch_async and appropriate critical 
section locking.

—Rob


___

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


Re: dispatch_apply() on an NSArray and Thread Sanitizer

2022-04-19 Thread Sean McBride via Cocoa-dev

On 19 Apr 2022, at 18:47, Saagar Jha wrote:

If Thread Sanitizer says your code has a race, it almost certainly has 
a race.


Yeah, that's been my general experience until now.

Your simple code seems OK superficially, but there are a couple things 
that could be problematic here: either your real code is actually 
mutating something, or (unlikely) you are touching some internal 
state, perhaps a CoW optimization, that is not visible to you but is 
silently changing things under the hood.


In case it wasn't clear, the code snippet in my email actually 
reproduces the issue.  I created a fresh Xcode project and it's 
literally just:


- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSArray* array = @[@5, @6, @7, @8, @9, @10, @11];

	[array enumerateObjectsWithOptions:NSEnumerationConcurrent 
usingBlock:^(NSNumber* num, NSUInteger idx, BOOL* stop) {

array[idx];
}];
}   

TSan complains with this on macOS 12.3.1 on an M1 Mac Mini with Xcode 
13.3.  But on an Intel Mac Pro, macOS 11.6.6 with Xcode 13.2.1, TSan 
does not complain.


In any case, I would generally suggest using -[NSArray 
enumerateObjectsAtIndexes:options:usingBlock:] with the 
NSEnumerationConcurrent flag, which should rule out any issues with 
concurrent access on the array itself.


I tried enumerateObjectsWithOptions:usingBlock: and TSan doesn't 
complain with it.  But I was suspicious of that and added an NSLog to 
print the index, and even after adding random sleeps:


	[array enumerateObjectsWithOptions:NSEnumerationConcurrent 
usingBlock:^(NSNumber* nub, NSUInteger idx, BOOL* stop) {

usleep(arc4random_uniform(100));
NSLog(@"idx: %d", idx);
array[idx];
}];

The thing is *not* running concurrently on the M1.  The indices are 
always printed in order.  Weird.


Sean
___

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


Re: dispatch_apply() on an NSArray and Thread Sanitizer

2022-04-19 Thread Saagar Jha via Cocoa-dev
If Thread Sanitizer says your code has a race, it almost certainly has a race. 
Your simple code seems OK superficially, but there are a couple things that 
could be problematic here: either your real code is actually mutating 
something, or (unlikely) you are touching some internal state, perhaps a CoW 
optimization, that is not visible to you but is silently changing things under 
the hood. In any case, I would generally suggest using -[NSArray 
enumerateObjectsAtIndexes:options:usingBlock:] with the NSEnumerationConcurrent 
flag, which should rule out any issues with concurrent access on the array 
itself.

Regards,
Saagar Jha

> On Apr 19, 2022, at 14:02, Sean McBride via Cocoa-dev 
>  wrote:
> 
> Hi all,
> 
> If one wants to do something with every item in an NSArray in a concurrent 
> way, is the following safe/correct?
> 
> 
> NSArray* array = @[@5, @6, @7, @8, @9, @10, @11];
>   
> dispatch_apply([array count], DISPATCH_APPLY_AUTO, ^(size_t idx) {
>   id unused = array[idx];
> });
> 
> 
> Here of course I'm not doing anything interesting, just extracting the object 
> from the array.  This is a reduced example.
> 
> On one Mac I have, Thread Sanitizer says there is a data race there.  On 
> another Mac, Thread Sanitizer does not complain.
> 
> My understanding is that this code is correct, and that TSan is wrong to 
> complain, but maybe I'm wrong...
> 
> Thanks,
> 
> Sean
> ___
> 
> 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/saagar%40saagarjha.com
> 
> This email sent to saa...@saagarjha.com

___

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


dispatch_apply() on an NSArray and Thread Sanitizer

2022-04-19 Thread Sean McBride via Cocoa-dev
Hi all,

If one wants to do something with every item in an NSArray in a concurrent way, 
is the following safe/correct?


NSArray* array = @[@5, @6, @7, @8, @9, @10, @11];

dispatch_apply([array count], DISPATCH_APPLY_AUTO, ^(size_t idx) {
id unused = array[idx];
});


Here of course I'm not doing anything interesting, just extracting the object 
from the array.  This is a reduced example.

On one Mac I have, Thread Sanitizer says there is a data race there.  On 
another Mac, Thread Sanitizer does not complain.

My understanding is that this code is correct, and that TSan is wrong to 
complain, but maybe I'm wrong...

Thanks,

Sean
___

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