1 /**
2  *
3  * $Id: Cache.c,v 1.1 2004/08/28 19:22:43 dannybackx Exp $
4  *
5  * Copyright (C) 1995 Free Software Foundation, Inc.
6  * Copyright (C) 1995-2001 LessTif Development Team
7  *
8  * This file is part of the GNU LessTif Library.
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public
21  * License along with this library; if not, write to the Free
22  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  *
24  **/
25 
26 static const char rcsid[] = "$Id: Cache.c,v 1.1 2004/08/28 19:22:43 dannybackx Exp $";
27 
28 #include <LTconfig.h>
29 
30 #include <string.h>
31 
32 #include <XmI/XmI.h>
33 
34 #include <Xm/XmP.h>
35 #include <Xm/CacheP.h>
36 #include <Xm/ExtObjectP.h>
37 
38 #include <XmI/DebugUtil.h>
39 
40 
41 void
_XmCacheDelete(XtPointer data)42 _XmCacheDelete(XtPointer data)
43 {
44     XmGadgetCacheRefPtr node;
45 
46     node = (XmGadgetCacheRefPtr)DataToGadgetCache(data);
47     node->cache.ref_count--;
48 
49     DEBUGOUT(_LtDebug(__FILE__, NULL, "Deleting %p : %08x: refcount: %d\n",
50 		      data, node, node->cache.ref_count));
51 
52     if (node->cache.ref_count == 0)
53     {
54 	DEBUGOUT(_LtDebug(__FILE__, NULL,
55 			  "Ref count 0: deleting %08x\n", node));
56 
57 	node->cache.prev->next = node->cache.next;
58 
59 	if (node->cache.next != NULL)	/* rws 16 Jun 1997
60 					   This is not the correct solution
61 					   since the node never gets freed, but
62 					   it does stop a core dump in one of
63 					   my apps
64 					 */
65 	{
66 	    node->cache.next->prev = node->cache.prev;
67 	    XtFree((char *)node);
68 	}
69 	else
70 	{
71 	    _XmWarning(NULL,
72 		       "Cache.c:_XmCacheDelete - node->cache.next is NULL");
73 	}
74     }
75 }
76 
77 void
_XmCacheCopy(XtPointer src,XtPointer dest,size_t size)78 _XmCacheCopy(XtPointer src, XtPointer dest, size_t size)
79 {
80     memcpy(dest, src, size);
81 }
82 
83 XtPointer
_XmCachePart(XmCacheClassPartPtr cp,XtPointer cpart,size_t size)84 _XmCachePart(XmCacheClassPartPtr cp, XtPointer cpart, size_t size)
85 {
86     XmGadgetCachePtr list;
87     XtPointer newpart;
88 
89     DEBUGOUT(_LtDebug(__FILE__, NULL,
90 		      "Attempting to cache a part %p head: %p.\n", cpart,
91 		      &ClassCacheHead(cp)));
92 
93     /*
94      * Guess what.  Motif doesn't save memory and self link the initial node.
95      * Big surprise.
96      */
97     if (ClassCacheHead(cp).next == NULL)
98     {
99 	ClassCacheHead(cp).prev = &ClassCacheHead(cp);
100 	ClassCacheHead(cp).next = &ClassCacheHead(cp);
101 	ClassCacheHead(cp).ref_count = -1;
102     }
103 
104     /* search cache */
105     list = ClassCacheHead(cp).next;
106 
107     while (list != &ClassCacheHead(cp))
108     {
109 	XmGadgetCachePtr tmp;
110 
111 	if (ClassCacheCompare(cp) (cpart, CacheDataPtr(list)))
112 	{
113 	    DEBUGOUT(_LtDebug(__FILE__, NULL,
114 			      "Cache hit: %08x\n", CacheDataPtr(list)));
115 
116 	    if (cpart != CacheDataPtr(list))
117 	    {
118 		list->ref_count++;
119 	    }
120 
121 	    return CacheDataPtr(list);
122 	}
123 
124 	tmp = list->next;
125 
126 	if (cpart == CacheDataPtr(list))
127 	{
128 	    DEBUGOUT(_LtDebug(__FILE__, NULL,
129 			      "In cache, but invalid.  Deleting old entry.\n"));
130 
131 	    _XmCacheDelete(cpart);
132 	}
133 
134 	list = tmp;
135     }
136 
137     /* not in cache, add new entry */
138     list = (XmGadgetCachePtr)XtCalloc(1, sizeof(XmGadgetCache) + size);
139 
140     DEBUGOUT(_LtDebug(__FILE__, NULL,
141 	     "Not in cache.  Adding new entry of size %d: %p.\n", size, list));
142 
143     newpart = (XtPointer)((char *)list + sizeof(XmGadgetCache));
144 
145     list->prev = ClassCacheHead(cp).prev;
146     ClassCacheHead(cp).prev->next = list;
147 
148     list->next = &ClassCacheHead(cp);
149     ClassCacheHead(cp).prev = list;
150 
151     list->ref_count = 1;
152 
153     DEBUGOUT(_LtDebug(__FILE__, NULL,
154 		      "Next: %p Prev: %p\n", list->prev, list->next));
155 
156     ClassCacheCopy(cp) (cpart, (XtPointer)newpart, size);
157 
158     return newpart;
159 }
160