fix and document iarray
This commit is contained in:
parent
5baf943f0a
commit
f3c0e69988
@ -18,24 +18,35 @@ static iarray_page* new_page(size_t pagesize) {
|
|||||||
|
|
||||||
void* iarray_allocate(iarray* ia,size_t pos) {
|
void* iarray_allocate(iarray* ia,size_t pos) {
|
||||||
size_t index,prevlen=ia->len;
|
size_t index,prevlen=ia->len;
|
||||||
|
/* first, find the linked list of pages */
|
||||||
iarray_page** p=&ia->pages[pos%(sizeof(ia->pages)/sizeof(ia->pages[0]))];
|
iarray_page** p=&ia->pages[pos%(sizeof(ia->pages)/sizeof(ia->pages[0]))];
|
||||||
|
/* this is here so we don't munmap and then re-mmap pages when a
|
||||||
|
* certain path makes it necessary to mmap several pages into the
|
||||||
|
* linked list and we are competing with another thread that does the
|
||||||
|
* same thing */
|
||||||
iarray_page* newpage=0;
|
iarray_page* newpage=0;
|
||||||
for (index=0; pos<index+ia->elemperpage; index+=ia->elemperpage) {
|
/* since we have a fan-out of 16, on page 0 the elements are 0, 16, 32, ...
|
||||||
|
* so we divide pos by the fan-out here */
|
||||||
|
size_t realpos=pos;
|
||||||
|
pos /= sizeof(ia->pages)/sizeof(ia->pages[0]);
|
||||||
|
/* now walk the linked list of pages until we reach the one we want */
|
||||||
|
for (index=0; ; index+=ia->elemperpage) {
|
||||||
if (!*p) {
|
if (!*p) {
|
||||||
if (!newpage)
|
if (!newpage)
|
||||||
if (!(newpage=new_page(ia->bytesperpage))) return 0;
|
if (!(newpage=new_page(ia->bytesperpage))) return 0;
|
||||||
if (__CAS(p,0,newpage)==0)
|
if (__CAS(p,0,newpage)==0)
|
||||||
newpage=0;
|
newpage=0;
|
||||||
}
|
}
|
||||||
if (index+ia->elemperpage>pos) {
|
if (index+ia->elemperpage>pos)
|
||||||
size_t l;
|
break;
|
||||||
if (newpage) munmap(newpage,ia->bytesperpage);
|
|
||||||
do {
|
|
||||||
l=__CAS(&ia->len,prevlen,pos);
|
|
||||||
} while (l<pos);
|
|
||||||
return &(*p)->data[(pos-index)*ia->elemsize];
|
|
||||||
}
|
|
||||||
p=&(*p)->next;
|
p=&(*p)->next;
|
||||||
}
|
}
|
||||||
return 0; // can't happen
|
if (newpage) munmap(newpage,ia->bytesperpage);
|
||||||
|
{
|
||||||
|
size_t l;
|
||||||
|
do {
|
||||||
|
l=__CAS(&ia->len,prevlen,realpos);
|
||||||
|
} while (l<realpos);
|
||||||
|
}
|
||||||
|
return &(*p)->data[(pos-index)*ia->elemsize];
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
void* iarray_get(iarray* ia,size_t pos) {
|
void* iarray_get(iarray* ia,size_t pos) {
|
||||||
size_t index;
|
size_t index;
|
||||||
iarray_page* p=ia->pages[pos%(sizeof(ia->pages)/sizeof(ia->pages[0]))];
|
iarray_page* p=ia->pages[pos%(sizeof(ia->pages)/sizeof(ia->pages[0]))];
|
||||||
|
pos /= sizeof(ia->pages)/sizeof(ia->pages[0]);
|
||||||
for (index=0; p; p=p->next, index+=ia->elemperpage) {
|
for (index=0; p; p=p->next, index+=ia->elemperpage) {
|
||||||
if (pos>=index && pos<index+ia->elemperpage)
|
if (pos>=index && pos<index+ia->elemperpage)
|
||||||
return &p->data[(pos-index)*ia->elemsize];
|
return &p->data[(pos-index)*ia->elemsize];
|
||||||
|
12
iarray.h
12
iarray.h
@ -17,6 +17,18 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* The basic data structure is a static array of pointers to pages.
|
||||||
|
* Each page also contains a next pointer to form a linked list.
|
||||||
|
* To get to element n, you take n % the number of elements in the
|
||||||
|
* static array (iarray->pages) to get to the list of pages that
|
||||||
|
* contains it. Then keep going to the next page until you are on the
|
||||||
|
* right page.
|
||||||
|
* Note: The elements on each page are not contiguous. If the fanout is
|
||||||
|
* 16, the indices on page 0 are 0, 16, 32, ...
|
||||||
|
* To get to element 0, you'd go to iarray->pages[0].data,
|
||||||
|
* to get to element 1, you'd go to iarray->pages[1].data,
|
||||||
|
* to get to element 16, you'd go to iarray->pages[0].data+iarray->elemsize.
|
||||||
|
*/
|
||||||
typedef struct _iarray_page {
|
typedef struct _iarray_page {
|
||||||
struct _iarray_page* next;
|
struct _iarray_page* next;
|
||||||
char data[];
|
char data[];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user