/[dtapublic]/projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclpreserve.c
ViewVC logotype

Diff of /projs/trunk/shared_source/c_tcl_base_7_5_w_mods/tclpreserve.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 67 by dashley, Mon Oct 31 00:57:34 2016 UTC revision 71 by dashley, Sat Nov 5 11:07:06 2016 UTC
# Line 1  Line 1 
1  /* $Header$ */  /* $Header$ */
2  /*  /*
3   * tclPreserve.c --   * tclPreserve.c --
4   *   *
5   *      This file contains a collection of procedures that are used   *      This file contains a collection of procedures that are used
6   *      to make sure that widget records and other data structures   *      to make sure that widget records and other data structures
7   *      aren't reallocated when there are nested procedures that   *      aren't reallocated when there are nested procedures that
8   *      depend on their existence.   *      depend on their existence.
9   *   *
10   * Copyright (c) 1991-1994 The Regents of the University of California.   * Copyright (c) 1991-1994 The Regents of the University of California.
11   * Copyright (c) 1994-1998 Sun Microsystems, Inc.   * Copyright (c) 1994-1998 Sun Microsystems, Inc.
12   *   *
13   * See the file "license.terms" for information on usage and redistribution   * See the file "license.terms" for information on usage and redistribution
14   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.   * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15   *   *
16   * RCS: @(#) $Id: tclpreserve.c,v 1.1.1.1 2001/06/13 04:45:15 dtashley Exp $   * RCS: @(#) $Id: tclpreserve.c,v 1.1.1.1 2001/06/13 04:45:15 dtashley Exp $
17   */   */
18    
19  #include "tclInt.h"  #include "tclInt.h"
20    
21  /*  /*
22   * The following data structure is used to keep track of all the   * The following data structure is used to keep track of all the
23   * Tcl_Preserve calls that are still in effect.  It grows as needed   * Tcl_Preserve calls that are still in effect.  It grows as needed
24   * to accommodate any number of calls in effect.   * to accommodate any number of calls in effect.
25   */   */
26    
27  typedef struct {  typedef struct {
28      ClientData clientData;      /* Address of preserved block. */      ClientData clientData;      /* Address of preserved block. */
29      int refCount;               /* Number of Tcl_Preserve calls in effect      int refCount;               /* Number of Tcl_Preserve calls in effect
30                                   * for block. */                                   * for block. */
31      int mustFree;               /* Non-zero means Tcl_EventuallyFree was      int mustFree;               /* Non-zero means Tcl_EventuallyFree was
32                                   * called while a Tcl_Preserve call was in                                   * called while a Tcl_Preserve call was in
33                                   * effect, so the structure must be freed                                   * effect, so the structure must be freed
34                                   * when refCount becomes zero. */                                   * when refCount becomes zero. */
35      Tcl_FreeProc *freeProc;     /* Procedure to call to free. */      Tcl_FreeProc *freeProc;     /* Procedure to call to free. */
36  } Reference;  } Reference;
37    
38  static Reference *refArray;     /* First in array of references. */  static Reference *refArray;     /* First in array of references. */
39  static int spaceAvl = 0;        /* Total number of structures available  static int spaceAvl = 0;        /* Total number of structures available
40                                   * at *firstRefPtr. */                                   * at *firstRefPtr. */
41  static int inUse = 0;           /* Count of structures currently in use  static int inUse = 0;           /* Count of structures currently in use
42                                   * in refArray. */                                   * in refArray. */
43  #define INITIAL_SIZE 2  #define INITIAL_SIZE 2
44  TCL_DECLARE_MUTEX(preserveMutex)/* To protect the above statics */  TCL_DECLARE_MUTEX(preserveMutex)/* To protect the above statics */
45    
46  /*  /*
47   * The following data structure is used to keep track of whether an   * The following data structure is used to keep track of whether an
48   * arbitrary block of memory has been deleted.  This is used by the   * arbitrary block of memory has been deleted.  This is used by the
49   * TclHandle code to avoid the more time-expensive algorithm of   * TclHandle code to avoid the more time-expensive algorithm of
50   * Tcl_Preserve().  This mechanism is mainly used when we have lots of   * Tcl_Preserve().  This mechanism is mainly used when we have lots of
51   * references to a few big, expensive objects that we don't want to live   * references to a few big, expensive objects that we don't want to live
52   * any longer than necessary.   * any longer than necessary.
53   */   */
54    
55  typedef struct HandleStruct {  typedef struct HandleStruct {
56      VOID *ptr;                  /* Pointer to the memory block being      VOID *ptr;                  /* Pointer to the memory block being
57                                   * tracked.  This field will become NULL when                                   * tracked.  This field will become NULL when
58                                   * the memory block is deleted.  This field                                   * the memory block is deleted.  This field
59                                   * must be the first in the structure. */                                   * must be the first in the structure. */
60  #ifdef TCL_MEM_DEBUG  #ifdef TCL_MEM_DEBUG
61      VOID *ptr2;                 /* Backup copy of the abpve pointer used to      VOID *ptr2;                 /* Backup copy of the abpve pointer used to
62                                   * ensure that the contents of the handle are                                   * ensure that the contents of the handle are
63                                   * not changed by anyone else. */                                   * not changed by anyone else. */
64  #endif  #endif
65      int refCount;               /* Number of TclHandlePreserve() calls in      int refCount;               /* Number of TclHandlePreserve() calls in
66                                   * effect on this handle. */                                   * effect on this handle. */
67  } HandleStruct;  } HandleStruct;
68    
69    
70  /*  /*
71   * Static routines in this file:   * Static routines in this file:
72   */   */
73    
74  static void     PreserveExitProc _ANSI_ARGS_((ClientData clientData));  static void     PreserveExitProc _ANSI_ARGS_((ClientData clientData));
75    
76    
77  /*  /*
78   *----------------------------------------------------------------------   *----------------------------------------------------------------------
79   *   *
80   * PreserveExitProc --   * PreserveExitProc --
81   *   *
82   *      Called during exit processing to clean up the reference array.   *      Called during exit processing to clean up the reference array.
83   *   *
84   * Results:   * Results:
85   *      None.   *      None.
86   *   *
87   * Side effects:   * Side effects:
88   *      Frees the storage of the reference array.   *      Frees the storage of the reference array.
89   *   *
90   *----------------------------------------------------------------------   *----------------------------------------------------------------------
91   */   */
92    
93          /* ARGSUSED */          /* ARGSUSED */
94  static void  static void
95  PreserveExitProc(clientData)  PreserveExitProc(clientData)
96      ClientData clientData;              /* NULL -Unused. */      ClientData clientData;              /* NULL -Unused. */
97  {  {
98      Tcl_MutexLock(&preserveMutex);      Tcl_MutexLock(&preserveMutex);
99      if (spaceAvl != 0) {      if (spaceAvl != 0) {
100          ckfree((char *) refArray);          ckfree((char *) refArray);
101          refArray = (Reference *) NULL;          refArray = (Reference *) NULL;
102          inUse = 0;          inUse = 0;
103          spaceAvl = 0;          spaceAvl = 0;
104      }      }
105      Tcl_MutexUnlock(&preserveMutex);      Tcl_MutexUnlock(&preserveMutex);
106  }  }
107    
108  /*  /*
109   *----------------------------------------------------------------------   *----------------------------------------------------------------------
110   *   *
111   * Tcl_Preserve --   * Tcl_Preserve --
112   *   *
113   *      This procedure is used by a procedure to declare its interest   *      This procedure is used by a procedure to declare its interest
114   *      in a particular block of memory, so that the block will not be   *      in a particular block of memory, so that the block will not be
115   *      reallocated until a matching call to Tcl_Release has been made.   *      reallocated until a matching call to Tcl_Release has been made.
116   *   *
117   * Results:   * Results:
118   *      None.   *      None.
119   *   *
120   * Side effects:   * Side effects:
121   *      Information is retained so that the block of memory will   *      Information is retained so that the block of memory will
122   *      not be freed until at least the matching call to Tcl_Release.   *      not be freed until at least the matching call to Tcl_Release.
123   *   *
124   *----------------------------------------------------------------------   *----------------------------------------------------------------------
125   */   */
126    
127  void  void
128  Tcl_Preserve(clientData)  Tcl_Preserve(clientData)
129      ClientData clientData;      /* Pointer to malloc'ed block of memory. */      ClientData clientData;      /* Pointer to malloc'ed block of memory. */
130  {  {
131      Reference *refPtr;      Reference *refPtr;
132      int i;      int i;
133    
134      /*      /*
135       * See if there is already a reference for this pointer.  If so,       * See if there is already a reference for this pointer.  If so,
136       * just increment its reference count.       * just increment its reference count.
137       */       */
138    
139      Tcl_MutexLock(&preserveMutex);      Tcl_MutexLock(&preserveMutex);
140      for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {      for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
141          if (refPtr->clientData == clientData) {          if (refPtr->clientData == clientData) {
142              refPtr->refCount++;              refPtr->refCount++;
143              Tcl_MutexUnlock(&preserveMutex);              Tcl_MutexUnlock(&preserveMutex);
144              return;              return;
145          }          }
146      }      }
147    
148      /*      /*
149       * Make a reference array if it doesn't already exist, or make it       * Make a reference array if it doesn't already exist, or make it
150       * bigger if it is full.       * bigger if it is full.
151       */       */
152    
153      if (inUse == spaceAvl) {      if (inUse == spaceAvl) {
154          if (spaceAvl == 0) {          if (spaceAvl == 0) {
155              Tcl_CreateExitHandler((Tcl_ExitProc *) PreserveExitProc,              Tcl_CreateExitHandler((Tcl_ExitProc *) PreserveExitProc,
156                      (ClientData) NULL);                      (ClientData) NULL);
157              refArray = (Reference *) ckalloc((unsigned)              refArray = (Reference *) ckalloc((unsigned)
158                      (INITIAL_SIZE*sizeof(Reference)));                      (INITIAL_SIZE*sizeof(Reference)));
159              spaceAvl = INITIAL_SIZE;              spaceAvl = INITIAL_SIZE;
160          } else {          } else {
161              Reference *new;              Reference *new;
162    
163              new = (Reference *) ckalloc((unsigned)              new = (Reference *) ckalloc((unsigned)
164                      (2*spaceAvl*sizeof(Reference)));                      (2*spaceAvl*sizeof(Reference)));
165              memcpy((VOID *) new, (VOID *) refArray,              memcpy((VOID *) new, (VOID *) refArray,
166                      spaceAvl*sizeof(Reference));                      spaceAvl*sizeof(Reference));
167              ckfree((char *) refArray);              ckfree((char *) refArray);
168              refArray = new;              refArray = new;
169              spaceAvl *= 2;              spaceAvl *= 2;
170          }          }
171      }      }
172    
173      /*      /*
174       * Make a new entry for the new reference.       * Make a new entry for the new reference.
175       */       */
176    
177      refPtr = &refArray[inUse];      refPtr = &refArray[inUse];
178      refPtr->clientData = clientData;      refPtr->clientData = clientData;
179      refPtr->refCount = 1;      refPtr->refCount = 1;
180      refPtr->mustFree = 0;      refPtr->mustFree = 0;
181      refPtr->freeProc = TCL_STATIC;      refPtr->freeProc = TCL_STATIC;
182      inUse += 1;      inUse += 1;
183      Tcl_MutexUnlock(&preserveMutex);      Tcl_MutexUnlock(&preserveMutex);
184  }  }
185    
186  /*  /*
187   *----------------------------------------------------------------------   *----------------------------------------------------------------------
188   *   *
189   * Tcl_Release --   * Tcl_Release --
190   *   *
191   *      This procedure is called to cancel a previous call to   *      This procedure is called to cancel a previous call to
192   *      Tcl_Preserve, thereby allowing a block of memory to be   *      Tcl_Preserve, thereby allowing a block of memory to be
193   *      freed (if no one else cares about it).   *      freed (if no one else cares about it).
194   *   *
195   * Results:   * Results:
196   *      None.   *      None.
197   *   *
198   * Side effects:   * Side effects:
199   *      If Tcl_EventuallyFree has been called for clientData, and if   *      If Tcl_EventuallyFree has been called for clientData, and if
200   *      no other call to Tcl_Preserve is still in effect, the block of   *      no other call to Tcl_Preserve is still in effect, the block of
201   *      memory is freed.   *      memory is freed.
202   *   *
203   *----------------------------------------------------------------------   *----------------------------------------------------------------------
204   */   */
205    
206  void  void
207  Tcl_Release(clientData)  Tcl_Release(clientData)
208      ClientData clientData;      /* Pointer to malloc'ed block of memory. */      ClientData clientData;      /* Pointer to malloc'ed block of memory. */
209  {  {
210      Reference *refPtr;      Reference *refPtr;
211      int mustFree;      int mustFree;
212      Tcl_FreeProc *freeProc;      Tcl_FreeProc *freeProc;
213      int i;      int i;
214    
215      Tcl_MutexLock(&preserveMutex);      Tcl_MutexLock(&preserveMutex);
216      for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {      for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
217          if (refPtr->clientData != clientData) {          if (refPtr->clientData != clientData) {
218              continue;              continue;
219          }          }
220          refPtr->refCount--;          refPtr->refCount--;
221          if (refPtr->refCount == 0) {          if (refPtr->refCount == 0) {
222    
223              /*              /*
224               * Must remove information from the slot before calling freeProc               * Must remove information from the slot before calling freeProc
225               * to avoid reentrancy problems if the freeProc calls Tcl_Preserve               * to avoid reentrancy problems if the freeProc calls Tcl_Preserve
226               * on the same clientData. Copy down the last reference in the               * on the same clientData. Copy down the last reference in the
227               * array to overwrite the current slot.               * array to overwrite the current slot.
228               */               */
229    
230              freeProc = refPtr->freeProc;              freeProc = refPtr->freeProc;
231              mustFree = refPtr->mustFree;              mustFree = refPtr->mustFree;
232              inUse--;              inUse--;
233              if (i < inUse) {              if (i < inUse) {
234                  refArray[i] = refArray[inUse];                  refArray[i] = refArray[inUse];
235              }              }
236              if (mustFree) {              if (mustFree) {
237                  if ((freeProc == TCL_DYNAMIC) ||                  if ((freeProc == TCL_DYNAMIC) ||
238                          (freeProc == (Tcl_FreeProc *) free)) {                          (freeProc == (Tcl_FreeProc *) free)) {
239                      ckfree((char *) clientData);                      ckfree((char *) clientData);
240                  } else {                  } else {
241                      Tcl_MutexUnlock(&preserveMutex);                      Tcl_MutexUnlock(&preserveMutex);
242                      (*freeProc)((char *) clientData);                      (*freeProc)((char *) clientData);
243                      return;                      return;
244                  }                  }
245              }              }
246          }          }
247          Tcl_MutexUnlock(&preserveMutex);          Tcl_MutexUnlock(&preserveMutex);
248          return;          return;
249      }      }
250      Tcl_MutexUnlock(&preserveMutex);      Tcl_MutexUnlock(&preserveMutex);
251    
252      /*      /*
253       * Reference not found.  This is a bug in the caller.       * Reference not found.  This is a bug in the caller.
254       */       */
255    
256      panic("Tcl_Release couldn't find reference for 0x%x", clientData);      panic("Tcl_Release couldn't find reference for 0x%x", clientData);
257  }  }
258    
259  /*  /*
260   *----------------------------------------------------------------------   *----------------------------------------------------------------------
261   *   *
262   * Tcl_EventuallyFree --   * Tcl_EventuallyFree --
263   *   *
264   *      Free up a block of memory, unless a call to Tcl_Preserve is in   *      Free up a block of memory, unless a call to Tcl_Preserve is in
265   *      effect for that block.  In this case, defer the free until all   *      effect for that block.  In this case, defer the free until all
266   *      calls to Tcl_Preserve have been undone by matching calls to   *      calls to Tcl_Preserve have been undone by matching calls to
267   *      Tcl_Release.   *      Tcl_Release.
268   *   *
269   * Results:   * Results:
270   *      None.   *      None.
271   *   *
272   * Side effects:   * Side effects:
273   *      Ptr may be released by calling free().   *      Ptr may be released by calling free().
274   *   *
275   *----------------------------------------------------------------------   *----------------------------------------------------------------------
276   */   */
277    
278  void  void
279  Tcl_EventuallyFree(clientData, freeProc)  Tcl_EventuallyFree(clientData, freeProc)
280      ClientData clientData;      /* Pointer to malloc'ed block of memory. */      ClientData clientData;      /* Pointer to malloc'ed block of memory. */
281      Tcl_FreeProc *freeProc;     /* Procedure to actually do free. */      Tcl_FreeProc *freeProc;     /* Procedure to actually do free. */
282  {  {
283      Reference *refPtr;      Reference *refPtr;
284      int i;      int i;
285    
286      /*      /*
287       * See if there is a reference for this pointer.  If so, set its       * See if there is a reference for this pointer.  If so, set its
288       * "mustFree" flag (the flag had better not be set already!).       * "mustFree" flag (the flag had better not be set already!).
289       */       */
290    
291      Tcl_MutexLock(&preserveMutex);      Tcl_MutexLock(&preserveMutex);
292      for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {      for (i = 0, refPtr = refArray; i < inUse; i++, refPtr++) {
293          if (refPtr->clientData != clientData) {          if (refPtr->clientData != clientData) {
294              continue;              continue;
295          }          }
296          if (refPtr->mustFree) {          if (refPtr->mustFree) {
297              panic("Tcl_EventuallyFree called twice for 0x%x\n", clientData);              panic("Tcl_EventuallyFree called twice for 0x%x\n", clientData);
298          }          }
299          refPtr->mustFree = 1;          refPtr->mustFree = 1;
300          refPtr->freeProc = freeProc;          refPtr->freeProc = freeProc;
301          Tcl_MutexUnlock(&preserveMutex);          Tcl_MutexUnlock(&preserveMutex);
302          return;          return;
303      }      }
304      Tcl_MutexUnlock(&preserveMutex);      Tcl_MutexUnlock(&preserveMutex);
305    
306      /*      /*
307       * No reference for this block.  Free it now.       * No reference for this block.  Free it now.
308       */       */
309    
310      if ((freeProc == TCL_DYNAMIC)      if ((freeProc == TCL_DYNAMIC)
311              || (freeProc == (Tcl_FreeProc *) free)) {              || (freeProc == (Tcl_FreeProc *) free)) {
312          ckfree((char *) clientData);          ckfree((char *) clientData);
313      } else {      } else {
314          (*freeProc)((char *)clientData);          (*freeProc)((char *)clientData);
315      }      }
316  }  }
317    
318  /*  /*
319   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
320   *   *
321   * TclHandleCreate --   * TclHandleCreate --
322   *   *
323   *      Allocate a handle that contains enough information to determine   *      Allocate a handle that contains enough information to determine
324   *      if an arbitrary malloc'd block has been deleted.  This is   *      if an arbitrary malloc'd block has been deleted.  This is
325   *      used to avoid the more time-expensive algorithm of Tcl_Preserve().   *      used to avoid the more time-expensive algorithm of Tcl_Preserve().
326   *   *
327   * Results:   * Results:
328   *      The return value is a TclHandle that refers to the given malloc'd   *      The return value is a TclHandle that refers to the given malloc'd
329   *      block.  Doubly dereferencing the returned handle will give   *      block.  Doubly dereferencing the returned handle will give
330   *      back the pointer to the block, or will give NULL if the block has   *      back the pointer to the block, or will give NULL if the block has
331   *      been deleted.   *      been deleted.
332   *   *
333   * Side effects:   * Side effects:
334   *      The caller must keep track of this handle (generally by storing   *      The caller must keep track of this handle (generally by storing
335   *      it in a field in the malloc'd block) and call TclHandleFree()   *      it in a field in the malloc'd block) and call TclHandleFree()
336   *      on this handle when the block is deleted.  Everything else that   *      on this handle when the block is deleted.  Everything else that
337   *      wishes to keep track of whether the malloc'd block has been deleted   *      wishes to keep track of whether the malloc'd block has been deleted
338   *      should use calls to TclHandlePreserve() and TclHandleRelease()   *      should use calls to TclHandlePreserve() and TclHandleRelease()
339   *      on the associated handle.   *      on the associated handle.
340   *   *
341   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
342   */   */
343    
344  TclHandle  TclHandle
345  TclHandleCreate(ptr)  TclHandleCreate(ptr)
346      VOID *ptr;                  /* Pointer to an arbitrary block of memory      VOID *ptr;                  /* Pointer to an arbitrary block of memory
347                                   * to be tracked for deletion.  Must not be                                   * to be tracked for deletion.  Must not be
348                                   * NULL. */                                   * NULL. */
349  {  {
350      HandleStruct *handlePtr;      HandleStruct *handlePtr;
351    
352      handlePtr = (HandleStruct *) ckalloc(sizeof(HandleStruct));      handlePtr = (HandleStruct *) ckalloc(sizeof(HandleStruct));
353      handlePtr->ptr = ptr;      handlePtr->ptr = ptr;
354  #ifdef TCL_MEM_DEBUG  #ifdef TCL_MEM_DEBUG
355      handlePtr->ptr2 = ptr;      handlePtr->ptr2 = ptr;
356  #endif  #endif
357      handlePtr->refCount = 0;      handlePtr->refCount = 0;
358      return (TclHandle) handlePtr;      return (TclHandle) handlePtr;
359  }  }
360    
361  /*  /*
362   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
363   *   *
364   * TclHandleFree --   * TclHandleFree --
365   *   *
366   *      Called when the arbitrary malloc'd block associated with the   *      Called when the arbitrary malloc'd block associated with the
367   *      handle is being deleted.  Modifies the handle so that doubly   *      handle is being deleted.  Modifies the handle so that doubly
368   *      dereferencing it will give NULL.  This informs any user of the   *      dereferencing it will give NULL.  This informs any user of the
369   *      handle that the block of memory formerly referenced by the   *      handle that the block of memory formerly referenced by the
370   *      handle has been freed.   *      handle has been freed.
371   *   *
372   * Results:   * Results:
373   *      None.   *      None.
374   *   *
375   * Side effects:   * Side effects:
376   *      If nothing is referring to the handle, the handle will be reclaimed.   *      If nothing is referring to the handle, the handle will be reclaimed.
377   *   *
378   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
379   */   */
380    
381  void  void
382  TclHandleFree(handle)  TclHandleFree(handle)
383      TclHandle handle;           /* Previously created handle associated      TclHandle handle;           /* Previously created handle associated
384                                   * with a malloc'd block that is being                                   * with a malloc'd block that is being
385                                   * deleted.  The handle is modified so that                                   * deleted.  The handle is modified so that
386                                   * doubly dereferencing it will give NULL. */                                   * doubly dereferencing it will give NULL. */
387  {  {
388      HandleStruct *handlePtr;      HandleStruct *handlePtr;
389    
390      handlePtr = (HandleStruct *) handle;      handlePtr = (HandleStruct *) handle;
391  #ifdef TCL_MEM_DEBUG  #ifdef TCL_MEM_DEBUG
392      if (handlePtr->refCount == 0x61616161) {      if (handlePtr->refCount == 0x61616161) {
393          panic("using previously disposed TclHandle %x", handlePtr);          panic("using previously disposed TclHandle %x", handlePtr);
394      }      }
395      if (handlePtr->ptr2 != handlePtr->ptr) {      if (handlePtr->ptr2 != handlePtr->ptr) {
396          panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",          panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",
397                  handlePtr, handlePtr->ptr2, handlePtr->ptr);                  handlePtr, handlePtr->ptr2, handlePtr->ptr);
398      }      }
399  #endif  #endif
400      handlePtr->ptr = NULL;      handlePtr->ptr = NULL;
401      if (handlePtr->refCount == 0) {      if (handlePtr->refCount == 0) {
402          ckfree((char *) handlePtr);          ckfree((char *) handlePtr);
403      }      }
404  }  }
405    
406  /*  /*
407   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
408   *   *
409   * TclHandlePreserve --   * TclHandlePreserve --
410   *   *
411   *      Declare an interest in the arbitrary malloc'd block associated   *      Declare an interest in the arbitrary malloc'd block associated
412   *      with the handle.     *      with the handle.  
413   *   *
414   * Results:   * Results:
415   *      The return value is the handle argument, with its ref count   *      The return value is the handle argument, with its ref count
416   *      incremented.   *      incremented.
417   *   *
418   * Side effects:   * Side effects:
419   *      For each call to TclHandlePreserve(), there should be a matching   *      For each call to TclHandlePreserve(), there should be a matching
420   *      call to TclHandleRelease() when the caller is no longer interested   *      call to TclHandleRelease() when the caller is no longer interested
421   *      in the malloc'd block associated with the handle.   *      in the malloc'd block associated with the handle.
422   *   *
423   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
424   */   */
425    
426  TclHandle  TclHandle
427  TclHandlePreserve(handle)  TclHandlePreserve(handle)
428      TclHandle handle;           /* Declare an interest in the block of      TclHandle handle;           /* Declare an interest in the block of
429                                   * memory referenced by this handle. */                                   * memory referenced by this handle. */
430  {  {
431      HandleStruct *handlePtr;      HandleStruct *handlePtr;
432    
433      handlePtr = (HandleStruct *) handle;      handlePtr = (HandleStruct *) handle;
434  #ifdef TCL_MEM_DEBUG  #ifdef TCL_MEM_DEBUG
435      if (handlePtr->refCount == 0x61616161) {      if (handlePtr->refCount == 0x61616161) {
436          panic("using previously disposed TclHandle %x", handlePtr);          panic("using previously disposed TclHandle %x", handlePtr);
437      }      }
438      if ((handlePtr->ptr != NULL)      if ((handlePtr->ptr != NULL)
439              && (handlePtr->ptr != handlePtr->ptr2)) {              && (handlePtr->ptr != handlePtr->ptr2)) {
440          panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",          panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",
441                  handlePtr, handlePtr->ptr2, handlePtr->ptr);                  handlePtr, handlePtr->ptr2, handlePtr->ptr);
442      }      }
443  #endif  #endif
444      handlePtr->refCount++;      handlePtr->refCount++;
445    
446      return handle;      return handle;
447  }  }
448    
449  /*  /*
450   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
451   *   *
452   * TclHandleRelease --   * TclHandleRelease --
453   *   *
454   *      This procedure is called to release an interest in the malloc'd   *      This procedure is called to release an interest in the malloc'd
455   *      block associated with the handle.   *      block associated with the handle.
456   *   *
457   * Results:   * Results:
458   *      None.   *      None.
459   *   *
460   * Side effects:   * Side effects:
461   *      The ref count of the handle is decremented.  If the malloc'd block   *      The ref count of the handle is decremented.  If the malloc'd block
462   *      has been freed and if no one is using the handle any more, the   *      has been freed and if no one is using the handle any more, the
463   *      handle will be reclaimed.   *      handle will be reclaimed.
464   *   *
465   *---------------------------------------------------------------------------   *---------------------------------------------------------------------------
466   */   */
467    
468  void  void
469  TclHandleRelease(handle)  TclHandleRelease(handle)
470      TclHandle handle;           /* Unregister interest in the block of      TclHandle handle;           /* Unregister interest in the block of
471                                   * memory referenced by this handle. */                                   * memory referenced by this handle. */
472  {  {
473      HandleStruct *handlePtr;      HandleStruct *handlePtr;
474    
475      handlePtr = (HandleStruct *) handle;      handlePtr = (HandleStruct *) handle;
476  #ifdef TCL_MEM_DEBUG  #ifdef TCL_MEM_DEBUG
477      if (handlePtr->refCount == 0x61616161) {      if (handlePtr->refCount == 0x61616161) {
478          panic("using previously disposed TclHandle %x", handlePtr);          panic("using previously disposed TclHandle %x", handlePtr);
479      }      }
480      if ((handlePtr->ptr != NULL)      if ((handlePtr->ptr != NULL)
481              && (handlePtr->ptr != handlePtr->ptr2)) {              && (handlePtr->ptr != handlePtr->ptr2)) {
482          panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",          panic("someone has changed the block referenced by the handle %x\nfrom %x to %x",
483                  handlePtr, handlePtr->ptr2, handlePtr->ptr);                  handlePtr, handlePtr->ptr2, handlePtr->ptr);
484      }      }
485  #endif  #endif
486      handlePtr->refCount--;      handlePtr->refCount--;
487      if ((handlePtr->refCount == 0) && (handlePtr->ptr == NULL)) {      if ((handlePtr->refCount == 0) && (handlePtr->ptr == NULL)) {
488          ckfree((char *) handlePtr);          ckfree((char *) handlePtr);
489      }      }
490  }  }
491            
492  /* End of tclpreserve.c */  /* End of tclpreserve.c */

Legend:
Removed from v.67  
changed lines
  Added in v.71

dashley@gmail.com
ViewVC Help
Powered by ViewVC 1.1.25