diff options
| author | apnadkarni <apnmbx-wits@yahoo.com> | 2023-05-20 16:39:50 (GMT) |
|---|---|---|
| committer | apnadkarni <apnmbx-wits@yahoo.com> | 2023-05-20 16:39:50 (GMT) |
| commit | f19e2665d309df5a484a53ea6d9b1098275e33db (patch) | |
| tree | 6906aa04fcb87740b514d40f1b4c83435a53a645 /generic/tclInt.h | |
| parent | 72dfeb60e23c679d2c7258db4eb9ccce0a0661fa (diff) | |
| parent | 96d441c29a2a47269655285a02c546765c163fd2 (diff) | |
| download | tcl-f19e2665d309df5a484a53ea6d9b1098275e33db.zip tcl-f19e2665d309df5a484a53ea6d9b1098275e33db.tar.gz tcl-f19e2665d309df5a484a53ea6d9b1098275e33db.tar.bz2 | |
Fix [c9663296fd]. Also refactor memory reallocation.
Diffstat (limited to 'generic/tclInt.h')
| -rw-r--r-- | generic/tclInt.h | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/generic/tclInt.h b/generic/tclInt.h index 28ec508..bf42f6a 100644 --- a/generic/tclInt.h +++ b/generic/tclInt.h @@ -2873,6 +2873,75 @@ typedef struct ProcessGlobalValue { } while (0) /* + *---------------------------------------------------------------------- + * Common functions for calculating overallocation. Trivial but allows for + * experimenting with growth factors without having to change code in + * multiple places. See TclAttemptAllocElemsEx and similar for usage + * examples. Best to use those functions. Direct use of TclUpsizeAlloc / + * TclResizeAlloc is needed in special cases such as when total size of + * memory block is limited to less than TCL_SIZE_MAX. + * + *---------------------------------------------------------------------- + */ +static inline Tcl_Size +TclUpsizeAlloc(TCL_UNUSED(Tcl_Size) /* oldSize. For future experiments with + * some growth algorithms that use this + * information. */, + Tcl_Size needed, + Tcl_Size limit) +{ + /* assert (oldCapacity < needed <= limit) */ + if (needed < (limit - needed/2)) { + return needed + needed / 2; + } + else { + return limit; + } +} +static inline Tcl_Size TclUpsizeRetry(Tcl_Size needed, Tcl_Size lastAttempt) { + /* assert (needed < lastAttempt) */ + if (needed < lastAttempt - 1) { + /* (needed+lastAttempt)/2 but that formula may overflow Tcl_Size */ + return needed + (lastAttempt - needed) / 2; + } else { + return needed; + } +} +MODULE_SCOPE void *TclAllocElemsEx(Tcl_Size elemCount, Tcl_Size elemSize, + Tcl_Size leadSize, Tcl_Size *capacityPtr); +MODULE_SCOPE void *TclReallocElemsEx(void *oldPtr, Tcl_Size elemCount, + Tcl_Size elemSize, Tcl_Size leadSize, + Tcl_Size *capacityPtr); +MODULE_SCOPE void *TclAttemptReallocElemsEx(void *oldPtr, + Tcl_Size elemCount, Tcl_Size elemSize, + Tcl_Size leadSize, Tcl_Size *capacityPtr); +/* Alloc elemCount elements of size elemSize with leadSize header + * returning actual capacity (in elements) in *capacityPtr. */ +static inline void *TclAttemptAllocElemsEx(Tcl_Size elemCount, Tcl_Size elemSize, + Tcl_Size leadSize, Tcl_Size *capacityPtr) { + return TclAttemptReallocElemsEx( + NULL, elemCount, elemSize, leadSize, capacityPtr); +} +/* Alloc numByte bytes, returning actual capacity in *capacityPtr. */ +static inline void *TclAllocEx(Tcl_Size numBytes, Tcl_Size *capacityPtr) { + return TclAllocElemsEx(numBytes, 1, 0, capacityPtr); +} +/* Alloc numByte bytes, returning actual capacity in *capacityPtr. */ +static inline void * +TclAttemptAllocEx(Tcl_Size numBytes, Tcl_Size *capacityPtr) +{ + return TclAttemptAllocElemsEx(numBytes, 1, 0, capacityPtr); +} +/* Realloc numByte bytes, returning actual capacity in *capacityPtr. */ +static inline void *TclReallocEx(void *oldPtr, Tcl_Size numBytes, Tcl_Size *capacityPtr) { + return TclReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr); +} +/* Realloc numByte bytes, returning actual capacity in *capacityPtr. */ +static inline void *TclAttemptReallocEx(void *oldPtr, Tcl_Size numBytes, Tcl_Size *capacityPtr) { + return TclAttemptReallocElemsEx(oldPtr, numBytes, 1, 0, capacityPtr); +} + +/* *---------------------------------------------------------------- * Variables shared among Tcl modules but not used by the outside world. *---------------------------------------------------------------- |
