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

ruby-changes:38954

From: normal <ko1@a...>
Date: Fri, 26 Jun 2015 04:56:37 +0900 (JST)
Subject: [ruby-changes:38954] normal:r51035 (trunk): Revert r51034 "st.c: use ccan linked-list"

normal	2015-06-26 04:56:20 +0900 (Fri, 26 Jun 2015)

  New Revision: 51035

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

  Log:
    Revert r51034 "st.c: use ccan linked-list"
    
    Maybe this will stop mysterious CI failures from ko1@sasada-8core:
    
    ?\227?\131?\170?\227?\131?\147?\227?\130?\184?\227?\131?\167?\227?\131?\179 51034 ?\227?\129?\167?\227?\129?\153?\227?\128?\130
    make[1]: ?\227?\131?\135?\227?\130?\163?\227?\131?\172?\227?\130?\175?\227?\131?\136?\227?\131?\170 `/mnt/sdb1/ruby/build' ?\227?\129?\171?\229?\133?\165?\227?\130?\138?\227?\129?\190?\227?\129?\153
    ../trunk/revision.h unchanged
    make[1]: ?\227?\131?\135?\227?\130?\163?\227?\131?\172?\227?\130?\175?\227?\131?\136?\227?\131?\170 `/mnt/sdb1/ruby/build' ?\227?\129?\139?\227?\130?\137?\229?\135?\186?\227?\129?\190?\227?\129?\153
    make[1]: ?\227?\131?\135?\227?\130?\163?\227?\131?\172?\227?\130?\175?\227?\131?\136?\227?\131?\170 `/mnt/sdb1/ruby/build' ?\227?\129?\171?\229?\133?\165?\227?\130?\138?\227?\129?\190?\227?\129?\153
    config.guess already exists
    config.sub already exists
    generating ../trunk/ext/ripper/ripper.c
    make[2]: ?\227?\131?\135?\227?\130?\163?\227?\131?\172?\227?\130?\175?\227?\131?\136?\227?\131?\170 `/mnt/sdb1/ruby/trunk/ext/ripper' ?\227?\129?\171?\229?\133?\165?\227?\130?\138?\227?\129?\190?\227?\129?\153
    extracting ripper.y from ../../parse.y
    id.h not found in ["../.."]
    make[2]: *** [ripper.y] ?\227?\130?\168?\227?\131?\169?\227?\131?\188 1
    make[2]: ?\227?\131?\135?\227?\130?\163?\227?\131?\172?\227?\130?\175?\227?\131?\136?\227?\131?\170 `/mnt/sdb1/ruby/trunk/ext/ripper' ?\227?\129?\139?\227?\130?\137?\229?\135?\186?\227?\129?\190?\227?\129?\153
    make[1]: *** [../trunk/ext/ripper/ripper.c] ?\227?\130?\168?\227?\131?\169?\227?\131?\188 2
    make[1]: ?\227?\131?\135?\227?\130?\163?\227?\131?\172?\227?\130?\175?\227?\131?\136?\227?\131?\170 `/mnt/sdb1/ruby/build' ?\227?\129?\139?\227?\130?\137?\229?\135?\186?\227?\129?\190?\227?\129?\153
    make: [up] ?\227?\130?\168?\227?\131?\169?\227?\131?\188 2 (?\231?\132?\161?\232?\166?\150?\227?\129?\149?\227?\130?\140?\227?\129?\190?\227?\129?\151?\227?\129?\159)
    make: *** [.rbconfig.time] ?\227?\130?\187?\227?\130?\176?\227?\131?\161?\227?\131?\179?\227?\131?\134?\227?\131?\188?\227?\130?\183?\227?\131?\167?\227?\131?\179?\233?\129?\149?\229?\143?\141?\227?\129?\167?\227?\129?\153
    Command exited with non-zero status 2

  Modified files:
    trunk/ChangeLog
    trunk/include/ruby/st.h
    trunk/st.c
Index: include/ruby/st.h
===================================================================
--- include/ruby/st.h	(revision 51034)
+++ include/ruby/st.h	(revision 51035)
@@ -86,7 +86,7 @@ struct st_table { https://github.com/ruby/ruby/blob/trunk/include/ruby/st.h#L86
     union {
 	struct {
 	    struct st_table_entry **bins;
-	    void *private_list_head[2];
+	    struct st_table_entry *head, *tail;
 	} big;
 	struct {
 	    struct st_packed_entry *entries;
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 51034)
+++ ChangeLog	(revision 51035)
@@ -1,26 +1,3 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
-Fri Jun 26 03:52:27 2015  Eric Wong  <e@8...>
-
-	* include/ruby/st.h (struct st_table): hide struct list_head
-	* st.c (struct st_table_entry): adjust struct
-	  (head, tail): remove shortcut macros
-	  (st_head): new wrapper function
-	  (st_init_table_with_size): adjust to new struct and API
-	  (st_clear): ditto
-	  (add_direct): ditto
-	  (unpack_entries): ditto
-	  (rehash): ditto
-	  (st_copy): ditto
-	  (remove_entry): ditto
-	  (st_shift): ditto
-	  (st_foreach_check): ditto
-	  (st_foreach): ditto
-	  (get_keys): ditto
-	  (get_values): ditto
-	  (st_values_check): ditto
-	  (st_reverse_foreach_check): ditto (unused)
-	  (st_reverse_foreach): ditto (unused)
-	  [ruby-core:69726] [Misc #10278]
-
 Thu Jun 25 21:24:28 2015  Naohisa Goto  <ngotogenome@g...>
 
 	* test/-ext-/popen_deadlock/test_popen_deadlock.rb: test [Bug #11265]
Index: st.c
===================================================================
--- st.c	(revision 51034)
+++ st.c	(revision 51035)
@@ -14,7 +14,6 @@ https://github.com/ruby/ruby/blob/trunk/st.c#L14
 #include <stdlib.h>
 #endif
 #include <string.h>
-#include "ccan/list/list.h"
 
 typedef struct st_table_entry st_table_entry;
 
@@ -23,7 +22,7 @@ struct st_table_entry { https://github.com/ruby/ruby/blob/trunk/st.c#L22
     st_data_t key;
     st_data_t record;
     st_table_entry *next;
-    struct list_node olist;
+    st_table_entry *fore, *back;
 };
 
 typedef struct st_packed_entry {
@@ -108,6 +107,8 @@ st_realloc_bins(st_table_entry **bins, s https://github.com/ruby/ruby/blob/trunk/st.c#L107
 
 /* Shortcut */
 #define bins as.big.bins
+#define head as.big.head
+#define tail as.big.tail
 #define real_entries as.packed.real_entries
 
 /* preparation for possible packing improvements */
@@ -193,12 +194,6 @@ stat_col(void) https://github.com/ruby/ruby/blob/trunk/st.c#L194
 }
 #endif
 
-static struct list_head *
-st_head(const st_table *tbl)
-{
-    return (struct list_head *)&tbl->as.big.private_list_head;
-}
-
 st_table*
 st_init_table_with_size(const struct st_hash_type *type, st_index_t size)
 {
@@ -224,14 +219,14 @@ st_init_table_with_size(const struct st_ https://github.com/ruby/ruby/blob/trunk/st.c#L219
     tbl->entries_packed = size <= MAX_PACKED_HASH;
     if (tbl->entries_packed) {
 	size = ST_DEFAULT_PACKED_TABLE_SIZE;
-	tbl->real_entries = 0;
     }
     else {
 	size = new_size(size);	/* round up to power-of-two */
-	list_head_init(st_head(tbl));
     }
     tbl->num_bins = size;
     tbl->bins = st_alloc_bins(size);
+    tbl->head = 0;
+    tbl->tail = 0;
 
     return tbl;
 }
@@ -282,6 +277,7 @@ void https://github.com/ruby/ruby/blob/trunk/st.c#L277
 st_clear(st_table *table)
 {
     register st_table_entry *ptr, *next;
+    st_index_t i;
 
     if (table->entries_packed) {
         table->num_entries = 0;
@@ -289,13 +285,18 @@ st_clear(st_table *table) https://github.com/ruby/ruby/blob/trunk/st.c#L285
         return;
     }
 
-    list_for_each_safe(st_head(table), ptr, next, olist) {
-	/* list_del is not needed */
-	st_free_entry(ptr);
+    for (i = 0; i < table->num_bins; i++) {
+	ptr = table->bins[i];
+	table->bins[i] = 0;
+	while (ptr != 0) {
+	    next = ptr->next;
+	    st_free_entry(ptr);
+	    ptr = next;
+	}
     }
     table->num_entries = 0;
-    MEMZERO(table->bins, st_table_entry*, table->num_bins);
-    list_head_init(st_head(table));
+    table->head = 0;
+    table->tail = 0;
 }
 
 void
@@ -463,7 +464,16 @@ add_direct(st_table *table, st_data_t ke https://github.com/ruby/ruby/blob/trunk/st.c#L464
     }
 
     entry = new_entry(table, key, value, hash_val, bin_pos);
-    list_add_tail(st_head(table), &entry->olist);
+
+    if (table->head != 0) {
+	entry->fore = 0;
+	(entry->back = table->tail)->fore = entry;
+	table->tail = entry;
+    }
+    else {
+	table->head = table->tail = entry;
+	entry->fore = entry->back = 0;
+    }
     table->num_entries++;
 }
 
@@ -472,7 +482,7 @@ unpack_entries(register st_table *table) https://github.com/ruby/ruby/blob/trunk/st.c#L482
 {
     st_index_t i;
     st_packed_entry packed_bins[MAX_PACKED_HASH];
-    register st_table_entry *entry;
+    register st_table_entry *entry, *preventry = 0, **chain;
     st_table tmp_table = *table;
 
     MEMCPY(packed_bins, PACKED_BINS(table), st_packed_entry, MAX_PACKED_HASH);
@@ -484,24 +494,22 @@ unpack_entries(register st_table *table) https://github.com/ruby/ruby/blob/trunk/st.c#L494
     tmp_table.bins = st_realloc_bins(tmp_table.bins, ST_DEFAULT_INIT_TABLE_SIZE, tmp_table.num_bins);
     tmp_table.num_bins = ST_DEFAULT_INIT_TABLE_SIZE;
 #endif
-
-    /*
-     * order is important here, we need to keep the original table
-     * walkable during GC (GC may be triggered by new_entry call)
-     */
     i = 0;
-    list_head_init(st_head(&tmp_table));
+    chain = &tmp_table.head;
     do {
 	st_data_t key = packed_bins[i].key;
 	st_data_t val = packed_bins[i].val;
 	st_index_t hash = packed_bins[i].hash;
 	entry = new_entry(&tmp_table, key, val, hash,
 			  hash_pos(hash, ST_DEFAULT_INIT_TABLE_SIZE));
-	list_add_tail(st_head(&tmp_table), &entry->olist);
+	*chain = entry;
+	entry->back = preventry;
+	preventry = entry;
+	chain = &entry->fore;
     } while (++i < MAX_PACKED_HASH);
+    *chain = NULL;
+    tmp_table.tail = entry;
     *table = tmp_table;
-    list_head_init(st_head(table));
-    list_append_list(st_head(table), st_head(&tmp_table));
 }
 
 static void
@@ -611,10 +619,12 @@ rehash(register st_table *table) https://github.com/ruby/ruby/blob/trunk/st.c#L619
     table->num_bins = new_num_bins;
     table->bins = new_bins;
 
-    list_for_each(st_head(table), ptr, olist) {
-	hash_val = hash_pos(ptr->hash, new_num_bins);
-	ptr->next = new_bins[hash_val];
-	new_bins[hash_val] = ptr;
+    if ((ptr = table->head) != 0) {
+	do {
+	    hash_val = hash_pos(ptr->hash, new_num_bins);
+	    ptr->next = new_bins[hash_val];
+	    new_bins[hash_val] = ptr;
+	} while ((ptr = ptr->fore) != 0);
     }
 }
 
@@ -622,8 +632,9 @@ st_table* https://github.com/ruby/ruby/blob/trunk/st.c#L632
 st_copy(st_table *old_table)
 {
     st_table *new_table;
-    st_table_entry *ptr, *entry;
+    st_table_entry *ptr, *entry, *prev, **tailp;
     st_index_t num_bins = old_table->num_bins;
+    st_index_t hash_val;
 
     new_table = st_alloc_table();
     if (new_table == 0) {
@@ -643,12 +654,24 @@ st_copy(st_table *old_table) https://github.com/ruby/ruby/blob/trunk/st.c#L654
         return new_table;
     }
 
-    list_head_init(st_head(new_table));
-
-    list_for_each(st_head(old_table), ptr, olist) {
-	entry = new_entry(new_table, ptr->key, ptr->record, ptr->hash,
-			    hash_pos(ptr->hash, num_bins));
-	list_add_tail(st_head(new_table), &entry->olist);
+    if ((ptr = old_table->head) != 0) {
+	prev = 0;
+	tailp = &new_table->head;
+	do {
+	    entry = st_alloc_entry();
+	    if (entry == 0) {
+		st_free_table(new_table);
+		return 0;
+	    }
+	    *entry = *ptr;
+	    hash_val = hash_pos(entry->hash, num_bins);
+	    entry->next = new_table->bins[hash_val];
+	    new_table->bins[hash_val] = entry;
+	    entry->back = prev;
+	    *tailp = prev = entry;
+	    tailp = &entry->fore;
+	} while ((ptr = ptr->fore) != 0);
+	new_table->tail = prev;
     }
 
     return new_table;
@@ -657,7 +680,17 @@ st_copy(st_table *old_table) https://github.com/ruby/ruby/blob/trunk/st.c#L680
 static inline void
 remove_entry(st_table *table, st_table_entry *ptr)
 {
-    list_del(&ptr->olist);
+    if (ptr->fore == 0 && ptr->back == 0) {
+	table->head = 0;
+	table->tail = 0;
+    }
+    else {
+	st_table_entry *fore = ptr->fore, *back = ptr->back;
+	if (fore) fore->back = back;
+	if (back) back->fore = fore;
+	if (ptr == table->head) table->head = fore;
+	if (ptr == table->tail) table->tail = back;
+    }
     table->num_entries--;
 }
 
@@ -737,7 +770,6 @@ st_delete_safe(register st_table *table, https://github.com/ruby/ruby/blob/trunk/st.c#L770
 int
 st_shift(register st_table *table, register st_data_t *key, st_data_t *value)
 {
-    st_table_entry *old;
     st_table_entry **prev;
     register st_table_entry *ptr;
 
@@ -753,13 +785,12 @@ st_shift(register st_table *table, regis https://github.com/ruby/ruby/blob/trunk/st.c#L785
         return 1;
     }
 
-    old = list_pop(st_head(table), st_table_entry, olist);
-    table->num_entries--;
-    prev = &table->bins[hash_pos(old->hash, table->num_bins)];
-    while ((ptr = *prev) != old) prev = &ptr->next;
+    prev = &table->bins[hash_pos(table->head->hash, table->num_bins)];
+    while ((ptr = *prev) != table->head) prev = &ptr->next;
     *prev = ptr->next;
     if (value != 0) *value = ptr->record;
     *key = ptr->key;
+    remove_entry(table, ptr);
     st_free_entry(ptr);
     return 1;
 }
@@ -886,8 +917,7 @@ st_update(st_table *table, st_data_t key https://github.com/ruby/ruby/blob/trunk/st.c#L917
 int
 st_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t never)
 {
-    st_table_entry *ptr, **last, *tmp, *next;
-    struct list_head *head;
+    st_table_entry *ptr, **last, *tmp;
     enum st_retval retval;
     st_index_t i;
 
@@ -904,10 +934,8 @@ st_foreach_check(st_table *table, int (* https://github.com/ruby/ruby/blob/trunk/st.c#L934
 		FIND_ENTRY(table, ptr, hash, i);
 		if (retval == ST_CHECK) {
 		    if (!ptr) goto deleted;
+		    goto unpacked_continue;
 		}
-		if (table->num_entries == 0) return 0;
-		head = st_head(table);
-		next = list_entry(ptr->olist.next, st_table_entry, olist);
 		goto unpacked;
 	    }
 	    switch (retval) {
@@ -932,10 +960,14 @@ st_foreach_check(st_table *table, int (* https://github.com/ruby/ruby/blob/trunk/st.c#L960
 	}
 	return 0;
     }
+    else {
+	ptr = table->head;
+    }
 
-    head = st_head(table);
-    list_for_each_safe(head, ptr, next, olist) {
-	if (ptr->key != never) {
+    if (ptr != 0) {
+	do {
+	    if (ptr->key == never)
+		goto unpacked_continue;
 	    i = hash_pos(ptr->hash, table->num_bins);
 	    retval = (*func)(ptr->key, ptr->record, arg, 0);
 	  unpacked:
@@ -951,6 +983,8 @@ st_foreach_check(st_table *table, int (* https://github.com/ruby/ruby/blob/trunk/st.c#L983
 		}
 		/* fall through */
 	      case ST_CONTINUE:
+	      unpacked_continue:
+		ptr = ptr->fore;
 		break;
 	      case ST_STOP:
 		return 0;
@@ -958,15 +992,16 @@ st_foreach_check(st_table *table, int (* https://github.com/ruby/ruby/blob/trunk/st.c#L992
 		last = &table->bins[hash_pos(ptr->hash, table->num_bins)];
 		for (; (tmp = *last) != 0; last = &tmp->next) {
 		    if (ptr == tmp) {
+			tmp = ptr->fore;
 			remove_entry(table, ptr);
 			ptr->key = ptr->record = never;
 			ptr->hash = 0;
+			ptr = tmp;
 			break;
 		    }
 		}
-		if (table->num_entries == 0) return 0;
 	    }
-	}
+	} while (ptr && table->head);
     }
     return 0;
 }
@@ -974,9 +1009,8 @@ st_foreach_check(st_table *table, int (* https://github.com/ruby/ruby/blob/trunk/st.c#L1009
 int
 st_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
 {
-    st_table_entry *ptr, **last, *tmp, *next;
+    st_table_entry *ptr, **last, *tmp;
     enum st_retval retval;
-    struct list_head *head;
     st_index_t i;
 
     if (table->entries_packed) {
@@ -990,8 +1024,6 @@ st_foreach(st_table *table, int (*func)( https://github.com/ruby/ruby/blob/trunk/st.c#L1024
 	    if (!table->entries_packed) {
 		FIND_ENTRY(table, ptr, hash, i);
 		if (!ptr) return 0;
-		head = st_head(table);
-		next = list_entry(ptr->olist.next, st_table_entry, olist);
 		goto unpacked;
 	    }
 	    switch (retval) {
@@ -1008,30 +1040,36 @@ st_foreach(st_table *table, int (*func)( https://github.com/ruby/ruby/blob/trunk/st.c#L1040
 	}
 	return 0;
     }
+    else {
+	ptr = table->head;
+    }
 
-    head = st_head(table);
-    list_for_each_safe(head, ptr, next, olist) {
-	i = hash_pos(ptr->hash, table->num_bins);
-	retval = (*func)(ptr->key, ptr->record, arg, 0);
-      unpacked:
-	switch (retval) {
-	  case ST_CONTINUE:
-	    break;
-	  case ST_CHECK:
-	  case ST_STOP:
-	    return 0;
-	  case ST_DELETE:
-	    last = &table->bins[hash_pos(ptr->hash, table->num_bins)];
-	    for (; (tmp = *last) != 0; last = &tmp->next) {
-		if (ptr == tmp) {
-		    *last = ptr->next;
-		    remove_entry(table, ptr);
-		    st_free_entry(ptr);
-		    break;
+    if (ptr != 0) {
+	do {
+	    i = hash_pos(ptr->hash, table->num_bins);
+	    retval = (*func)(ptr->key, ptr->record, arg, 0);
+	  unpacked:
+	    switch (retval) {
+	      case ST_CONTINUE:
+		ptr = ptr->fore;
+		break;
+	      case ST_CHECK:
+	      case ST_STOP:
+		return 0;
+	      case ST_DELETE:
+		last = &table->bins[hash_pos(ptr->hash, table->num_bins)];
+		for (; (tmp = *last) != 0; last = &tmp->next) {
+		    if (ptr == tmp) {
+			tmp = ptr->fore;
+			*last = ptr->next;
+			remove_entry(table, ptr);
+			st_free_entry(ptr);
+			ptr = tmp;
+			break;
+		    }
 		}
 	    }
-	    if (table->num_entries == 0) return 0;
-	}
+	} while (ptr && table->head);
     }
     return 0;
 }
@@ -1053,11 +1091,9 @@ get_keys(st_table *table, st_data_t *key https://github.com/ruby/ruby/blob/trunk/st.c#L1091
 	}
     }
     else {
-	st_table_entry *ptr;
+	st_table_entry *ptr = table->head;
 	st_data_t *keys_end = keys + size;
-
-	list_for_each(st_head(table), ptr, olist) {
-	    if (keys >= keys_end) break;
+	for (; ptr && keys < keys_end; ptr = ptr->fore) {
 	    key = ptr->key;
 	    if (check && key == never) continue;
 	    *keys++ = key;
@@ -1096,11 +1132,9 @@ get_values(st_table *table, st_data_t *v https://github.com/ruby/ruby/blob/trunk/st.c#L1132
 	}
     }
     else {
-	st_table_entry *ptr;
+	st_table_entry *ptr = table->head;
 	st_data_t *values_end = values + size;
-
-	list_for_each(st_head(table), ptr, olist) {
-	    if (values >= values_end) break;
+	for (; ptr && values < values_end; ptr = ptr->fore) {
 	    key = ptr->key;
 	    if (check && key == never) continue;
 	    *values++ = ptr->record;
@@ -1126,8 +1160,7 @@ st_values_check(st_table *table, st_data https://github.com/ruby/ruby/blob/trunk/st.c#L1160
 int
 st_reverse_foreach_check(st_table *table, int (*func)(ANYARGS), st_data_t arg, st_data_t never)
 {
-    st_table_entry *ptr, **last, *tmp, *next;
-    struct list_head *head;
+    st_table_entry *ptr, **last, *tmp;
     enum st_retval retval;
     st_index_t i;
 
@@ -1145,10 +1178,8 @@ st_reverse_foreach_check(st_table *table https://github.com/ruby/ruby/blob/trunk/st.c#L1178
 		FIND_ENTRY(table, ptr, hash, i);
 		if (retval == ST_CHECK) {
 		    if (!ptr) goto deleted;
+		    goto unpacked_continue;
 		}
-		if (table->num_entries == 0) return 0;
-		head = st_head(table);
-		next = list_entry(ptr->olist.next, st_table_entry, olist);
 		goto unpacked;
 	    }
 	    switch (retval) {
@@ -1173,10 +1204,14 @@ st_reverse_foreach_check(st_table *table https://github.com/ruby/ruby/blob/trunk/st.c#L1204
 	}
 	return 0;
     }
+    else {
+	ptr = table->tail;
+    }
 
-    head = st_head(table);
-    list_for_each_rev_safe(head, ptr, next, olist) {
-	if (ptr->key != never) {
+    if (ptr != 0) {
+	do {
+	    if (ptr->key == never)
+		goto unpacked_continue;
 	    i = hash_pos(ptr->hash, table->num_bins);
 	    retval = (*func)(ptr->key, ptr->record, arg, 0);
 	  unpacked:
@@ -1192,6 +1227,8 @@ st_reverse_foreach_check(st_table *table https://github.com/ruby/ruby/blob/trunk/st.c#L1227
 		}
 		/* fall through */
 	      case ST_CONTINUE:
+	      unpacked_continue:
+		ptr = ptr->back;
 		break;
 	      case ST_STOP:
 		return 0;
@@ -1199,15 +1236,16 @@ st_reverse_foreach_check(st_table *table https://github.com/ruby/ruby/blob/trunk/st.c#L1236
 		last = &table->bins[hash_pos(ptr->hash, table->num_bins)];
 		for (; (tmp = *last) != 0; last = &tmp->next) {
 		    if (ptr == tmp) {
+			tmp = ptr->back;
 			remove_entry(table, ptr);
 			ptr->key = ptr->record = never;
 			ptr->hash = 0;
+			ptr = tmp;
 			break;
 		    }
 		}
-		if (table->num_entries == 0) return 0;
 	    }
-	}
+	} while (ptr && table->head);
     }
     return 0;
 }
@@ -1215,9 +1253,8 @@ st_reverse_foreach_check(st_table *table https://github.com/ruby/ruby/blob/trunk/st.c#L1253
 int
 st_reverse_foreach(st_table *table, int (*func)(ANYARGS), st_data_t arg)
 {
-    st_table_entry *ptr, **last, *tmp, *next;
+    st_table_entry *ptr, **last, *tmp;
     enum st_retval retval;
-    struct list_head *head;
     st_index_t i;
 
     if (table->entries_packed) {
@@ -1232,8 +1269,6 @@ st_reverse_foreach(st_table *table, int https://github.com/ruby/ruby/blob/trunk/st.c#L1269
 	    if (!table->entries_packed) {
 		FIND_ENTRY(table, ptr, hash, i);
 		if (!ptr) return 0;
-		head = st_head(table);
-		next = list_entry(ptr->olist.next, st_table_entry, olist);
 		goto unpacked;
 	    }
 	    switch (retval) {
@@ -1249,30 +1284,36 @@ st_reverse_foreach(st_table *table, int https://github.com/ruby/ruby/blob/trunk/st.c#L1284
 	}
 	return 0;
     }
+    else {
+	ptr = table->tail;
+    }
 
-    head = st_head(table);
-    list_for_each_rev_safe(head, ptr, next, olist) {
-	i = hash_pos(ptr->hash, table->num_bins);
-	retval = (*func)(ptr->key, ptr->record, arg, 0);
-      unpacked:
-	switch (retval) {
-	  case ST_CONTINUE:
-	    break;
-	  case ST_CHECK:
-	  case ST_STOP:
-	    return 0;
-	  case ST_DELETE:
-	    last = &table->bins[hash_pos(ptr->hash, table->num_bins)];
-	    for (; (tmp = *last) != 0; last = &tmp->next) {
-		if (ptr == tmp) {
-		    *last = ptr->next;
-		    remove_entry(table, ptr);
-		    st_free_entry(ptr);
-		    break;
+    if (ptr != 0) {
+	do {
+	    i = hash_pos(ptr->hash, table->num_bins);
+	    retval = (*func)(ptr->key, ptr->record, arg, 0);
+	  unpacked:
+	    switch (retval) {
+	      case ST_CONTINUE:
+		ptr = ptr->back;
+		break;
+	      case ST_CHECK:
+	      case ST_STOP:
+		return 0;
+	      case ST_DELETE:
+		last = &table->bins[hash_pos(ptr->hash, table->num_bins)];
+		for (; (tmp = *last) != 0; last = &tmp->next) {
+		    if (ptr == tmp) {
+			tmp = ptr->back;
+			*last = ptr->next;
+			remove_entry(table, ptr);
+			st_free_entry(ptr);
+			ptr = tmp;
+			break;
+		    }
 		}
 	    }
-	    if (table->num_entries == 0) return 0;
-	}
+	} while (ptr && table->head);
     }
     return 0;
 }

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

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