diff options
Diffstat (limited to 'implement.h')
-rw-r--r-- | implement.h | 89 |
1 files changed, 68 insertions, 21 deletions
diff --git a/implement.h b/implement.h index d575539..994a768 100644 --- a/implement.h +++ b/implement.h @@ -266,7 +266,7 @@ struct pthread_key_t_ { DWORD key; void (*destructor) (void *); - pthread_mutex_t threadsLock; + pthread_mutex_t keyLock; void *threads; }; @@ -347,26 +347,67 @@ struct ThreadKeyAssoc { /* * Purpose: - * This structure creates an association between a - * thread and a key. - * It is used to implement the implicit invocation - * of a user defined destroy routine for thread - * specific data registered by a user upon exiting a - * thread. + * This structure creates an association between a thread and a key. + * It is used to implement the implicit invocation of a user defined + * destroy routine for thread specific data registered by a user upon + * exiting a thread. * - * Attributes: - * lock - * protects access to the rest of the structure + * Graphically, the arrangement is as follows, where: + * + * K - Key with destructor + * (head of chain is key->threads) + * T - Thread that has called pthread_setspecific(Kn) + * (head of chain is thread->keys) + * A - Association. Each association is a node at the + * intersection of two doubly-linked lists. + * + * T1 T2 T3 + * | | | + * | | | + * K1 -----+-----A-----A-----> + * | | | + * | | | + * K2 -----A-----A-----+-----> + * | | | + * | | | + * K3 -----A-----+-----A-----> + * | | | + * | | | + * V V V + * + * Access to the association is guarded by two locks: the key's + * general lock (guarding the row) and the thread's general + * lock (guarding the column). This avoids the need for a + * dedicated lock for each association, which not only consumes + * more handles but requires that: before the lock handle can + * be released - both the key must be deleted and the thread + * must have called the destructor. The two-lock arrangement + * allows the resources to be freed as soon as either thread or + * key is concluded. + * + * To avoid deadlock: whenever both locks are required, the key + * and thread locks are always applied in the order: key lock + * then thread lock. * + * An association is created when a thread first calls + * pthread_setspecific() on a key that has a specified + * destructor. + * + * An association is destroyed either immediately after the + * thread calls the key destructor function on thread exit, or + * when the key is deleted. + * + * Attributes: * thread - * reference to the thread that owns the association. - * As long as this is not NULL, the association remains - * referenced by the pthread_t. + * reference to the thread that owns the + * association. This is actually the pointer to the + * thread struct itself. Since the association is + * destroyed before the thread exits, this can never + * point to a different logical thread to the one that + * created the assoc, i.e. after thread struct reuse. * * key * reference to the key that owns the association. - * As long as this is not NULL, the association remains - * referenced by the pthread_key_t. * * nextKey * The pthread_t->keys attribute is the head of a @@ -375,6 +416,9 @@ struct ThreadKeyAssoc * between a pthread_t and all pthread_key_t on which * it called pthread_setspecific. * + * prevKey + * Similarly. + * * nextThread * The pthread_key_t->threads attribute is the head of * a chain of assoctiations that runs through the @@ -383,11 +427,13 @@ struct ThreadKeyAssoc * PThreads that have called pthread_setspecific for * this pthread_key_t. * + * prevThread + * Similarly. * * Notes: - * 1) As long as one of the attributes, thread or key, is - * not NULL, the association is being referenced; once - * both are NULL, the association must be released. + * 1) As soon as either the key or the thread is no longer + * referencing the association, it can be destroyed. The + * association will be removed from both chains. * * 2) Under WIN32, an association is only created by * pthread_setspecific if the user provided a @@ -395,11 +441,12 @@ struct ThreadKeyAssoc * * */ - pthread_mutex_t lock; - pthread_t thread; + ptw32_thread_t * thread; pthread_key_t key; ThreadKeyAssoc *nextKey; ThreadKeyAssoc *nextThread; + ThreadKeyAssoc *prevKey; + ThreadKeyAssoc *prevThread; }; @@ -564,7 +611,7 @@ extern "C" void ptw32_callUserDestroyRoutines (pthread_t thread); int ptw32_tkAssocCreate (ThreadKeyAssoc ** assocP, - pthread_t thread, pthread_key_t key); + ptw32_thread_t * thread, pthread_key_t key); void ptw32_tkAssocDestroy (ThreadKeyAssoc * assoc); |