Skip to content

Commit 5b0a303

Browse files
authored
bpo-40609: _Py_hashtable_t values become void* (GH-20065)
_Py_hashtable_t values become regular "void *" pointers. * Add _Py_hashtable_entry_t.data member * Remove _Py_hashtable_t.data_size member * Remove _Py_hashtable_t.get_func member. It is no longer needed to specialize _Py_hashtable_get() for a specific value size, since all entries now have the same size (void*). * Remove the following macros: * _Py_HASHTABLE_GET() * _Py_HASHTABLE_SET() * _Py_HASHTABLE_SET_NODATA() * _Py_HASHTABLE_POP() * Rename _Py_hashtable_pop() to _Py_hashtable_steal() * _Py_hashtable_foreach() callback now gets key and value rather than entry. * Remove _Py_hashtable_value_destroy_func type. value_destroy_func callback now only has a single parameter: data (void*).
1 parent d95bd42 commit 5b0a303

File tree

4 files changed

+140
-303
lines changed

4 files changed

+140
-303
lines changed

Include/internal/pycore_hashtable.h

Lines changed: 21 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,9 @@ typedef struct {
3131

3232
Py_uhash_t key_hash;
3333
void *key;
34-
/* data (data_size bytes) follows */
34+
void *value;
3535
} _Py_hashtable_entry_t;
3636

37-
#define _Py_HASHTABLE_ENTRY_PDATA(ENTRY) \
38-
((const void *)((char *)(ENTRY) \
39-
+ sizeof(_Py_hashtable_entry_t)))
40-
41-
#define _Py_HASHTABLE_ENTRY_READ_DATA(TABLE, ENTRY, DATA) \
42-
do { \
43-
assert(sizeof(DATA) == (TABLE)->data_size); \
44-
memcpy(&(DATA), _Py_HASHTABLE_ENTRY_PDATA((ENTRY)), \
45-
sizeof(DATA)); \
46-
} while (0)
47-
4837

4938
/* _Py_hashtable: prototypes */
5039

@@ -55,12 +44,8 @@ typedef struct _Py_hashtable_t _Py_hashtable_t;
5544
typedef Py_uhash_t (*_Py_hashtable_hash_func) (const void *key);
5645
typedef int (*_Py_hashtable_compare_func) (const void *key1, const void *key2);
5746
typedef void (*_Py_hashtable_destroy_func) (void *key);
58-
typedef void (*_Py_hashtable_value_destroy_func) (_Py_hashtable_t *ht,
59-
_Py_hashtable_entry_t *entry);
6047
typedef _Py_hashtable_entry_t* (*_Py_hashtable_get_entry_func)(_Py_hashtable_t *ht,
6148
const void *key);
62-
typedef int (*_Py_hashtable_get_func) (_Py_hashtable_t *ht,
63-
const void *key, void *data);
6449

6550
typedef struct {
6651
/* allocate a memory block */
@@ -76,14 +61,12 @@ struct _Py_hashtable_t {
7661
size_t num_buckets;
7762
size_t entries; /* Total number of entries in the table. */
7863
_Py_slist_t *buckets;
79-
size_t data_size;
8064

81-
_Py_hashtable_get_func get_func;
8265
_Py_hashtable_get_entry_func get_entry_func;
8366
_Py_hashtable_hash_func hash_func;
8467
_Py_hashtable_compare_func compare_func;
8568
_Py_hashtable_destroy_func key_destroy_func;
86-
_Py_hashtable_value_destroy_func value_destroy_func;
69+
_Py_hashtable_destroy_func value_destroy_func;
8770
_Py_hashtable_allocator_t alloc;
8871
};
8972

@@ -96,95 +79,66 @@ PyAPI_FUNC(int) _Py_hashtable_compare_direct(
9679
const void *key2);
9780

9881
PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new(
99-
size_t data_size,
10082
_Py_hashtable_hash_func hash_func,
10183
_Py_hashtable_compare_func compare_func);
10284

10385
PyAPI_FUNC(_Py_hashtable_t *) _Py_hashtable_new_full(
104-
size_t data_size,
105-
size_t init_size,
10686
_Py_hashtable_hash_func hash_func,
10787
_Py_hashtable_compare_func compare_func,
10888
_Py_hashtable_destroy_func key_destroy_func,
109-
_Py_hashtable_value_destroy_func value_destroy_func,
89+
_Py_hashtable_destroy_func value_destroy_func,
11090
_Py_hashtable_allocator_t *allocator);
11191

11292
PyAPI_FUNC(void) _Py_hashtable_destroy(_Py_hashtable_t *ht);
11393

11494
PyAPI_FUNC(void) _Py_hashtable_clear(_Py_hashtable_t *ht);
11595

11696
typedef int (*_Py_hashtable_foreach_func) (_Py_hashtable_t *ht,
117-
_Py_hashtable_entry_t *entry,
118-
void *arg);
97+
const void *key, const void *value,
98+
void *user_data);
11999

120100
/* Call func() on each entry of the hashtable.
121101
Iteration stops if func() result is non-zero, in this case it's the result
122102
of the call. Otherwise, the function returns 0. */
123103
PyAPI_FUNC(int) _Py_hashtable_foreach(
124104
_Py_hashtable_t *ht,
125105
_Py_hashtable_foreach_func func,
126-
void *arg);
106+
void *user_data);
127107

128-
PyAPI_FUNC(size_t) _Py_hashtable_size(_Py_hashtable_t *ht);
108+
PyAPI_FUNC(size_t) _Py_hashtable_size(const _Py_hashtable_t *ht);
129109

130110
/* Add a new entry to the hash. The key must not be present in the hash table.
131-
Return 0 on success, -1 on memory error.
132-
133-
Don't call directly this function,
134-
but use _Py_HASHTABLE_SET() and _Py_HASHTABLE_SET_NODATA() macros */
111+
Return 0 on success, -1 on memory error. */
135112
PyAPI_FUNC(int) _Py_hashtable_set(
136113
_Py_hashtable_t *ht,
137114
const void *key,
138-
size_t data_size,
139-
const void *data);
140-
141-
#define _Py_HASHTABLE_SET(TABLE, KEY, DATA) \
142-
_Py_hashtable_set(TABLE, (KEY), sizeof(DATA), &(DATA))
143-
144-
#define _Py_HASHTABLE_SET_NODATA(TABLE, KEY) \
145-
_Py_hashtable_set(TABLE, (KEY), 0, NULL)
115+
void *value);
146116

147117

148118
/* Get an entry.
149-
Return NULL if the key does not exist.
150-
151-
Don't call directly this function, but use _Py_HASHTABLE_GET_ENTRY()
152-
macro */
119+
Return NULL if the key does not exist. */
153120
static inline _Py_hashtable_entry_t *
154121
_Py_hashtable_get_entry(_Py_hashtable_t *ht, const void *key)
155122
{
156123
return ht->get_entry_func(ht, key);
157124
}
158125

159-
#define _Py_HASHTABLE_GET_ENTRY(TABLE, KEY) \
160-
_Py_hashtable_get_entry(TABLE, (const void *)(KEY))
161126

127+
/* Get value from an entry.
128+
Return NULL if the entry is not found.
162129
163-
/* Get data from an entry. Copy entry data into data and return 1 if the entry
164-
exists, return 0 if the entry does not exist.
130+
Use _Py_hashtable_get_entry() to distinguish entry value equal to NULL
131+
and entry not found. */
132+
extern void *_Py_hashtable_get(_Py_hashtable_t *ht, const void *key);
165133

166-
Don't call directly this function, but use _Py_HASHTABLE_GET() macro */
167-
static inline int
168-
_Py_hashtable_get(_Py_hashtable_t *ht, const void *key,
169-
size_t data_size, void *data)
170-
{
171-
assert(data_size == ht->data_size);
172-
return ht->get_func(ht, key, data);
173-
}
174-
175-
#define _Py_HASHTABLE_GET(TABLE, KEY, DATA) \
176-
_Py_hashtable_get(TABLE, (KEY), sizeof(DATA), &(DATA))
177134

178-
179-
/* Don't call directly this function, but use _Py_HASHTABLE_POP() macro */
180-
PyAPI_FUNC(int) _Py_hashtable_pop(
135+
// Remove a key and its associated value without calling key and value destroy
136+
// functions.
137+
// Return the removed value if the key was found.
138+
// Return NULL if the key was not found.
139+
PyAPI_FUNC(void*) _Py_hashtable_steal(
181140
_Py_hashtable_t *ht,
182-
const void *key,
183-
size_t data_size,
184-
void *data);
185-
186-
#define _Py_HASHTABLE_POP(TABLE, KEY, DATA) \
187-
_Py_hashtable_pop(TABLE, (KEY), sizeof(DATA), &(DATA))
141+
const void *key);
188142

189143

190144
#ifdef __cplusplus

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy