void sarray_at_put_safe (struct sarray *array, sidx index, void *element) { if (soffset_decode (index) >= array->capacity) sarray_realloc (array, soffset_decode (index) + 1); sarray_at_put (array, index, element); }
static __inline__ void * sarray_get_safe (struct sarray *array, sidx indx) { if (soffset_decode (indx) < array->capacity) return (void *)sarray_get (array, indx); }
/* sarray_at_put : copies data in such a way as to be thread reader safe. */ void sarray_at_put (struct sarray *array, sidx index, void *element) { #ifdef OBJC_SPARSE3 struct sindex **the_index; struct sindex *new_index; #endif struct sbucket **the_bucket; struct sbucket *new_bucket; #ifdef OBJC_SPARSE3 size_t ioffset; #endif size_t boffset; size_t eoffset; #ifdef PRECOMPUTE_SELECTORS union sofftype xx; xx.idx = index; #ifdef OBJC_SPARSE3 ioffset = xx.off.ioffset; #endif boffset = xx.off.boffset; eoffset = xx.off.eoffset; #else /* not PRECOMPUTE_SELECTORS */ #ifdef OBJC_SPARSE3 ioffset = index/INDEX_CAPACITY; boffset = (index/BUCKET_SIZE)%INDEX_SIZE; eoffset = index%BUCKET_SIZE; #else boffset = index/BUCKET_SIZE; eoffset = index%BUCKET_SIZE; #endif #endif /* not PRECOMPUTE_SELECTORS */ assert (soffset_decode (index) < array->capacity); /* Range check */ #ifdef OBJC_SPARSE3 the_index = &(array->indices[ioffset]); the_bucket = &((*the_index)->buckets[boffset]); #else the_bucket = &(array->buckets[boffset]); #endif if ((*the_bucket)->elems[eoffset] == element) return; /* great! we just avoided a lazy copy */ #ifdef OBJC_SPARSE3 /* First, perform lazy copy/allocation of index if needed */ if ((*the_index) == array->empty_index) { /* The index was previously empty, allocate a new */ new_index = (struct sindex *) objc_malloc (sizeof (struct sindex)); memcpy (new_index, array->empty_index, sizeof (struct sindex)); new_index->version.version = array->version.version; *the_index = new_index; /* Prepared for install. */ the_bucket = &((*the_index)->buckets[boffset]); nindices += 1; } else if ((*the_index)->version.version != array->version.version) { /* This index must be lazy copied */ struct sindex *old_index = *the_index; new_index = (struct sindex *) objc_malloc (sizeof (struct sindex)); memcpy (new_index, old_index, sizeof (struct sindex)); new_index->version.version = array->version.version; *the_index = new_index; /* Prepared for install. */ the_bucket = &((*the_index)->buckets[boffset]); nindices += 1; } #endif /* OBJC_SPARSE3 */ /* next, perform lazy allocation/copy of the bucket if needed */ if ((*the_bucket) == array->empty_bucket) { /* The bucket was previously empty (or something like that), */ /* allocate a new. This is the effect of `lazy' allocation */ new_bucket = (struct sbucket *) objc_malloc (sizeof (struct sbucket)); memcpy ((void *) new_bucket, (const void *) array->empty_bucket, sizeof (struct sbucket)); new_bucket->version.version = array->version.version; *the_bucket = new_bucket; /* Prepared for install. */ nbuckets += 1; } else if ((*the_bucket)->version.version != array->version.version) { /* Perform lazy copy. */ struct sbucket *old_bucket = *the_bucket; new_bucket = (struct sbucket *) objc_malloc (sizeof (struct sbucket)); memcpy (new_bucket, old_bucket, sizeof (struct sbucket)); new_bucket->version.version = array->version.version; *the_bucket = new_bucket; /* Prepared for install. */ nbuckets += 1; } (*the_bucket)->elems[eoffset] = element; }