More fixes - hopefully fixed for real now

This commit is contained in:
Airy ANDRE 2013-05-24 17:54:32 +02:00
parent 8af05dd142
commit 84b18af68b

View File

@ -15,7 +15,8 @@ typedef struct {
objc_AssociationPolicy policy;
} AssociationObjectEntry;
#define AssociationObjectEntrySize 4
#define BucketsInitialSize 509 // Some prime size (and as a bonus, next three n*2+1 are prime too)
#define AssociationObjectEntrySize 5
#define HASHPTR(p) (((unsigned int)p)>>5)
@ -31,18 +32,11 @@ typedef struct AssociationTable {
AssociationHashBucket **buckets;
} AssociationTable;
typedef struct {
AssociationTable *table;
unsigned int i;
struct AssociationHashBucket *j;
} NSHashEnumerator;
AssociationTable *CreateAssociationTable(unsigned int capacity) {
AssociationTable *table=malloc(sizeof(AssociationTable));
table->count=0;
table->nBuckets=(capacity<4)?4:capacity;
table->nBuckets=(capacity<5)?5:capacity;
table->buckets=calloc(table->nBuckets,sizeof(AssociationHashBucket *));
return table;
@ -65,31 +59,48 @@ void AssociationTableInsert(AssociationTable *table,id key, AssociationObjectEnt
unsigned int i=hash%table->nBuckets;
AssociationHashBucket *j;
for(j=table->buckets[i];j!=NULL;j=j->next)
for(j=table->buckets[i];j!=NULL;j=j->next) {
if(j->key==key){
id oldKey=j->key;
AssociationObjectEntry *oldValue=j->value;
j->key=key;
j->value=value;
j->value=value;
free(oldValue);
return;
}
if(table->count>=table->nBuckets){
}
int newSize = 0;
if (table->count>=table->nBuckets) {
// Expand the buckets size to limit collisions
newSize=table->nBuckets*2+1; // Let"s use odd size
} else if (table->count > BucketsInitialSize && table->count < table->nBuckets/2) {
// Compact the table - plenty of free room
newSize=table->nBuckets/2;
if (newSize%2) {
// Let"s use odd size
newSize+=1;
}
}
if(newSize != 0){
unsigned int nBuckets=table->nBuckets;
AssociationHashBucket **buckets=table->buckets,*next;
AssociationHashBucket **buckets=table->buckets;
table->nBuckets=nBuckets*2;
table->nBuckets=newSize;
table->buckets=calloc(table->nBuckets,sizeof(AssociationHashBucket *));
for(i=0;i<nBuckets;i++)
for(j=buckets[i];j!=NULL;j=next){
unsigned int newi=HASHPTR(key)%table->nBuckets;
// Get all of the existing buckets and place them into the new list
for(i=0;i<nBuckets;i++) {
j = buckets[i];
while (j) {
unsigned int newi=HASHPTR(j->key)%table->nBuckets;
next=j->next;
AssociationHashBucket *next = j->next;
j->next=table->buckets[newi];
table->buckets[newi]=j;
j = next;
}
}
free(buckets);
i=hash%table->nBuckets;
}
@ -156,7 +167,7 @@ void AssociationTableRemove(AssociationTable *table,id key){
AssociationObjectEntry *entry = j->value;
for (int i = 0; i < AssociationObjectEntrySize; i++) {
AssociationObjectEntry *e = (AssociationObjectEntry *)entry + i;
AssociationObjectEntry *e = entry + i;
while (e) {
switch (e->policy) {
case OBJC_ASSOCIATION_ASSIGN:
@ -176,9 +187,12 @@ void AssociationTableRemove(AssociationTable *table,id key){
objectsToRelease[releaseCount++] = e->object;
break;
}
void *prevEntry = e;
AssociationObjectEntry *currentEntry = e;
e = e->nextEntry;
free(prevEntry);
// Don't free the first entry of the list - it's part of the "entry" block that will be freed after the loop
if (currentEntry != entry + i) {
free(currentEntry);
}
}
}
@ -215,7 +229,7 @@ void objc_setAssociatedObject(id object, const void *key, id value, objc_Associa
AssociationSpinLockLock(&AssociationLock);
if (associationTable == NULL) {
associationTable = CreateAssociationTable(512);
associationTable = CreateAssociationTable(BucketsInitialSize);
}
AssociationObjectEntry *objectTable = AssociationTableGet(associationTable, object);