/* * ptw32_callUserDestroyRoutines.c * * Description: * This translation unit implements routines which are private to * the implementation and may be used throughout it. * * -------------------------------------------------------------------------- * * Pthreads-win32 - POSIX Threads Library for Win32 * Copyright(C) 1998 John E. Bossom * Copyright(C) 1999,2004 Pthreads-win32 contributors * * Contact Email: rpj@callisto.canberra.edu.au * * The current list of contributors is contained * in the file CONTRIBUTORS included with the source * code distribution. The list can also be seen at the * following World Wide Web location: * http://sources.redhat.com/pthreads-win32/contributors.html * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library in the file COPYING.LIB; * if not, write to the Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #include "pthread.h" #include "implement.h" #ifdef __cplusplus # if ! defined (_MSC_VER) && ! (defined(__GNUC__) && __GNUC__ < 3) && ! defined(__WATCOMC__) using std::terminate; # endif #endif void ptw32_callUserDestroyRoutines (pthread_t thread) /* * ------------------------------------------------------------------- * DOCPRIVATE * * This the routine runs through all thread keys and calls * the destroy routines on the user's data for the current thread. * It simulates the behaviour of POSIX Threads. * * PARAMETERS * thread * an instance of pthread_t * * RETURNS * N/A * ------------------------------------------------------------------- */ { ThreadKeyAssoc ** nextP; ThreadKeyAssoc * assoc; if (thread.p != NULL) { /* * Run through all Thread<-->Key associations * for the current thread. * If the pthread_key_t still exits (ie the assoc->key * is not NULL) then call the user's TSD destroy routine. * Notes: * If assoc->key is NULL, then the user previously called * PThreadKeyDestroy. The association is now only referenced * by the current thread and must be released; otherwise * the assoc will be destroyed when the key is destroyed. */ nextP = (ThreadKeyAssoc **) &((ptw32_thread_t *)thread.p)->keys; assoc = *nextP; while (assoc != NULL) { if (pthread_mutex_lock (&(assoc->lock)) == 0) { pthread_key_t k; pthread_t nil = {NULL, 0}; if ((k = assoc->key) != NULL) { /* * Key still active; pthread_key_delete * will block on this same mutex before * it can release actual key; therefore, * key is valid and we can call the destroy * routine; */ void * value = NULL; value = pthread_getspecific (k); if (value != NULL && k->destructor != NULL) { #ifdef __cplusplus try { /* * Run the caller's cleanup routine. */ (*(k->destructor)) (value); } catch (...) { /* * A system unexpected exception has occurred * running the user's destructor. * We get control back within this block in case * the application has set up it's own terminate * handler. Since we are leaving the thread we * should not get any internal pthreads * exceptions. */ terminate (); } #else /* __cplusplus */ /* * Run the caller's cleanup routine. */ (*(k->destructor)) (value); #endif /* __cplusplus */ } } /* * mark assoc->thread as NULL to indicate the * thread no longer references this association */ assoc->thread = nil; /* * Remove association from the pthread_t chain */ *nextP = assoc->nextKey; pthread_mutex_unlock (&(assoc->lock)); ptw32_tkAssocDestroy (assoc); assoc = *nextP; } } } } /* ptw32_callUserDestroyRoutines */