Note that there are some explanatory texts on larger screens.

plurals
  1. POHow thread-safe is my uniquing code?
    text
    copied!<p>I have a small value class that I create lots of instances of. Often with the same value. This class is used as a kind of identifier, so the main use is comparing instances of this class with each other (via <code>isEqual:</code>). </p> <p>To save some memory and time comparing I keep only unique instances in a <code>NSHashTable</code> and use pointer comparison instead of <code>isEqual:</code>.</p> <p>So my designated initializer looks like this:</p> <pre><code>- initWithStuff: (NSString *)stuff; { self = [super init]; if (!self) return nil; // ... (actual initialisation code omitted) hash = UniquingHashTable(); static OSSpinLock spinlock = OS_SPINLOCK_INIT; OSSpinLockLock( &amp;spinlock ); id member = [hash member: self]; if (member) self = member; else [hash addObject: self]; OSSpinLockUnlock( &amp;spinlock ); return self; } </code></pre> <p><code>UniquingHashTable()</code> returns the global <code>NSHashTable</code> or creates it via <code>[NSHashTable weakObjectsHashTable]</code> if it doesn’t exist yet. The <code>weakObjectsHashTable</code> is the important bit - it stores weak pointers to the objects that automatically get removed once there is no other strong reference to that object. The initialization is thread-safe thanks to <code>dispatch_once</code>.</p> <p>This works fine, peak memory usage is significantly lower and all my test cases still pass. But I am not quite sure if I can rely on pointer-comparison to test for equality. <em>Is there any case or race condition where I get two distinct instances at the same time (so the pointers are different) but they still compare equal by <code>isEqual:</code>?</em></p> <h3>To clarify what I have/want:</h3> <p>Given</p> <pre><code>MyClass *a = [[MyClass alloc] initWithStuff: stringA]; MyClass *b = [[MyClass alloc] initWithStuff: stringB]; </code></pre> <p>we always have</p> <pre><code>[a isEqual: b] == [stringA isEqual: stringB]; </code></pre> <p>This is not changed with the new code.</p> <p>What I am trying to achieve is that also</p> <pre><code>[a isEqual: b] == (a == b) </code></pre> <p>so that I can replace the <code>isEqual:</code> with a faster pointer comparison. (Yes, I measured this, this will be significant).</p> <p>For single threaded code or if I was using a <code>NSMutableSet</code> instead of a weak <code>NSHashTable</code> this always works out. I’m just not sure if there is any race condition so that I can have the case where</p> <pre><code>[a isEqual: b] &amp;&amp; (a != b) </code></pre> <p>is true.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload