devPrivates rework: add new interface implementation.

This commit is contained in:
Eamon Walsh 2007-02-23 13:20:43 -05:00 committed by Eamon Walsh
parent 779faccfb7
commit 16f2b8892d
2 changed files with 323 additions and 0 deletions

View File

@ -36,6 +36,7 @@ from The Open Group.
#include "os.h"
#include "windowstr.h"
#include "resource.h"
#include "privates.h"
#include "dixstruct.h"
#include "gcstruct.h"
#include "colormapst.h"
@ -44,6 +45,322 @@ from The Open Group.
#include "inputstr.h"
#include "extnsionst.h"
typedef struct _PrivateDescItem {
int index;
RESTYPE type;
pointer parent;
unsigned size;
CallbackListPtr initfuncs;
CallbackListPtr deletefuncs;
} PrivateDescItemRec, *PrivateDescItemPtr;
/* keeps track of whether resource objects have been created */
static char *instances = NULL;
static RESTYPE instancesSize = 0;
static char anyInstances = 0;
/* list of all allocated privates */
static PrivateDescItemPtr items = NULL;
static unsigned itemsSize = 0;
static unsigned nextPrivateIndex = 0;
/* number of extra slots to add when resizing the tables */
#define PRIV_TAB_INCREMENT 48
/* set in index value for privates registered after resources were created */
#define PRIV_DYN_MASK (1<<30)
/* descriptor item lookup convenience macro */
#define GET_DESCRIPTOR(index) (items + ((index) & (PRIV_DYN_MASK - 1)))
/* type mask convenience macro */
#define TYPE_BITS(type) ((type) & TypeMask)
static _X_INLINE ResourcePtr
findResourceBucket(RESTYPE type, pointer instance) {
ResourcePtr res = *((ResourcePtr *)instance);
while (res->type != type)
res = res->nexttype;
return res;
}
/*
* Request functions; the latter calls the former internally.
*/
_X_EXPORT int
dixRequestPrivate(RESTYPE type, unsigned size, pointer parent)
{
int index = nextPrivateIndex;
/* check if privates descriptor table needs to be resized */
if (nextPrivateIndex >= itemsSize) {
unsigned bytes;
unsigned size = itemsSize;
while (nextPrivateIndex >= size)
size += PRIV_TAB_INCREMENT;
bytes = size * sizeof(PrivateDescItemRec);
items = (PrivateDescItemPtr)xrealloc(items, bytes);
if (!items) {
itemsSize = nextPrivateIndex = 0;
return -1;
}
memset(items + itemsSize, 0,
(size - itemsSize) * sizeof(PrivateDescItemRec));
}
/* figure out if resource instances already exist */
if ((type != RC_ANY && instances[TYPE_BITS(type)]) ||
(type == RC_ANY && anyInstances))
index |= PRIV_DYN_MASK;
/* add privates descriptor */
items[nextPrivateIndex].index = index;
items[nextPrivateIndex].type = type;
items[nextPrivateIndex].parent = parent;
items[nextPrivateIndex].size = size;
nextPrivateIndex++;
return index;
}
_X_EXPORT int
dixRequestSinglePrivate(RESTYPE type, unsigned size, pointer instance)
{
PrivatePtr ptr;
ResourcePtr res = findResourceBucket(type, instance);
int index = dixRequestPrivate(type, size, instance);
if (index < 0)
return index;
ptr = (PrivatePtr)xalloc(sizeof(PrivateRec) + size);
if (!ptr)
return -1;
ptr->index = index;
ptr->value = ptr + 1;
ptr->next = res->privates;
res->privates = ptr;
return index;
}
/*
* Lookup function (some of this could be static inlined)
*/
_X_EXPORT pointer
dixLookupPrivate(RESTYPE type, int index, pointer instance)
{
ResourcePtr res = findResourceBucket(type, instance);
PrivatePtr ptr = res->privates;
PrivateDescItemPtr item;
PrivateCallbackRec calldata;
/* see if private has already been allocated (likely) */
while (ptr) {
if (ptr->index == index)
return ptr->value;
ptr = ptr->next;
}
/* past this point, need to create private on the fly */
/* create the new private */
item = GET_DESCRIPTOR(index);
ptr = (PrivatePtr)xalloc(sizeof(PrivateRec) + item->size);
if (!ptr)
return NULL;
memset(ptr, 0, sizeof(PrivateRec) + item->size);
ptr->index = index;
ptr->value = ptr + 1;
ptr->next = res->privates;
res->privates = ptr;
/* call any init funcs and return */
calldata.value = ptr->value;
calldata.index = index;
calldata.resource = res;
CallCallbacks(&item->initfuncs, &calldata);
return ptr->value;
}
/*
* Callback registration
*/
_X_EXPORT int
dixRegisterPrivateInitFunc(RESTYPE type, int index,
CallbackProcPtr callback, pointer data)
{
return AddCallback(&GET_DESCRIPTOR(index)->initfuncs, callback, data);
}
_X_EXPORT int
dixRegisterPrivateDeleteFunc(RESTYPE type, int index,
CallbackProcPtr callback, pointer data)
{
return AddCallback(&GET_DESCRIPTOR(index)->deletefuncs, callback, data);
}
/*
* Internal function called from the main loop to reset the subsystem.
*/
void
dixResetPrivates(void)
{
if (items)
xfree(items);
items = NULL;
itemsSize = 0;
nextPrivateIndex = 0;
if (instances)
xfree(instances);
instances = NULL;
instancesSize = 0;
anyInstances = 0;
}
/*
* Internal function called from CreateNewResourceType.
*/
int
dixUpdatePrivates(void)
{
RESTYPE next = lastResourceType + 1;
/* check if instances table needs to be resized */
if (next >= instancesSize) {
RESTYPE size = instancesSize;
while (next >= size)
size += PRIV_TAB_INCREMENT;
instances = (char *)xrealloc(instances, size);
if (!instances) {
instancesSize = 0;
return FALSE;
}
memset(instances + instancesSize, 0, size - instancesSize);
instancesSize = size;
}
return TRUE;
}
/*
* Internal function called from dixAddResource.
* Allocates a ResourceRec along with any private space all in one chunk.
*/
ResourcePtr
dixAllocateResourceRec(RESTYPE type, pointer instance, pointer parent)
{
unsigned i, count = 0, size = sizeof(ResourceRec);
ResourcePtr res;
PrivatePtr ptr;
char *value;
/* first pass figures out total size */
for (i=0; i<nextPrivateIndex; i++)
if (items[i].type == type &&
(items[i].parent == NULL || items[i].parent == parent)) {
size += sizeof(PrivateRec) + items[i].size;
count++;
}
/* allocate resource bucket */
res = (ResourcePtr)xalloc(size);
if (!res)
return res;
memset(res, 0, size);
ptr = (PrivatePtr)(res + 1);
value = (char *)(ptr + count);
res->privates = (count > 0) ? ptr : NULL;
/* second pass sets up privates records */
count = 0;
for (i=0; i<nextPrivateIndex; i++)
if (items[i].type == type &&
(items[i].parent == NULL || items[i].parent == parent)) {
ptr[count].index = items[i].index;
ptr[count].value = value;
ptr[count].next = ptr + (count + 1);
count++;
value += items[i].size;
}
if (count > 0)
ptr[count-1].next = NULL;
/* hook up back-pointer to resource record(s) */
if (type & RC_PRIVATES) {
res->nexttype = *((ResourcePtr *)instance);
*((ResourcePtr *)instance) = res;
}
instances[TYPE_BITS(type)] = anyInstances = 1;
return res;
}
/*
* Internal function called from dixAddResource.
* Calls the init functions on a newly allocated resource.
*/
void
dixCallPrivateInitFuncs(ResourcePtr res)
{
PrivatePtr ptr = res->privates;
PrivateCallbackRec calldata;
calldata.resource = res;
while (ptr) {
calldata.value = ptr->value;
calldata.index = ptr->index;
CallCallbacks(&GET_DESCRIPTOR(ptr->index)->initfuncs, &calldata);
ptr = ptr->next;
}
}
/*
* Internal function called from the various delete resource functions.
* Calls delete callbacks before freeing the ResourceRec and other bits.
*/
void
dixFreeResourceRec(ResourcePtr res)
{
ResourcePtr *tmp;
PrivatePtr ptr, next, base;
PrivateCallbackRec calldata;
/* first pass calls the delete callbacks */
ptr = res->privates;
calldata.resource = res;
while (ptr) {
calldata.value = ptr->value;
calldata.index = ptr->index;
CallCallbacks(&GET_DESCRIPTOR(ptr->index)->deletefuncs, &calldata);
ptr = ptr->next;
}
/* second pass frees any off-struct private records */
ptr = res->privates;
base = (PrivatePtr)(res + 1);
while (ptr && ptr != base) {
next = ptr->next;
xfree(ptr);
ptr = next;
}
/* remove the record from the nexttype linked list and free it*/
if (res->type & RC_PRIVATES) {
tmp = (ResourcePtr *)res->value;
while (*tmp != res)
tmp = &(*tmp)->nexttype;
*tmp = (*tmp)->nexttype;
}
xfree(res);
}
/*
* Following is the old devPrivates support. These functions and variables
* are deprecated, and should no longer be used.
*/
/*
* See the Wrappers and devPrivates section in "Definition of the
* Porting Layer for the X v11 Sample Server" (doc/Server/ddx.tbl.ms)

View File

@ -63,6 +63,7 @@
#include "globals.h"
#include "os.h"
#include "osdep.h"
#include "privates.h"
#include "resource.h"
#include "servermd.h"
#include "scrnintstr.h"
@ -259,6 +260,11 @@ _X_HIDDEN void *dixLookupTab[] = {
SYMFUNC(GetScratchPixmapHeader)
SYMFUNC(FreeScratchPixmapHeader)
/* privates.c */
SYMFUNC(dixRequestPrivate)
SYMFUNC(dixRequestSinglePrivate)
SYMFUNC(dixLookupPrivate)
SYMFUNC(dixRegisterPrivateInitFunc)
SYMFUNC(dixRegisterPrivateDeleteFunc)
SYMFUNC(AllocateExtensionPrivate)
SYMFUNC(AllocateExtensionPrivateIndex)
SYMFUNC(AllocateClientPrivate)