@@ -142,26 +142,80 @@ void PyThread_init_thread(void)
142142 This code stolen from "thread_sgi.h", where it was the only
143143 implementation of an existing Python TLS API.
144144*/
145- /*
146- * Per-thread data ("key") support.
147- */
145+ /* ------------------------------------------------------------------------
146+ Per-thread data ("key") support.
147+
148+ Use PyThread_create_key() to create a new key. This is typically shared
149+ across threads.
150+
151+ Use PyThread_set_key_value(thekey, value) to associate void* value with
152+ thekey in the current thread. Each thread has a distinct mapping of thekey
153+ to a void* value. Caution: if the current thread already has a mapping
154+ for thekey, value is ignored.
155+
156+ Use PyThread_get_key_value(thekey) to retrieve the void* value associated
157+ with thekey in the current thread. This returns NULL if no value is
158+ associated with thekey in the current thread.
159+
160+ Use PyThread_delete_key_value(thekey) to forget the current thread's associated
161+ value for thekey. PyThread_delete_key(thekey) forgets the values associated
162+ with thekey across *all* threads.
148163
164+ While some of these functions have error-return values, none set any
165+ Python exception.
166+
167+ None of the functions does memory management on behalf of the void* values.
168+ You need to allocate and deallocate them yourself. If the void* values
169+ happen to be PyObject*, these functions don't do refcount operations on
170+ them either.
171+
172+ The GIL does not need to be held when calling these functions; they supply
173+ their own locking. This isn't true of PyThread_create_key(), though (see
174+ next paragraph).
175+
176+ There's a hidden assumption that PyThread_create_key() will be called before
177+ any of the other functions are called. There's also a hidden assumption
178+ that calls to PyThread_create_key() are serialized externally.
179+ ------------------------------------------------------------------------ */
180+
181+ /* A singly-linked list of struct key objects remembers all the key->value
182+ * associations. File static keyhead heads the list. keymutex is used
183+ * to enforce exclusion internally.
184+ */
149185struct key {
186+ /* Next record in the list, or NULL if this is the last record. */
150187 struct key * next ;
188+
189+ /* The thread id, according to PyThread_get_thread_ident(). */
151190 long id ;
191+
192+ /* The key and its associated value. */
152193 int key ;
153194 void * value ;
154195};
155196
156197static struct key * keyhead = NULL ;
157- static int nkeys = 0 ;
158198static PyThread_type_lock keymutex = NULL ;
159-
199+ static int nkeys = 0 ; /* PyThread_create_key() hands out nkeys+1 next */
200+
201+ /* Internal helper.
202+ * If the current thread has a mapping for key, the appropriate struct key*
203+ * is returned. NB: value is ignored in this case!
204+ * If there is no mapping for key in the current thread, then:
205+ * If value is NULL, NULL is returned.
206+ * Else a mapping of key to value is created for the current thread,
207+ * and a pointer to a new struct key* is returned; except that if
208+ * malloc() can't find room for a new struct key*, NULL is returned.
209+ * So when value==NULL, this acts like a pure lookup routine, and when
210+ * value!=NULL, this acts like dict.setdefault(), returning an existing
211+ * mapping if one exists, else creating a new mapping.
212+ */
160213static struct key *
161214find_key (int key , void * value )
162215{
163216 struct key * p ;
164217 long id = PyThread_get_thread_ident ();
218+
165219 for (p = keyhead ; p != NULL ; p = p -> next ) {
166220 if (p -> id == id && p -> key == key )
167221 return p ;
@@ -181,18 +235,27 @@ find_key(int key, void *value)
181235 return p ;
182236}
183237
238+ /* Return a new key. This must be called before any other functions in
239+ * this family, and callers must arrange to serialize calls to this
240+ * function. No violations are detected.
241+ */
184242int
185243PyThread_create_key (void )
186244{
245+ /* All parts of this function are wrong if it's called by multiple
246+ * threads simultaneously.
247+ */
187248 if (keymutex == NULL )
188249 keymutex = PyThread_allocate_lock ();
189250 return ++ nkeys ;
190251}
191252
253+ /* Forget the associations for key across *all* threads. */
192254void
193255PyThread_delete_key (int key )
194256{
195257 struct key * p , * * q ;
258+
196259 PyThread_acquire_lock (keymutex , 1 );
197260 q = & keyhead ;
198261 while ((p = * q ) != NULL ) {
@@ -207,31 +270,46 @@ PyThread_delete_key(int key)
207270 PyThread_release_lock (keymutex );
208271}
209272
273+ /* Confusing: If the current thread has an association for key,
274+ * value is ignored, and 0 is returned. Else an attempt is made to create
275+ * an association of key to value for the current thread. 0 is returned
276+ * if that succeeds, but -1 is returned if there's not enough memory
277+ * to create the association. value must not be NULL.
278+ */
210279int
211280PyThread_set_key_value (int key , void * value )
212281{
213- struct key * p = find_key (key , value );
282+ struct key * p ;
283+
284+ assert (value != NULL );
285+ p = find_key (key , value );
214286 if (p == NULL )
215287 return -1 ;
216288 else
217289 return 0 ;
218290}
219291
292+ /* Retrieve the value associated with key in the current thread, or NULL
293+ * if the current thread doesn't have an association for key.
294+ */
220295void *
221296PyThread_get_key_value (int key )
222297{
223298 struct key * p = find_key (key , NULL );
299+
224300 if (p == NULL )
225301 return NULL ;
226302 else
227303 return p -> value ;
228304}
229305
306+ /* Forget the current thread's association for key, if any. */
230307void
231308PyThread_delete_key_value (int key )
232309{
233310 long id = PyThread_get_thread_ident ();
234311 struct key * p , * * q ;
312+
235313 PyThread_acquire_lock (keymutex , 1 );
236314 q = & keyhead ;
237315 while ((p = * q ) != NULL ) {
0 commit comments