[前][次][番号順一覧][スレッド一覧]

ruby-changes:22408

From: nobu <ko1@a...>
Date: Tue, 7 Feb 2012 14:29:39 +0900 (JST)
Subject: [ruby-changes:22408] nobu:r34456 (trunk, ruby_1_9_3): * st.c (st_foreach): should not yield same pair when checking

nobu	2012-02-07 14:29:20 +0900 (Tue, 07 Feb 2012)

  New Revision: 34456

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=34456

  Log:
    * st.c (st_foreach): should not yield same pair when checking
      after unpacking.

  Added directories:
    branches/ruby_1_9_3/ext/-test-/st/
    branches/ruby_1_9_3/ext/-test-/st/numhash/
    branches/ruby_1_9_3/test/-ext-/st/
    trunk/ext/-test-/st/numhash/
  Added files:
    branches/ruby_1_9_3/ext/-test-/st/numhash/extconf.rb
    branches/ruby_1_9_3/ext/-test-/st/numhash/numhash.c
    branches/ruby_1_9_3/test/-ext-/st/test_numhash.rb
    trunk/ext/-test-/st/numhash/extconf.rb
    trunk/ext/-test-/st/numhash/numhash.c
    trunk/test/-ext-/st/test_numhash.rb
  Modified files:
    branches/ruby_1_9_3/ChangeLog
    branches/ruby_1_9_3/st.c
    branches/ruby_1_9_3/version.h
    trunk/ChangeLog
    trunk/st.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 34455)
+++ ChangeLog	(revision 34456)
@@ -1,3 +1,8 @@
+Tue Feb  7 14:29:16 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* st.c (st_foreach): should not yield same pair when checking
+	  after unpacking.
+
 Mon Feb  6 21:55:13 2012  NARUSE, Yui  <naruse@r...>
 
 	* tool/merger.rb: abort if the working directory is dirty.
Index: st.c
===================================================================
--- st.c	(revision 34455)
+++ st.c	(revision 34456)
@@ -337,6 +337,9 @@
 #define FOUND_ENTRY
 #endif
 
+#define FIND_ENTRY(table, ptr, hash_val, bin_pos) \
+    ((ptr) = find_entry((table), key, (hash_val), ((bin_pos) = (hash_val)%(table)->num_bins)))
+
 static st_table_entry *
 find_entry(st_table *table, st_data_t key, st_index_t hash_val, st_index_t bin_pos)
 {
@@ -420,8 +423,8 @@
 #define collision_check 1
 
 static inline void
-add_direct(st_table * table, st_data_t key, st_data_t value,
-	st_index_t hash_val, register st_index_t bin_pos)
+add_direct(st_table *table, st_data_t key, st_data_t value,
+	   st_index_t hash_val, register st_index_t bin_pos)
 {
     register st_table_entry *entry;
     if (table->num_entries > ST_DEFAULT_MAX_DENSITY * table->num_bins) {
@@ -819,7 +822,14 @@
             key = PKEY(table, i);
             val = PVAL(table, i);
             retval = (*func)(key, val, arg);
-	    if (!table->entries_packed) goto unpacked;
+	    if (!table->entries_packed) {
+		FIND_ENTRY(table, ptr, key, i);
+		if (retval == ST_CHECK) {
+		    if (!ptr) goto deleted;
+		    goto unpacked_continue;
+		}
+		goto unpacked;
+	    }
             switch (retval) {
 	      case ST_CHECK:	/* check if hash is modified during iteration */
                 for (j = 0; j < table->num_entries; j++) {
@@ -827,9 +837,7 @@
                         break;
                 }
                 if (j == table->num_entries) {
-                    /* call func with error notice */
-                    retval = (*func)(0, 0, arg, 1);
-                    return 1;
+		    goto deleted;
                 }
 		/* fall through */
 	      case ST_CONTINUE:
@@ -843,11 +851,6 @@
             }
         }
         return 0;
-      unpacked:
-	ptr = table->head;
-	while (i-- > 0) {
-	    if (!(ptr = ptr->fore)) return 0;
-	}
     }
     else {
 	ptr = table->head;
@@ -857,10 +860,12 @@
 	do {
 	    i = ptr->hash % table->num_bins;
 	    retval = (*func)(ptr->key, ptr->record, arg);
+	  unpacked:
 	    switch (retval) {
 	      case ST_CHECK:	/* check if hash is modified during iteration */
 		for (tmp = table->bins[i]; tmp != ptr; tmp = tmp->next) {
 		    if (!tmp) {
+		      deleted:
 			/* call func with error notice */
 			retval = (*func)(0, 0, arg, 1);
 			return 1;
@@ -868,6 +873,7 @@
 		}
 		/* fall through */
 	      case ST_CONTINUE:
+	      unpacked_continue:
 		ptr = ptr->fore;
 		break;
 	      case ST_STOP:
Index: ext/-test-/st/numhash/numhash.c
===================================================================
--- ext/-test-/st/numhash/numhash.c	(revision 0)
+++ ext/-test-/st/numhash/numhash.c	(revision 34456)
@@ -0,0 +1,63 @@
+#include <ruby.h>
+#include <ruby/st.h>
+
+static VALUE
+numhash_alloc(VALUE klass)
+{
+    return Data_Wrap_Struct(klass, 0, 0, 0);
+}
+
+static VALUE
+numhash_init(VALUE self)
+{
+    st_table *tbl = (st_table *)DATA_PTR(self);
+    if (tbl) st_free_table(tbl);
+    DATA_PTR(self) = st_init_numtable();
+    return self;
+}
+
+static VALUE
+numhash_aref(VALUE self, VALUE key)
+{
+    st_data_t data;
+    if (!SPECIAL_CONST_P(key)) rb_raise(rb_eArgError, "not a special const");
+    if (st_lookup((st_table *)DATA_PTR(self), (st_data_t)key, &data))
+	return (VALUE)data;
+    return Qnil;
+}
+
+static VALUE
+numhash_aset(VALUE self, VALUE key, VALUE data)
+{
+    if (!SPECIAL_CONST_P(key)) rb_raise(rb_eArgError, "not a special const");
+    if (!SPECIAL_CONST_P(data)) rb_raise(rb_eArgError, "not a special const");
+    st_insert((st_table *)DATA_PTR(self), (st_data_t)key, (st_data_t)data);
+    return self;
+}
+
+static int
+numhash_i(st_data_t key, st_data_t value, st_data_t arg, int error)
+{
+    VALUE ret;
+    if (key == 0 && value == 0 && error == 1) rb_raise(rb_eRuntimeError, "numhash modified");
+    ret = rb_yield_values(3, (VALUE)key, (VALUE)value, (VALUE)arg);
+    if (ret == Qtrue) return ST_CHECK;
+    return ST_CONTINUE;
+}
+
+static VALUE
+numhash_each(VALUE self)
+{
+    return st_foreach((st_table *)DATA_PTR(self), numhash_i, self) ? Qtrue : Qfalse;
+}
+
+void
+Init_numhash(void)
+{
+    VALUE st = rb_define_class_under(rb_define_module("Bug"), "StNumHash", rb_cData);
+    rb_define_alloc_func(st, numhash_alloc);
+    rb_define_method(st, "initialize", numhash_init, 0);
+    rb_define_method(st, "[]", numhash_aref, 1);
+    rb_define_method(st, "[]=", numhash_aset, 2);
+    rb_define_method(st, "each", numhash_each, 0);
+}

Property changes on: ext/-test-/st/numhash/numhash.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ext/-test-/st/numhash/extconf.rb
===================================================================
--- ext/-test-/st/numhash/extconf.rb	(revision 0)
+++ ext/-test-/st/numhash/extconf.rb	(revision 34456)
@@ -0,0 +1 @@
+create_makefile("-test-/st/numhash")

Property changes on: ext/-test-/st/numhash/extconf.rb
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: test/-ext-/st/test_numhash.rb
===================================================================
--- test/-ext-/st/test_numhash.rb	(revision 0)
+++ test/-ext-/st/test_numhash.rb	(revision 34456)
@@ -0,0 +1,21 @@
+require 'test/unit'
+require "-test-/st/numhash"
+
+class Bug::StNumHash
+  class Test_NumHash < Test::Unit::TestCase
+    def setup
+      @tbl = Bug::StNumHash.new
+      5.times {|i| @tbl[i] = i}
+    end
+
+    def test_check
+      keys = []
+      @tbl.each do |k, v, t|
+        keys << k
+        t[5] = 5 if k == 3
+        true
+      end
+      assert_equal([*0..5], keys)
+    end
+  end
+end

Property changes on: test/-ext-/st/test_numhash.rb
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ruby_1_9_3/ChangeLog
===================================================================
--- ruby_1_9_3/ChangeLog	(revision 34455)
+++ ruby_1_9_3/ChangeLog	(revision 34456)
@@ -1,3 +1,8 @@
+Tue Feb  7 14:29:16 2012  Nobuyoshi Nakada  <nobu@r...>
+
+	* st.c (st_foreach): should not yield same pair when checking
+	  after unpacking.
+
 Tue Feb  7 14:03:45 2012  CHIKANAGA Tomoyuki  <nagachika00@g...>
 
 	* lib/tempfile.rb (Tempfile#_close): clear @tempfile and @data[1] even
Index: ruby_1_9_3/st.c
===================================================================
--- ruby_1_9_3/st.c	(revision 34455)
+++ ruby_1_9_3/st.c	(revision 34456)
@@ -745,7 +745,14 @@
             key = (st_data_t)table->bins[i*2];
             val = (st_data_t)table->bins[i*2+1];
             retval = (*func)(key, val, arg);
-	    if (!table->entries_packed) goto unpacked;
+	    if (!table->entries_packed) {
+		FIND_ENTRY(table, ptr, key, i);
+		if (retval == ST_CHECK) {
+		    if (!ptr) goto deleted;
+		    goto unpacked_continue;
+		}
+		goto unpacked;
+	    }
             switch (retval) {
 	      case ST_CHECK:	/* check if hash is modified during iteration */
                 for (j = 0; j < table->num_entries; j++) {
@@ -753,9 +760,7 @@
                         break;
                 }
                 if (j == table->num_entries) {
-                    /* call func with error notice */
-                    retval = (*func)(0, 0, arg, 1);
-                    return 1;
+		    goto deleted;
                 }
 		/* fall through */
 	      case ST_CONTINUE:
@@ -771,11 +776,6 @@
             }
         }
         return 0;
-      unpacked:
-	ptr = table->head;
-	while (i-- > 0) {
-	    if (!(ptr = ptr->fore)) return 0;
-	}
     }
     else {
 	ptr = table->head;
@@ -785,10 +785,12 @@
 	do {
 	    i = ptr->hash % table->num_bins;
 	    retval = (*func)(ptr->key, ptr->record, arg);
+	  unpacked:
 	    switch (retval) {
 	      case ST_CHECK:	/* check if hash is modified during iteration */
 		for (tmp = table->bins[i]; tmp != ptr; tmp = tmp->next) {
 		    if (!tmp) {
+		      deleted:
 			/* call func with error notice */
 			retval = (*func)(0, 0, arg, 1);
 			return 1;
@@ -796,6 +798,7 @@
 		}
 		/* fall through */
 	      case ST_CONTINUE:
+	      unpacked_continue:
 		ptr = ptr->fore;
 		break;
 	      case ST_STOP:
Index: ruby_1_9_3/ext/-test-/st/numhash/numhash.c
===================================================================
--- ruby_1_9_3/ext/-test-/st/numhash/numhash.c	(revision 0)
+++ ruby_1_9_3/ext/-test-/st/numhash/numhash.c	(revision 34456)
@@ -0,0 +1,63 @@
+#include <ruby.h>
+#include <ruby/st.h>
+
+static VALUE
+numhash_alloc(VALUE klass)
+{
+    return Data_Wrap_Struct(klass, 0, 0, 0);
+}
+
+static VALUE
+numhash_init(VALUE self)
+{
+    st_table *tbl = (st_table *)DATA_PTR(self);
+    if (tbl) st_free_table(tbl);
+    DATA_PTR(self) = st_init_numtable();
+    return self;
+}
+
+static VALUE
+numhash_aref(VALUE self, VALUE key)
+{
+    st_data_t data;
+    if (!SPECIAL_CONST_P(key)) rb_raise(rb_eArgError, "not a special const");
+    if (st_lookup((st_table *)DATA_PTR(self), (st_data_t)key, &data))
+	return (VALUE)data;
+    return Qnil;
+}
+
+static VALUE
+numhash_aset(VALUE self, VALUE key, VALUE data)
+{
+    if (!SPECIAL_CONST_P(key)) rb_raise(rb_eArgError, "not a special const");
+    if (!SPECIAL_CONST_P(data)) rb_raise(rb_eArgError, "not a special const");
+    st_insert((st_table *)DATA_PTR(self), (st_data_t)key, (st_data_t)data);
+    return self;
+}
+
+static int
+numhash_i(st_data_t key, st_data_t value, st_data_t arg, int error)
+{
+    VALUE ret;
+    if (key == 0 && value == 0 && error == 1) rb_raise(rb_eRuntimeError, "numhash modified");
+    ret = rb_yield_values(3, (VALUE)key, (VALUE)value, (VALUE)arg);
+    if (ret == Qtrue) return ST_CHECK;
+    return ST_CONTINUE;
+}
+
+static VALUE
+numhash_each(VALUE self)
+{
+    return st_foreach((st_table *)DATA_PTR(self), numhash_i, self) ? Qtrue : Qfalse;
+}
+
+void
+Init_numhash(void)
+{
+    VALUE st = rb_define_class_under(rb_define_module("Bug"), "StNumHash", rb_cData);
+    rb_define_alloc_func(st, numhash_alloc);
+    rb_define_method(st, "initialize", numhash_init, 0);
+    rb_define_method(st, "[]", numhash_aref, 1);
+    rb_define_method(st, "[]=", numhash_aset, 2);
+    rb_define_method(st, "each", numhash_each, 0);
+}

Property changes on: ruby_1_9_3/ext/-test-/st/numhash/numhash.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ruby_1_9_3/ext/-test-/st/numhash/extconf.rb
===================================================================
--- ruby_1_9_3/ext/-test-/st/numhash/extconf.rb	(revision 0)
+++ ruby_1_9_3/ext/-test-/st/numhash/extconf.rb	(revision 34456)
@@ -0,0 +1 @@
+create_makefile("-test-/st/numhash")

Property changes on: ruby_1_9_3/ext/-test-/st/numhash/extconf.rb
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: ruby_1_9_3/version.h
===================================================================
--- ruby_1_9_3/version.h	(revision 34455)
+++ ruby_1_9_3/version.h	(revision 34456)
@@ -1,5 +1,5 @@
 #define RUBY_VERSION "1.9.3"
-#define RUBY_PATCHLEVEL 49
+#define RUBY_PATCHLEVEL 50
 
 #define RUBY_RELEASE_DATE "2012-02-07"
 #define RUBY_RELEASE_YEAR 2012
Index: ruby_1_9_3/test/-ext-/st/test_numhash.rb
===================================================================
--- ruby_1_9_3/test/-ext-/st/test_numhash.rb	(revision 0)
+++ ruby_1_9_3/test/-ext-/st/test_numhash.rb	(revision 34456)
@@ -0,0 +1,21 @@
+require 'test/unit'
+require "-test-/st/numhash"
+
+class Bug::StNumHash
+  class Test_NumHash < Test::Unit::TestCase
+    def setup
+      @tbl = Bug::StNumHash.new
+      5.times {|i| @tbl[i] = i}
+    end
+
+    def test_check
+      keys = []
+      @tbl.each do |k, v, t|
+        keys << k
+        t[5] = 5 if k == 3
+        true
+      end
+      assert_equal([*0..5], keys)
+    end
+  end
+end

Property changes on: ruby_1_9_3/test/-ext-/st/test_numhash.rb
___________________________________________________________________
Added: svn:eol-style
   + LF


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]