Array-index based devPrivates implementation.

Note: DevPrivateKey is now pointer-to-int, which means
each key now needs to point to some global storage of
size at least sizeof(int).
This commit is contained in:
Eamon Walsh 2008-09-12 19:11:53 -04:00
parent 999f3362d5
commit b6ab114212
2 changed files with 108 additions and 101 deletions

View File

@ -40,9 +40,8 @@ from The Open Group.
#include "inputstr.h" #include "inputstr.h"
struct _Private { struct _Private {
DevPrivateKey key; int state;
pointer value; pointer value;
struct _Private *next;
}; };
typedef struct _PrivateDesc { typedef struct _PrivateDesc {
@ -50,22 +49,36 @@ typedef struct _PrivateDesc {
unsigned size; unsigned size;
CallbackListPtr initfuncs; CallbackListPtr initfuncs;
CallbackListPtr deletefuncs; CallbackListPtr deletefuncs;
struct _PrivateDesc *next;
} PrivateDescRec; } PrivateDescRec;
/* list of all allocated privates */ #define PRIV_MAX 256
static PrivateDescRec *items = NULL; #define PRIV_STEP 16
static _X_INLINE PrivateDescRec * /* list of all allocated privates */
static PrivateDescRec items[PRIV_MAX];
static int nextPriv;
static PrivateDescRec *
findItem(const DevPrivateKey key) findItem(const DevPrivateKey key)
{ {
PrivateDescRec *item = items; if (!*key) {
while (item) { if (nextPriv >= PRIV_MAX)
if (item->key == key) return NULL;
return item;
item = item->next; items[nextPriv].key = key;
*key = nextPriv;
nextPriv++;
} }
return NULL;
return items + *key;
}
static _X_INLINE int
privateExists(PrivateRec **privates, const DevPrivateKey key)
{
return *key && *privates &&
(*privates)[0].state > *key &&
(*privates)[*key].state;
} }
/* /*
@ -75,21 +88,10 @@ _X_EXPORT int
dixRequestPrivate(const DevPrivateKey key, unsigned size) dixRequestPrivate(const DevPrivateKey key, unsigned size)
{ {
PrivateDescRec *item = findItem(key); PrivateDescRec *item = findItem(key);
if (item) { if (!item)
if (size > item->size) return FALSE;
item->size = size; if (size > item->size)
} else {
item = (PrivateDescRec *)xalloc(sizeof(PrivateDescRec));
if (!item)
return FALSE;
memset(item, 0, sizeof(PrivateDescRec));
/* add privates descriptor */
item->key = key;
item->size = size; item->size = size;
item->next = items;
items = item;
}
return TRUE; return TRUE;
} }
@ -100,25 +102,52 @@ _X_EXPORT pointer *
dixAllocatePrivate(PrivateRec **privates, const DevPrivateKey key) dixAllocatePrivate(PrivateRec **privates, const DevPrivateKey key)
{ {
PrivateDescRec *item = findItem(key); PrivateDescRec *item = findItem(key);
PrivateCallbackRec calldata;
PrivateRec *ptr; PrivateRec *ptr;
unsigned size = sizeof(PrivateRec); pointer value;
int oldsize, newsize;
if (item) newsize = (*key / PRIV_STEP + 1) * PRIV_STEP;
size += item->size;
ptr = (PrivateRec *)xcalloc(size, 1); /* resize or init privates array */
if (!ptr) if (!item)
return NULL; return NULL;
ptr->key = key;
ptr->value = (size > sizeof(PrivateRec)) ? (ptr + 1) : NULL;
ptr->next = *privates;
*privates = ptr;
/* call any init funcs and return */ /* initialize privates array if necessary */
if (item) { if (!*privates) {
PrivateCallbackRec calldata = { key, &ptr->value }; ptr = xcalloc(newsize, sizeof(*ptr));
CallCallbacks(&item->initfuncs, &calldata); if (!ptr)
return NULL;
*privates = ptr;
(*privates)[0].state = newsize;
} }
oldsize = (*privates)[0].state;
/* resize privates array if necessary */
if (*key >= oldsize) {
ptr = xrealloc(*privates, newsize * sizeof(*ptr));
if (!ptr)
return NULL;
memset(ptr + oldsize, 0, (newsize - oldsize) * sizeof(*ptr));
*privates = ptr;
(*privates)[0].state = newsize;
}
/* initialize slot */
ptr = *privates + *key;
ptr->state = 1;
if (item->size) {
value = xcalloc(item->size, 1);
if (!value)
return NULL;
ptr->value = value;
}
calldata.key = key;
calldata.value = &ptr->value;
CallCallbacks(&item->initfuncs, &calldata);
return &ptr->value; return &ptr->value;
} }
@ -128,14 +157,10 @@ dixAllocatePrivate(PrivateRec **privates, const DevPrivateKey key)
_X_EXPORT pointer _X_EXPORT pointer
dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key) dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key)
{ {
PrivateRec *rec = *privates;
pointer *ptr; pointer *ptr;
while (rec) { if (privateExists(privates, key))
if (rec->key == key) return (*privates)[*key].value;
return rec->value;
rec = rec->next;
}
ptr = dixAllocatePrivate(privates, key); ptr = dixAllocatePrivate(privates, key);
return ptr ? *ptr : NULL; return ptr ? *ptr : NULL;
@ -147,13 +172,8 @@ dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key)
_X_EXPORT pointer * _X_EXPORT pointer *
dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key) dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key)
{ {
PrivateRec *rec = *privates; if (privateExists(privates, key))
return &(*privates)[*key].value;
while (rec) {
if (rec->key == key)
return &rec->value;
rec = rec->next;
}
return dixAllocatePrivate(privates, key); return dixAllocatePrivate(privates, key);
} }
@ -164,16 +184,10 @@ dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key)
_X_EXPORT int _X_EXPORT int
dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val) dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val)
{ {
PrivateRec *rec;
top: top:
rec = *privates; if (privateExists(privates, key)) {
while (rec) { (*privates)[*key].value = val;
if (rec->key == key) { return TRUE;
rec->value = val;
return TRUE;
}
rec = rec->next;
} }
if (!dixAllocatePrivate(privates, key)) if (!dixAllocatePrivate(privates, key))
@ -187,27 +201,23 @@ dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val)
_X_EXPORT void _X_EXPORT void
dixFreePrivates(PrivateRec *privates) dixFreePrivates(PrivateRec *privates)
{ {
PrivateRec *ptr, *next; int i;
PrivateDescRec *item;
PrivateCallbackRec calldata; PrivateCallbackRec calldata;
/* first pass calls the delete callbacks */ if (privates)
for (ptr = privates; ptr; ptr = ptr->next) { for (i = 1; i < privates->state; i++)
item = findItem(ptr->key); if (privates[i].state) {
if (item) { /* call the delete callbacks */
calldata.key = ptr->key; calldata.key = items[i].key;
calldata.value = &ptr->value; calldata.value = &privates[i].value;
CallCallbacks(&item->deletefuncs, &calldata); CallCallbacks(&items[i].deletefuncs, &calldata);
}
}
/* second pass frees the memory */ /* free pre-allocated memory */
ptr = privates; if (items[i].size)
while (ptr) { xfree(privates[i].value);
next = ptr->next; }
xfree(ptr);
ptr = next; xfree(privates);
}
} }
/* /*
@ -218,11 +228,9 @@ dixRegisterPrivateInitFunc(const DevPrivateKey key,
CallbackProcPtr callback, pointer data) CallbackProcPtr callback, pointer data)
{ {
PrivateDescRec *item = findItem(key); PrivateDescRec *item = findItem(key);
if (!item) { if (!item)
if (!dixRequestPrivate(key, 0)) return FALSE;
return FALSE;
item = findItem(key);
}
return AddCallback(&item->initfuncs, callback, data); return AddCallback(&item->initfuncs, callback, data);
} }
@ -231,11 +239,9 @@ dixRegisterPrivateDeleteFunc(const DevPrivateKey key,
CallbackProcPtr callback, pointer data) CallbackProcPtr callback, pointer data)
{ {
PrivateDescRec *item = findItem(key); PrivateDescRec *item = findItem(key);
if (!item) { if (!item)
if (!dixRequestPrivate(key, 0)) return FALSE;
return FALSE;
item = findItem(key);
}
return AddCallback(&item->deletefuncs, callback, data); return AddCallback(&item->deletefuncs, callback, data);
} }
@ -292,16 +298,17 @@ dixLookupPrivateOffset(RESTYPE type)
int int
dixResetPrivates(void) dixResetPrivates(void)
{ {
PrivateDescRec *next; int i;
/* reset internal structures */ /* reset private descriptors */
while (items) { for (i = 1; i < nextPriv; i++) {
next = items->next; *items[i].key = 0;
DeleteCallbackList(&items->initfuncs); DeleteCallbackList(&items[i].initfuncs);
DeleteCallbackList(&items->deletefuncs); DeleteCallbackList(&items[i].deletefuncs);
xfree(items);
items = next;
} }
nextPriv = 1;
/* reset offsets */
if (offsets) if (offsets)
xfree(offsets); xfree(offsets);
offsetsSize = sizeof(offsetDefaults); offsetsSize = sizeof(offsetDefaults);

View File

@ -19,7 +19,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
* STUFF FOR PRIVATES * STUFF FOR PRIVATES
*****************************************************************/ *****************************************************************/
typedef void *DevPrivateKey; typedef int *DevPrivateKey;
struct _Private; struct _Private;
typedef struct _Private PrivateRec; typedef struct _Private PrivateRec;