[PATCH 3/4] devPrivates rework (v2): implementation

Eamon Walsh ewalsh at tycho.nsa.gov
Mon Mar 5 11:30:34 PST 2007


Adds implementation to dix/privates.c

--

 privates.c |  268 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 268 insertions(+)

--
diff --git a/dix/privates.c b/dix/privates.c
index b20a1db..c4ecf6a 100644
--- a/dix/privates.c
+++ b/dix/privates.c
@@ -31,11 +31,13 @@ from The Open Group.
 #endif
 
 #include <X11/X.h>
+#include <stddef.h>
 #include "scrnintstr.h"
 #include "misc.h"
 #include "os.h"
 #include "windowstr.h"
 #include "resource.h"
+#include "privates.h"
 #include "dixstruct.h"
 #include "gcstruct.h"
 #include "colormapst.h"
@@ -44,6 +46,272 @@ from The Open Group.
 #include "inputstr.h"
 #include "extnsionst.h"
 
+typedef struct _PrivateDesc {
+    devprivate_key_t *key;
+    RESTYPE type;
+    pointer parent;
+    unsigned size;
+    CallbackListPtr initfuncs;
+    CallbackListPtr deletefuncs;
+    struct _PrivateDesc *next;
+} PrivateDescRec;
+
+/* list of all allocated privates */
+static PrivateDescRec *items = NULL;
+
+static _X_INLINE PrivateDescRec *
+findItem(devprivate_key_t *const key)
+{
+    PrivateDescRec *item = items;
+    while (item) {
+	if (item->key == key)
+	    return item;
+	item = item->next;
+    }
+    return NULL;
+}
+
+/*
+ * Request pre-allocated space in resources of a given type.
+ */
+_X_EXPORT int
+dixRequestPrivate(RESTYPE type, devprivate_key_t *const key,
+		  unsigned size, pointer parent)
+{
+    PrivateDescRec *item = findItem(key);
+    if (item) {
+	assert(item->type == type);
+	if (size > item->size)
+	    item->size = size;
+    } else {
+	item = (PrivateDescRec *)xalloc(sizeof(PrivateDescRec));
+	if (!item)
+	    return FALSE;
+	memset(item, 0, sizeof(PrivateDescRec));
+
+	/* add privates descriptor */
+	item->key = key;
+	item->type = type;
+	item->parent = parent;
+	item->size = size;
+	item->next = items;
+	items = item;
+    }
+    return TRUE;
+}
+
+/*
+ * Allocate a private and attach it to an existing object.
+ */
+_X_EXPORT pointer *
+dixAllocatePrivate(PrivateRec **privates, devprivate_key_t *const key)
+{
+    PrivateDescRec *item = findItem(key);
+    PrivateRec *ptr;
+    unsigned size = sizeof(PrivateRec);
+    
+    if (item)
+	size += item->size;
+
+    ptr = (PrivateRec *)xalloc(size);
+    if (!ptr)
+	return NULL;
+    memset(ptr, 0, size);
+    ptr->key = key;
+    ptr->value = (size > sizeof(PrivateRec)) ? (ptr + 1) : NULL;
+    ptr->next = *privates;
+    *privates = ptr;
+
+    /* call any init funcs and return */
+    if (item) {
+	PrivateCallbackRec calldata = { key, ptr->value };
+	CallCallbacks(&item->initfuncs, &calldata);
+    }
+    return &ptr->value;
+}
+
+/*
+ * Allocates pre-requested privates in a single chunk.
+ */
+_X_EXPORT PrivateRec *
+dixAllocatePrivates(RESTYPE type, pointer parent)
+{
+    unsigned count = 0, size = 0;
+    PrivateCallbackRec calldata;
+    PrivateDescRec *item;
+    PrivateRec *ptr;
+    char *value;
+
+    /* first pass figures out total size */
+    for (item = items; item; item = item->next)
+	if ((item->type == type || item->type == RC_ANY) &&
+	    (item->parent == NULL || item->parent == parent)) {
+
+	    size += sizeof(PrivateRec) + item->size;
+	    count++;
+	}
+
+    /* allocate one chunk of memory for everything */
+    ptr = (PrivateRec *)xalloc(size);
+    if (!ptr)
+	return NULL;
+    memset(ptr, 0, size);
+    value = (char *)(ptr + count);
+
+    /* second pass sets up records and calls init funcs */
+    count = 0;
+    for (item = items; item; item = item->next)
+	if ((item->type == type || item->type == RC_ANY) &&
+	    (item->parent == NULL || item->parent == parent)) {
+
+	    ptr[count].key = calldata.key = item->key;
+	    ptr[count].dontfree = (count > 0);
+	    ptr[count].value = calldata.value = (items->size ? value : NULL);
+	    ptr[count].next = ptr + (count + 1);
+
+	    CallCallbacks(&item->initfuncs, &calldata);
+
+	    count++;
+	    value += item->size;
+	}
+
+    if (count > 0)
+	ptr[count-1].next = NULL;
+
+    return ptr;
+}
+
+/*
+ * Called to free privates at object deletion time.
+ */
+_X_EXPORT void
+dixFreePrivates(PrivateRec *privates)
+{
+    PrivateRec *ptr, *next;
+    PrivateDescRec *item;
+    PrivateCallbackRec calldata;
+
+    /* first pass calls the delete callbacks */
+    for (ptr = privates; ptr; ptr = ptr->next) {
+	item = findItem(ptr->key);
+	if (item) {
+	    calldata.key = ptr->key;
+	    calldata.value = ptr->value;
+	    CallCallbacks(&item->deletefuncs, &calldata);
+	}
+    }
+	
+    /* second pass frees the memory */
+    ptr = privates;
+    while (ptr) {
+	if (ptr->dontfree)
+	    ptr = ptr->next;
+	else {
+	    next = ptr->next;
+	    while (next && next->dontfree)
+		next = next->next;
+
+	    xfree(ptr);
+	    ptr = next;
+	}
+    }
+
+    /* no more use of privates permitted */
+    *privates = NULL;
+}
+
+/*
+ * Callback registration
+ */
+_X_EXPORT int
+dixRegisterPrivateInitFunc(devprivate_key_t *const key,
+			   CallbackProcPtr callback, pointer data)
+{
+    PrivateDescRec *item = findItem(key);
+    if (!item)
+	return FALSE;
+    return AddCallback(&item->initfuncs, callback, data);
+}
+
+_X_EXPORT int
+dixRegisterPrivateDeleteFunc(devprivate_key_t *const key,
+			     CallbackProcPtr callback, pointer data)
+{
+    PrivateDescRec *item = findItem(key);
+    if (!item)
+	return FALSE;
+    return AddCallback(&item->deletefuncs, callback, data);
+}
+
+/* Table of devPrivates offsets */
+static unsigned *offsets = NULL;
+static unsigned offsetsSize = 0;
+
+/*
+ * Specify where the devPrivates field is located in a structure type
+ */
+_X_EXPORT int
+dixRegisterPrivateOffset(RESTYPE type, unsigned offset)
+{
+    type = type & TypeMask;
+
+    /* resize offsets table if necessary */
+    while (type >= offsetsSize) {
+	offsets = (unsigned *)xrealloc(offsets,
+				       offsetsSize * 2 * sizeof(unsigned));
+	if (!offsets) {
+	    offsetsSize = 0;
+	    return FALSE;
+	}
+	offsetsSize *= 2;
+    }
+
+    offsets[type] = offset;
+    return TRUE;
+}
+
+_X_EXPORT unsigned
+dixLookupPrivateOffset(RESTYPE type)
+{
+    assert(type & RC_PRIVATES);
+    type = type & TypeMask;
+    assert(type < offsetsSize);
+    return offsets[type];
+}
+
+/*
+ * Called from the main loop to reset the subsystem.
+ */
+int
+dixResetPrivates(void)
+{
+    PrivateDescRec *next;
+    while (items) {
+	next = items->next;
+	xfree(items);
+	items = next;
+    }
+
+    if (offsets)
+	xfree(offsets);
+
+    offsetsSize = 16;
+    offsets = (unsigned *)xalloc(offsetsSize * sizeof(unsigned));
+    if (!offsets)
+	return FALSE;
+
+    /* register basic resource offsets */
+    if (!dixRegisterPrivateOffset(RT_WINDOW, offsetof(WindowRec,devPrivates)))
+	return FALSE;
+
+    return TRUE;
+}
+
+/*
+ *  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)





More information about the xorg mailing list