diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-11-15 13:21:38 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-11-15 13:21:38 +0000 |
commit | e7d29c6cdadbb08d39219a05d795fe6c38414e19 (patch) | |
tree | 158ca07b9a2bbe70ec90d308329f9cbd13fd55c7 /hash.c | |
parent | ca5739979dc932e809cb70d243ecc07d380d2725 (diff) | |
download | ruby-e7d29c6cdadbb08d39219a05d795fe6c38414e19.tar.gz |
hash.c: iteration level with reentering
* hash.c (hash_foreach_iter, hash_foreach_ensure, rb_hash_foreach):
deal with iteration level when reentering by callcc. temporary
measure until rollback of ensure is introduced. [ruby-dev:47807]
[Bug #9105]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@43683 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'hash.c')
-rw-r--r-- | hash.c | 14 |
1 files changed, 11 insertions, 3 deletions
@@ -173,7 +173,7 @@ struct hash_foreach_arg { VALUE hash; rb_foreach_func *func; VALUE arg; - int iter_lev; + VALUE marker; }; static int @@ -189,6 +189,10 @@ hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error) if (RHASH(arg->hash)->ntbl != tbl) { rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); } + if (DATA_PTR(arg->marker)) { + RHASH_ITER_LEV(arg->hash)++; + DATA_PTR(arg->marker) = 0; + } switch (status) { case ST_DELETE: FL_SET(arg->hash, HASH_DELETED); @@ -207,7 +211,10 @@ hash_foreach_ensure(VALUE arg) struct hash_foreach_arg *argp = (struct hash_foreach_arg *)arg; VALUE hash = argp->hash; - if ((RHASH_ITER_LEV(hash) = argp->iter_lev) == 0) { + if (DATA_PTR(argp->marker)) return 0; + DATA_PTR(argp->marker) = (void *)-1; + + if (--RHASH_ITER_LEV(hash) == 0) { if (FL_TEST(hash, HASH_DELETED)) { st_cleanup_safe(RHASH(hash)->ntbl, (st_data_t)Qundef); FL_UNSET(hash, HASH_DELETED); @@ -236,7 +243,8 @@ rb_hash_foreach(VALUE hash, int (*func)(ANYARGS), VALUE farg) arg.hash = hash; arg.func = (rb_foreach_func *)func; arg.arg = farg; - arg.iter_lev = RHASH_ITER_LEV(hash)++; + arg.marker = Data_Wrap_Struct(0, 0, 0, 0); + RHASH_ITER_LEV(hash)++; rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, (VALUE)&arg); } |