Lisp_Object Qhash_tablep;
static Lisp_Object Qhashtable, Qhash_table;
-static Lisp_Object Qweakness, Qvalue, Qkey_value;
+static Lisp_Object Qweakness, Qvalue, Qkey_or_value, Qkey_and_value;
static Lisp_Object Vall_weak_hash_tables;
static Lisp_Object Qrehash_size, Qrehash_threshold;
static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold;
/* obsolete as of 19990901 in xemacs-21.2 */
-static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qkey_value_weak;
+static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qkey_or_value_weak;
static Lisp_Object Qnon_weak, Q_type;
typedef struct hentry
#define HASH_TABLE_MIN_SIZE 10
#define HASH_CODE(key, ht) \
-((((ht)->hash_function ? (ht)->hash_function (key) : LISP_HASH (key)) \
- * (ht)->golden_ratio) \
- % (ht)->size)
+ ((((ht)->hash_function ? (ht)->hash_function (key) : LISP_HASH (key)) \
+ * (ht)->golden_ratio) \
+ % (ht)->size)
#define KEYS_EQUAL_P(key1, key2, testfun) \
(EQ (key1, key2) || ((testfun) && (testfun) (key1, key2)))
`size' (a natnum or nil)
`rehash-size' (a float)
`rehash-threshold' (a float)
- `weakness' (nil, t, key or value)
+ `weakness' (nil, key, value, key-and-value, or key-or-value)
`data' (a list)
If `print-readably' is nil, then a simpler syntax is used, for example
if (ht->weakness != HASH_TABLE_NON_WEAK)
{
sprintf (buf, " weakness %s",
- (ht->weakness == HASH_TABLE_WEAK ? "t" :
- ht->weakness == HASH_TABLE_KEY_WEAK ? "key" :
- ht->weakness == HASH_TABLE_VALUE_WEAK ? "value" :
- ht->weakness == HASH_TABLE_KEY_VALUE_WEAK ? "key-value" :
+ (ht->weakness == HASH_TABLE_WEAK ? "key-and-value" :
+ ht->weakness == HASH_TABLE_KEY_WEAK ? "key" :
+ ht->weakness == HASH_TABLE_VALUE_WEAK ? "value" :
+ ht->weakness == HASH_TABLE_KEY_VALUE_WEAK ? "key-or-value" :
"you-d-better-not-see-this"));
write_c_string (buf, printcharfun);
}
}
Lisp_Object
-make_general_lisp_hash_table (enum hash_table_test test,
- size_t size,
- double rehash_size,
- double rehash_threshold,
- enum hash_table_weakness weakness)
+make_standard_lisp_hash_table (enum hash_table_test test,
+ size_t size,
+ double rehash_size,
+ double rehash_threshold,
+ enum hash_table_weakness weakness)
{
- Lisp_Object hash_table;
- Lisp_Hash_Table *ht = alloc_lcrecord_type (Lisp_Hash_Table, &lrecord_hash_table);
+ hash_table_hash_function_t hash_function = 0;
+ hash_table_test_function_t test_function = 0;
switch (test)
{
case HASH_TABLE_EQ:
- ht->test_function = 0;
- ht->hash_function = 0;
+ test_function = 0;
+ hash_function = 0;
break;
case HASH_TABLE_EQL:
- ht->test_function = lisp_object_eql_equal;
- ht->hash_function = lisp_object_eql_hash;
+ test_function = lisp_object_eql_equal;
+ hash_function = lisp_object_eql_hash;
break;
case HASH_TABLE_EQUAL:
- ht->test_function = lisp_object_equal_equal;
- ht->hash_function = lisp_object_equal_hash;
+ test_function = lisp_object_equal_equal;
+ hash_function = lisp_object_equal_hash;
break;
default:
abort ();
}
+ return make_general_lisp_hash_table (hash_function, test_function,
+ size, rehash_size, rehash_threshold,
+ weakness);
+}
+
+Lisp_Object
+make_general_lisp_hash_table (hash_table_hash_function_t hash_function,
+ hash_table_test_function_t test_function,
+ size_t size,
+ double rehash_size,
+ double rehash_threshold,
+ enum hash_table_weakness weakness)
+{
+ Lisp_Object hash_table;
+ Lisp_Hash_Table *ht = alloc_lcrecord_type (Lisp_Hash_Table, &lrecord_hash_table);
+
+ ht->test_function = test_function;
+ ht->hash_function = hash_function;
ht->weakness = weakness;
ht->rehash_size =
compute_hash_table_derived_values (ht);
/* We leave room for one never-occupied sentinel hentry at the end. */
- ht->hentries = xnew_array (hentry, ht->size + 1);
-
- {
- hentry *e, *sentinel;
- for (e = ht->hentries, sentinel = e + ht->size; e <= sentinel; e++)
- CLEAR_HENTRY (e);
- }
+ ht->hentries = xnew_array_and_zero (hentry, ht->size + 1);
XSETHASH_TABLE (hash_table, ht);
enum hash_table_weakness weakness,
enum hash_table_test test)
{
- return make_general_lisp_hash_table (test, size, -1.0, -1.0, weakness);
+ return make_standard_lisp_hash_table (test, size, -1.0, -1.0, weakness);
}
/* Pretty reading of hash tables.
hash_table_weakness_validate (Lisp_Object keyword, Lisp_Object value,
Error_behavior errb)
{
- if (EQ (value, Qnil)) return 1;
- if (EQ (value, Qt)) return 1;
- if (EQ (value, Qkey)) return 1;
- if (EQ (value, Qkey_value)) return 1;
- if (EQ (value, Qvalue)) return 1;
+ if (EQ (value, Qnil)) return 1;
+ if (EQ (value, Qt)) return 1;
+ if (EQ (value, Qkey)) return 1;
+ if (EQ (value, Qkey_and_value)) return 1;
+ if (EQ (value, Qkey_or_value)) return 1;
+ if (EQ (value, Qvalue)) return 1;
/* Following values are obsolete as of 19990901 in xemacs-21.2 */
- if (EQ (value, Qnon_weak)) return 1;
- if (EQ (value, Qweak)) return 1;
- if (EQ (value, Qkey_weak)) return 1;
- if (EQ (value, Qkey_value_weak)) return 1;
- if (EQ (value, Qvalue_weak)) return 1;
+ if (EQ (value, Qnon_weak)) return 1;
+ if (EQ (value, Qweak)) return 1;
+ if (EQ (value, Qkey_weak)) return 1;
+ if (EQ (value, Qkey_or_value_weak)) return 1;
+ if (EQ (value, Qvalue_weak)) return 1;
maybe_signal_simple_error ("Invalid hash table weakness",
value, Qhash_table, errb);
static enum hash_table_weakness
decode_hash_table_weakness (Lisp_Object obj)
{
- if (EQ (obj, Qnil)) return HASH_TABLE_NON_WEAK;
- if (EQ (obj, Qt)) return HASH_TABLE_WEAK;
- if (EQ (obj, Qkey)) return HASH_TABLE_KEY_WEAK;
- if (EQ (obj, Qkey_value)) return HASH_TABLE_KEY_VALUE_WEAK;
- if (EQ (obj, Qvalue)) return HASH_TABLE_VALUE_WEAK;
+ if (EQ (obj, Qnil)) return HASH_TABLE_NON_WEAK;
+ if (EQ (obj, Qt)) return HASH_TABLE_WEAK;
+ if (EQ (obj, Qkey_and_value)) return HASH_TABLE_WEAK;
+ if (EQ (obj, Qkey)) return HASH_TABLE_KEY_WEAK;
+ if (EQ (obj, Qkey_or_value)) return HASH_TABLE_KEY_VALUE_WEAK;
+ if (EQ (obj, Qvalue)) return HASH_TABLE_VALUE_WEAK;
/* Following values are obsolete as of 19990901 in xemacs-21.2 */
- if (EQ (obj, Qnon_weak)) return HASH_TABLE_NON_WEAK;
- if (EQ (obj, Qweak)) return HASH_TABLE_WEAK;
- if (EQ (obj, Qkey_weak)) return HASH_TABLE_KEY_WEAK;
- if (EQ (obj, Qkey_value_weak)) return HASH_TABLE_KEY_VALUE_WEAK;
- if (EQ (obj, Qvalue_weak)) return HASH_TABLE_VALUE_WEAK;
+ if (EQ (obj, Qnon_weak)) return HASH_TABLE_NON_WEAK;
+ if (EQ (obj, Qweak)) return HASH_TABLE_WEAK;
+ if (EQ (obj, Qkey_weak)) return HASH_TABLE_KEY_WEAK;
+ if (EQ (obj, Qkey_or_value_weak)) return HASH_TABLE_KEY_VALUE_WEAK;
+ if (EQ (obj, Qvalue_weak)) return HASH_TABLE_VALUE_WEAK;
signal_simple_error ("Invalid hash table weakness", obj);
return HASH_TABLE_NON_WEAK; /* not reached */
}
/* Create the hash table. */
- hash_table = make_general_lisp_hash_table
+ hash_table = make_standard_lisp_hash_table
(decode_hash_table_test (test),
decode_hash_table_size (size),
decode_hash_table_rehash_size (rehash_size),
Keyword :rehash-threshold must be a float between 0.0 and 1.0,
and specifies the load factor of the hash table which triggers enlarging.
-Non-standard keyword :weakness can be `nil' (default), `t', `key', `value'
-or `key-value'.
+Non-standard keyword :weakness can be `nil' (default), `t', `key-and-value',
+`key', `value' or `key-or-value'. `t' is an alias for `key-and-value'.
-A weak hash table is one whose pointers do not count as GC referents:
-for any key-value pair in the hash table, if the only remaining pointer
-to either the key or the value is in a weak hash table, then the pair
-will be removed from the hash table, and the key and value collected.
-A non-weak hash table (or any other pointer) would prevent the object
-from being collected.
+A key-and-value-weak hash table, also known as a fully-weak or simply
+as a weak hash table, is one whose pointers do not count as GC
+referents: for any key-value pair in the hash table, if the only
+remaining pointer to either the key or the value is in a weak hash
+table, then the pair will be removed from the hash table, and the key
+and value collected. A non-weak hash table (or any other pointer)
+would prevent the object from being collected.
A key-weak hash table is similar to a fully-weak hash table except that
a key-value pair will be removed only if the key remains unmarked
hash table if the value is pointed to by something other than a weak
hash table, even if the key is not.
-A key-value-weak hash table is similar to a fully-weak hash table except
+A key-or-value-weak hash table is similar to a fully-weak hash table except
that a key-value pair will be removed only if the value and the key remain
unmarked outside of weak hash tables. The pair will remain in the
hash table if the value or key are pointed to by something other than a weak
VALIDATE_VAR (rehash_threshold);
VALIDATE_VAR (weakness);
- return make_general_lisp_hash_table
+ return make_standard_lisp_hash_table
(decode_hash_table_test (test),
decode_hash_table_size (size),
decode_hash_table_rehash_size (rehash_size),
DEFUN ("hash-table-weakness", Fhash_table_weakness, 1, 1, 0, /*
Return the weakness of HASH-TABLE.
-This can be one of `nil', `t', `key' or `value'.
+This can be one of `nil', `key-and-value', `key-or-value', `key' or `value'.
*/
(hash_table))
{
switch (xhash_table (hash_table)->weakness)
{
- case HASH_TABLE_WEAK: return Qt;
- case HASH_TABLE_KEY_WEAK: return Qkey;
- case HASH_TABLE_KEY_VALUE_WEAK: return Qkey_value;
- case HASH_TABLE_VALUE_WEAK: return Qvalue;
- default: return Qnil;
+ case HASH_TABLE_WEAK: return Qkey_and_value;
+ case HASH_TABLE_KEY_WEAK: return Qkey;
+ case HASH_TABLE_KEY_VALUE_WEAK: return Qkey_or_value;
+ case HASH_TABLE_VALUE_WEAK: return Qvalue;
+ default: return Qnil;
}
}
{
switch (xhash_table (hash_table)->weakness)
{
- case HASH_TABLE_WEAK: return Qweak;
- case HASH_TABLE_KEY_WEAK: return Qkey_weak;
- case HASH_TABLE_KEY_VALUE_WEAK: return Qkey_value_weak;
- case HASH_TABLE_VALUE_WEAK: return Qvalue_weak;
- default: return Qnon_weak;
+ case HASH_TABLE_WEAK: return Qweak;
+ case HASH_TABLE_KEY_WEAK: return Qkey_weak;
+ case HASH_TABLE_KEY_VALUE_WEAK: return Qkey_or_value_weak;
+ case HASH_TABLE_VALUE_WEAK: return Qvalue_weak;
+ default: return Qnon_weak;
}
}
}
break;
+ /* We seem to be sprouting new weakness types at an alarming
+ rate. At least this is not externally visible - and in
+ fact all of these KEY_CAR_* types are only used by the
+ glyph code. */
+ case HASH_TABLE_KEY_CAR_VALUE_WEAK:
+ for (; e < sentinel; e++)
+ if (!HENTRY_CLEAR_P (e))
+ {
+ if (!CONSP (e->key) || marked_p (XCAR (e->key)))
+ {
+ MARK_OBJ (e->key);
+ MARK_OBJ (e->value);
+ }
+ else if (marked_p (e->value))
+ MARK_OBJ (e->key);
+ }
+ break;
+
case HASH_TABLE_VALUE_CAR_WEAK:
for (; e < sentinel; e++)
if (!HENTRY_CLEAR_P (e))
DEFUN ("sxhash", Fsxhash, 1, 1, 0, /*
Return a hash value for OBJECT.
-(equal obj1 obj2) implies (= (sxhash obj1) (sxhash obj2)).
+\(equal obj1 obj2) implies (= (sxhash obj1) (sxhash obj2)).
*/
(object))
{
defsymbol (&Qhashtable, "hashtable");
defsymbol (&Qweakness, "weakness");
defsymbol (&Qvalue, "value");
- defsymbol (&Qkey_value, "key-value");
+ defsymbol (&Qkey_or_value, "key-or-value");
+ defsymbol (&Qkey_and_value, "key-and-value");
defsymbol (&Qrehash_size, "rehash-size");
defsymbol (&Qrehash_threshold, "rehash-threshold");
defsymbol (&Qweak, "weak"); /* obsolete */
defsymbol (&Qkey_weak, "key-weak"); /* obsolete */
- defsymbol (&Qkey_value_weak, "key-value-weak"); /* obsolete */
+ defsymbol (&Qkey_or_value_weak, "key-or-value-weak"); /* obsolete */
defsymbol (&Qvalue_weak, "value-weak"); /* obsolete */
defsymbol (&Qnon_weak, "non-weak"); /* obsolete */
{
/* This must NOT be staticpro'd */
Vall_weak_hash_tables = Qnil;
- pdump_wire_list (&Vall_weak_hash_tables);
+ dump_add_weak_object_chain (&Vall_weak_hash_tables);
}