mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.2.1210: using ht_used when looping through a hashtab is less reliable
Problem: Using ht_used when looping through a hashtab is less reliable. Solution: Use ht_changed in a few more places.
This commit is contained in:
parent
21c16f868d
commit
1f22cc5cdb
@ -1792,11 +1792,10 @@ DictionaryContains(DictionaryObject *self, PyObject *keyObject)
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
hashitem_T *ht_array;
|
int dii_changed;
|
||||||
long_u ht_used;
|
hashtab_T *dii_ht;
|
||||||
hashtab_T *ht;
|
hashitem_T *dii_hi;
|
||||||
hashitem_T *hi;
|
long_u dii_todo;
|
||||||
long_u todo;
|
|
||||||
} dictiterinfo_T;
|
} dictiterinfo_T;
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
@ -1804,23 +1803,22 @@ DictionaryIterNext(dictiterinfo_T **dii)
|
|||||||
{
|
{
|
||||||
PyObject *ret;
|
PyObject *ret;
|
||||||
|
|
||||||
if (!(*dii)->todo)
|
if (!(*dii)->dii_todo)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if ((*dii)->ht->ht_array != (*dii)->ht_array ||
|
if ((*dii)->dii_ht->ht_changed != (*dii)->dii_changed)
|
||||||
(*dii)->ht->ht_used != (*dii)->ht_used)
|
|
||||||
{
|
{
|
||||||
PyErr_SET_STRING(PyExc_RuntimeError,
|
PyErr_SET_STRING(PyExc_RuntimeError,
|
||||||
N_("hashtab changed during iteration"));
|
N_("hashtab changed during iteration"));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (((*dii)->todo) && HASHITEM_EMPTY((*dii)->hi))
|
while (((*dii)->dii_todo) && HASHITEM_EMPTY((*dii)->dii_hi))
|
||||||
++((*dii)->hi);
|
++((*dii)->dii_hi);
|
||||||
|
|
||||||
--((*dii)->todo);
|
--((*dii)->dii_todo);
|
||||||
|
|
||||||
if (!(ret = PyBytes_FromString((char *)(*dii)->hi->hi_key)))
|
if (!(ret = PyBytes_FromString((char *)(*dii)->dii_hi->hi_key)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -1839,11 +1837,10 @@ DictionaryIter(DictionaryObject *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ht = &self->dict->dv_hashtab;
|
ht = &self->dict->dv_hashtab;
|
||||||
dii->ht_array = ht->ht_array;
|
dii->dii_changed = ht->ht_changed;
|
||||||
dii->ht_used = ht->ht_used;
|
dii->dii_ht = ht;
|
||||||
dii->ht = ht;
|
dii->dii_hi = ht->ht_array;
|
||||||
dii->hi = dii->ht_array;
|
dii->dii_todo = ht->ht_used;
|
||||||
dii->todo = dii->ht_used;
|
|
||||||
|
|
||||||
return IterNew(dii,
|
return IterNew(dii,
|
||||||
(destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
|
(destructorfun) PyMem_Free, (nextfun) DictionaryIterNext,
|
||||||
|
@ -1712,7 +1712,7 @@ free_all_functions(void)
|
|||||||
ufunc_T *fp;
|
ufunc_T *fp;
|
||||||
long_u skipped = 0;
|
long_u skipped = 0;
|
||||||
long_u todo = 1;
|
long_u todo = 1;
|
||||||
long_u used;
|
int changed;
|
||||||
|
|
||||||
// Clean up the current_funccal chain and the funccal stack.
|
// Clean up the current_funccal chain and the funccal stack.
|
||||||
while (current_funccal != NULL)
|
while (current_funccal != NULL)
|
||||||
@ -1743,9 +1743,9 @@ free_all_functions(void)
|
|||||||
++skipped;
|
++skipped;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
used = func_hashtab.ht_used;
|
changed = func_hashtab.ht_changed;
|
||||||
func_clear(fp, TRUE);
|
func_clear(fp, TRUE);
|
||||||
if (used != func_hashtab.ht_used)
|
if (changed != func_hashtab.ht_changed)
|
||||||
{
|
{
|
||||||
skipped = 0;
|
skipped = 0;
|
||||||
break;
|
break;
|
||||||
@ -2484,12 +2484,11 @@ untrans_function_name(char_u *name)
|
|||||||
static void
|
static void
|
||||||
list_functions(regmatch_T *regmatch)
|
list_functions(regmatch_T *regmatch)
|
||||||
{
|
{
|
||||||
long_u used = func_hashtab.ht_used;
|
int changed = func_hashtab.ht_changed;
|
||||||
long_u todo = used;
|
long_u todo = func_hashtab.ht_used;
|
||||||
hashitem_T *ht_array = func_hashtab.ht_array;
|
|
||||||
hashitem_T *hi;
|
hashitem_T *hi;
|
||||||
|
|
||||||
for (hi = ht_array; todo > 0 && !got_int; ++hi)
|
for (hi = func_hashtab.ht_array; todo > 0 && !got_int; ++hi)
|
||||||
{
|
{
|
||||||
if (!HASHITEM_EMPTY(hi))
|
if (!HASHITEM_EMPTY(hi))
|
||||||
{
|
{
|
||||||
@ -2504,8 +2503,7 @@ list_functions(regmatch_T *regmatch)
|
|||||||
&& vim_regexec(regmatch, fp->uf_name, 0)))
|
&& vim_regexec(regmatch, fp->uf_name, 0)))
|
||||||
{
|
{
|
||||||
list_func_head(fp, FALSE);
|
list_func_head(fp, FALSE);
|
||||||
if (used != func_hashtab.ht_used
|
if (changed != func_hashtab.ht_changed)
|
||||||
|| ht_array != func_hashtab.ht_array)
|
|
||||||
{
|
{
|
||||||
emsg(_("E454: function list was modified"));
|
emsg(_("E454: function list was modified"));
|
||||||
return;
|
return;
|
||||||
@ -3564,6 +3562,7 @@ get_expanded_name(char_u *name, int check)
|
|||||||
get_user_func_name(expand_T *xp, int idx)
|
get_user_func_name(expand_T *xp, int idx)
|
||||||
{
|
{
|
||||||
static long_u done;
|
static long_u done;
|
||||||
|
static int changed;
|
||||||
static hashitem_T *hi;
|
static hashitem_T *hi;
|
||||||
ufunc_T *fp;
|
ufunc_T *fp;
|
||||||
|
|
||||||
@ -3571,8 +3570,9 @@ get_user_func_name(expand_T *xp, int idx)
|
|||||||
{
|
{
|
||||||
done = 0;
|
done = 0;
|
||||||
hi = func_hashtab.ht_array;
|
hi = func_hashtab.ht_array;
|
||||||
|
changed = func_hashtab.ht_changed;
|
||||||
}
|
}
|
||||||
if (done < func_hashtab.ht_used)
|
if (changed == func_hashtab.ht_changed && done < func_hashtab.ht_used)
|
||||||
{
|
{
|
||||||
if (done++ > 0)
|
if (done++ > 0)
|
||||||
++hi;
|
++hi;
|
||||||
|
@ -754,6 +754,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1210,
|
||||||
/**/
|
/**/
|
||||||
1209,
|
1209,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user