/// <summary> /// Assigns a hash code to the object in a thread-safe way. /// </summary> private static unsafe int AssignHashCode(int *pHeader) { int newHash = RuntimeHelpers.GetNewHashCode() & MASK_HASHCODE_INDEX; int bitAndValue; // Never use the zero hash code. SyncTable treats the zero value as "not assigned". if (newHash == 0) { newHash = 1; } while (true) { int oldBits = Volatile.Read(ref *pHeader); bitAndValue = oldBits & (BIT_SBLK_IS_HASHCODE | MASK_HASHCODE_INDEX); if (bitAndValue != 0) { // The header already stores some value break; } // The header stores nothing. Try to store the hash code. int newBits = oldBits | BIT_SBLK_IS_HASHCODE | newHash; if (Interlocked.CompareExchange(ref *pHeader, newBits, oldBits) == oldBits) { return(newHash); } // Another thread modified the header; try again } if ((bitAndValue & BIT_SBLK_IS_HASHCODE) == 0) { // Set the hash code in SyncTable. This call will resolve the potential race. return(SyncTable.SetHashCode(bitAndValue, newHash)); } // Another thread set the hash code, use it Debug.Assert((bitAndValue & ~BIT_SBLK_IS_HASHCODE) != 0); return(bitAndValue & ~BIT_SBLK_IS_HASHCODE); }