Index: src/runtime/association.m ================================================================== --- src/runtime/association.m +++ src/runtime/association.m @@ -16,28 +16,29 @@ #include "config.h" #import "ObjFWRT.h" #import "private.h" -#ifdef OF_HAVE_THREADS -# import "OFPlainMutex.h" -# define numSpinlocks 8 /* needs to be a power of 2 */ -static OFSpinlock spinlocks[numSpinlocks]; - -static OF_INLINE size_t -spinlockSlot(id object) -{ - return ((size_t)((uintptr_t)object >> 4) & (numSpinlocks - 1)); -} -#endif - struct Association { id object; objc_associationPolicy policy; }; -static struct objc_hashtable *hashtable; +#ifdef OF_HAVE_THREADS +# define numSlots 8 /* needs to be a power of 2 */ +# import "OFPlainMutex.h" +static OFSpinlock spinlocks[numSlots]; +#else +# define numSlots 1 +#endif +static struct objc_hashtable *hashtables[numSlots]; + +static OF_INLINE size_t +slotForObject(id object) +{ + return ((size_t)((uintptr_t)object >> 4) & (numSlots - 1)); +} static uint32_t hash(const void *object) { return (uint32_t)(uintptr_t)object; @@ -49,26 +50,24 @@ return (object1 == object2); } OF_CONSTRUCTOR() { - hashtable = objc_hashtable_new(hash, equal, 2); - + for (size_t i = 0; i < numSlots; i++) { + hashtables[i] = objc_hashtable_new(hash, equal, 2); #ifdef OF_HAVE_THREADS - for (size_t i = 0; i < numSpinlocks; i++) if (OFSpinlockNew(&spinlocks[i]) != 0) OBJC_ERROR("Failed to create spinlocks!"); #endif + } } void objc_setAssociatedObject(id object, const void *key, id value, objc_associationPolicy policy) { -#ifdef OF_HAVE_THREADS size_t slot; -#endif switch (policy) { case OBJC_ASSOCIATION_ASSIGN: break; case OBJC_ASSOCIATION_RETAIN: @@ -82,25 +81,26 @@ default: /* Don't know what to do, so do nothing. */ return; } -#ifdef OF_HAVE_THREADS - slot = spinlockSlot(object); + slot = slotForObject(object); +#ifdef OF_HAVE_THREADS if (OFSpinlockLock(&spinlocks[slot]) != 0) OBJC_ERROR("Failed to lock spinlock!"); @try { #endif struct objc_hashtable *objectHashtable; struct Association *association; - objectHashtable = objc_hashtable_get(hashtable, object); + objectHashtable = objc_hashtable_get(hashtables[slot], object); if (objectHashtable == NULL) { objectHashtable = objc_hashtable_new(hash, equal, 2); - objc_hashtable_set(hashtable, object, objectHashtable); + objc_hashtable_set(hashtables[slot], object, + objectHashtable); } association = objc_hashtable_get(objectHashtable, key); if (association != NULL) { switch (association->policy) { @@ -132,22 +132,22 @@ } id objc_getAssociatedObject(id object, const void *key) { -#ifdef OF_HAVE_THREADS - size_t slot = spinlockSlot(object); + size_t slot = slotForObject(object); +#ifdef OF_HAVE_THREADS if (OFSpinlockLock(&spinlocks[slot]) != 0) OBJC_ERROR("Failed to lock spinlock!"); @try { #endif struct objc_hashtable *objectHashtable; struct Association *association; - objectHashtable = objc_hashtable_get(hashtable, object); + objectHashtable = objc_hashtable_get(hashtables[slot], object); if (objectHashtable == NULL) return nil; association = objc_hashtable_get(objectHashtable, key); if (association == NULL) @@ -169,21 +169,21 @@ } void objc_removeAssociatedObjects(id object) { -#ifdef OF_HAVE_THREADS - size_t slot = spinlockSlot(object); + size_t slot = slotForObject(object); +#ifdef OF_HAVE_THREADS if (OFSpinlockLock(&spinlocks[slot]) != 0) OBJC_ERROR("Failed to lock spinlock!"); @try { #endif struct objc_hashtable *objectHashtable; - objectHashtable = objc_hashtable_get(hashtable, object); + objectHashtable = objc_hashtable_get(hashtables[slot], object); if (objectHashtable == NULL) return; for (uint32_t i = 0; i < objectHashtable->size; i++) { struct Association *association; @@ -207,13 +207,14 @@ } free(association); } - objc_hashtable_delete(hashtable, object); + objc_hashtable_delete(hashtables[slot], object); + objc_hashtable_free(objectHashtable); #ifdef OF_HAVE_THREADS } @finally { if (OFSpinlockUnlock(&spinlocks[slot]) != 0) OBJC_ERROR("Failed to unlock spinlock!"); } #endif }