[PATCH 2/4] devPrivates rework (v3): implementation
Eamon Walsh
ewalsh at tycho.nsa.gov
Thu Mar 8 13:50:24 PST 2007
Adds implementation to dix/privates.c
--
privates.c | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 233 insertions(+)
--
diff --git a/dix/privates.c b/dix/privates.c
index b20a1db..8aab32d 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,7 +46,238 @@ from The Open Group.
#include "inputstr.h"
#include "extnsionst.h"
+typedef struct _PrivateDesc {
+ devprivate_key_t *key;
+ 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.
+ */
+_X_EXPORT int
+dixRequestPrivate(devprivate_key_t *const key, unsigned size)
+{
+ PrivateDescRec *item = findItem(key);
+ if (item) {
+ 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->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;
+ 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;
+}
+
+/*
+ * 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) {
+ next = ptr->next;
+ xfree(ptr);
+ ptr = next;
+ }
+}
+
+/*
+ * Callback registration
+ */
+_X_EXPORT int
+dixRegisterPrivateInitFunc(devprivate_key_t *const key,
+ CallbackProcPtr callback, pointer data)
+{
+ PrivateDescRec *item = findItem(key);
+ if (!item) {
+ if (!dixRequestPrivate(key, 0))
+ return FALSE;
+ item = findItem(key);
+ }
+ 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) {
+ if (!dixRequestPrivate(key, 0))
+ return FALSE;
+ item = findItem(key);
+ }
+ 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) {
+ unsigned i = offsetsSize * 2 * sizeof(int);
+ offsets = (unsigned *)xrealloc(offsets, i);
+ if (!offsets) {
+ offsetsSize = 0;
+ return FALSE;
+ }
+ for (i=offsetsSize; i < 2*offsetsSize; i++)
+ offsets[i] = -1;
+ offsetsSize *= 2;
+ }
+
+ offsets[type] = offset;
+ return TRUE;
+}
+
+_X_EXPORT int
+dixLookupPrivateOffset(RESTYPE type)
+{
+ type = type & TypeMask;
+ assert(type < offsetsSize);
+ return offsets[type];
+}
+
+/*
+ * Called from the main loop to reset the subsystem.
+ */
+static int ResetExtensionPrivates(void);
+static int ResetClientPrivates(void);
+static void ResetScreenPrivates(void);
+static void ResetWindowPrivates(void);
+static void ResetGCPrivates(void);
+static void ResetPixmapPrivates(void);
+static void ResetColormapPrivates(void);
+static void ResetDevicePrivateIndex(void);
+
+int
+dixResetPrivates(void)
+{
+ PrivateDescRec *next;
+ unsigned i;
+
+ /* reset internal structures */
+ 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;
+ for (i=0; i < offsetsSize; i++)
+ offsets[i] = -1;
+
+ /* reset legacy devPrivates support */
+ if (!ResetExtensionPrivates() || !ResetClientPrivates())
+ return FALSE;
+ ResetScreenPrivates();
+ ResetWindowPrivates();
+ ResetGCPrivates();
+ ResetPixmapPrivates();
+ ResetColormapPrivates();
+ ResetDevicePrivateIndex();
+
+ /* register basic resource offsets */
+ return dixRegisterPrivateOffset(RT_WINDOW,
+ offsetof(WindowRec, devPrivates)) &&
+ dixRegisterPrivateOffset(RT_PIXMAP,
+ offsetof(PixmapRec, devPrivates)) &&
+ dixRegisterPrivateOffset(RT_GC,
+ offsetof(GC, devPrivates)) &&
+ dixRegisterPrivateOffset(RT_COLORMAP,
+ offsetof(ColormapRec, devPrivates));
+}
+
+/*
+ * 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