diff --git a/associate.mm b/associate.mm index 9cee7b8f..8a3e4e55 100644 --- a/associate.mm +++ b/associate.mm @@ -54,6 +54,11 @@ * @syncronize(). */ mutex_t lock; + /** + * Lock guarding the structure of the list. Only the first reference list + * in a chain uses it. + */ + ThinLock structureLock; /** * Array of references. */ @@ -135,12 +140,14 @@ static void setReference(struct reference_list *list, case OBJC_ASSOCIATION_ASSIGN: break; } - // While inserting into the list, we need to lock it temporarily. + // While inserting into the list, we need to lock it temporarily. An + // existing reference is updated in place. struct reference *r = findReference(list, key); + if (NULL == r) { - auto lock = acquire_locks_for_pointers(list); - // If there's an existing reference, then we can update it, otherwise we - // have to install a new one + std::lock_guard lock{list->structureLock}; + // Another thread may have installed this key since the search above. + r = findReference(list, key); if (NULL == r) { // Search for an unused slot