summaryrefslogtreecommitdiff
path: root/ace/OS_NS_Thread.cpp
diff options
context:
space:
mode:
authornobody <nobody@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2004-09-16 21:19:02 +0000
committernobody <nobody@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2004-09-16 21:19:02 +0000
commit40fdc8a404e75ab03b68cc62e9987cf208fd8c30 (patch)
tree37d9c4d3abe4aefd8a34ed797883dd2cd4862ca7 /ace/OS_NS_Thread.cpp
parentc254b281f1b9a4ca19dd0c3ee73a0654a7718909 (diff)
downloadATCD-40fdc8a404e75ab03b68cc62e9987cf208fd8c30.tar.gz
This commit was manufactured by cvs2svn to create branchtypecode-overhaul
'typecode-overhaul'.
Diffstat (limited to 'ace/OS_NS_Thread.cpp')
-rw-r--r--ace/OS_NS_Thread.cpp464
1 files changed, 217 insertions, 247 deletions
diff --git a/ace/OS_NS_Thread.cpp b/ace/OS_NS_Thread.cpp
index abf9c5bbe7b..c992554753a 100644
--- a/ace/OS_NS_Thread.cpp
+++ b/ace/OS_NS_Thread.cpp
@@ -16,7 +16,7 @@ ACE_RCSID (ace,
#include "ace/Object_Manager_Base.h"
#include "ace/OS_NS_errno.h"
#include "ace/OS_NS_ctype.h"
-#include "ace/Log_Msg.h" // for ACE_ASSERT
+
// This is necessary to work around nasty problems with MVS C++.
extern "C" void
@@ -502,11 +502,11 @@ ACE_TSS_Ref::operator != (const ACE_TSS_Ref &tss_ref) const
// single file of template instantiations
ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key,
- ACE_TSS_Info::Destructor dest,
+ void (*dest)(void *),
void *tss_inst)
: key_ (key),
destructor_ (dest),
- tss_inst_ (tss_inst),
+ tss_obj_ (tss_inst),
thread_count_ (-1)
{
ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
@@ -515,7 +515,7 @@ ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key,
ACE_TSS_Info::ACE_TSS_Info (void)
: key_ (ACE_OS::NULL_key),
destructor_ (0),
- tss_inst_ (0),
+ tss_obj_ (0),
thread_count_ (-1)
{
ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
@@ -563,7 +563,7 @@ ACE_TSS_Info::dump (void)
ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("key_ = %u\n"), this->key_));
ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("destructor_ = %u\n"), this->destructor_));
- ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("tss_inst_ = %u\n"), this->tss_inst_));
+ ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("tss_obj_ = %u\n"), this->tss_obj_));
ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
# endif /* 0 */
# endif /* ACE_HAS_DUMP */
@@ -639,30 +639,12 @@ ACE_TSS_Keys::is_set (const ACE_thread_key_t key) const
/**
* @class ACE_TSS_Cleanup
*
- * @brief Singleton that helps to manage the lifetime of TSS objects and keys.
+ * @brief Singleton that knows how to clean up all the thread-specific
+ * resources for Win32.
*
- ***********************************************************************
- * Behavior of TSS_Cleanup was changed to eliminate leaks:
- * +------OLD------------+--------NEW---------
- * Action | exit| detach | exit : detach : remove
- * -------------------------- | Always: Last | : : (if...)
- * --key_info->thread_count_ X | X : | X : :
- * destructor(tss_obj) X | [4] : | X : :
- * tss_keys ()->test_and_clear X | X[2] : X[2] | X : :
- * key_info->inst = 0 | X[2] : X[1] | : X :
- * | | remove : remove :
- * key_info->in_use (0) | : X[1] | : : X
- * key_info->key_ = NULL [6] | : X[1] | : :
- * key_info->destructor=0 | : X[1] | : : X
- * release tss key [4] | : X | : : X
- * clear key in_use_ | : [5] | : : X
- *----------------------------------------------------------------------
- * [1] delegated to remove
- * [2] done twice;
- * [3] this is a bug. It should not be done here
- * [4] Resource leak--should be done, but it's not.
- * [5] Should be done here, but it's not.
- * [6] Unnecessary and problematic.
+ * All this nonsense is required since Win32 doesn't
+ * automatically cleanup thread-specific storage on thread exit,
+ * unlike real operating systems... ;-)
*/
class ACE_TSS_Cleanup
{
@@ -681,44 +663,22 @@ public:
int remove (ACE_thread_key_t key);
/// Detaches a tss_instance from its key.
- int detach (ACE_thread_key_t key, void * inst);
+ int detach (void *inst);
/// Mark a key as being used by this thread.
void key_used (ACE_thread_key_t key);
+ /// Free all keys left in the table before destruction.
+ int free_all_keys_left (void);
+
/// Indication of whether the ACE_TSS_CLEANUP_LOCK is usable, and
/// therefore whether we are in static constructor/destructor phase
/// or not.
- static int lockable ()
- {
- return instance_ != 0;
- }
+ static int lockable () { return instance_ != 0; }
protected:
void dump (void);
- /// remove key if it's unused
- /// @param info reference to the info for this key
- void remove_key (ACE_TSS_Info &info);
-
- /// Release a key used by this thread
- /// @param info reference to the info for this key
- /// @param destructor out arg to receive destructor function ptr
- /// @param tss_obj out arg to receive pointer to deletable object
- void thread_release (
- ACE_TSS_Info &info,
- ACE_TSS_Info::Destructor & destructor,
- void *& tss_obj);
-
- /// Find the TSS keys (if any) for this thread.
- /// @param thread_keys reference to pointer to be filled in by this function.
- /// @return false if keys don't exist.
- bool find_tss_keys (ACE_TSS_Keys *& thread_keys) const;
-
- /// Accessor for this threads ACE_TSS_Keys instance.
- /// Creates the keys if necessary.
- ACE_TSS_Keys *tss_keys ();
-
/// Ensure singleton.
ACE_TSS_Cleanup (void);
@@ -730,12 +690,18 @@ private:
/// Table of <ACE_TSS_Info>'s.
ACE_TSS_TABLE table_;
- /// Key for the thread-specific ACE_TSS_Keys
- /// Used by find_tss_keys() or tss_keys() to find the
- /// bit array that records whether each TSS key is in
- /// use by this thread.
+ /// Key for the thread-specific array of whether each TSS key is in use.
ACE_thread_key_t in_use_;
+ /// Accessor for this threads ACE_TSS_Keys instance.
+ ACE_TSS_Keys *tss_keys ();
+
+# if defined (ACE_HAS_TSS_EMULATION)
+ /// Key that is used by in_use_. We save this key so that we know
+ /// not to call its destructor in free_all_keys_left ().
+ ACE_thread_key_t in_use_key_;
+# endif /* ACE_HAS_TSS_EMULATION */
+
// = Static data.
/// Pointer to the singleton instance.
static ACE_TSS_Cleanup *instance_;
@@ -756,74 +722,134 @@ void
ACE_TSS_Cleanup::exit (void * /* status */)
{
ACE_OS_TRACE ("ACE_TSS_Cleanup::exit");
- // variables to hold the destructors
- // and pointers to the object to be destructed
- // the actual destruction is deferred until the guard is released
- ACE_TSS_Info::Destructor destructor[ACE_DEFAULT_THREAD_KEYS];
- void * tss_obj[ACE_DEFAULT_THREAD_KEYS];
- // count of items to be destroyed
- unsigned int d_count = 0;
-
- // scope the guard
+
+ ACE_TSS_TABLE_ITERATOR key_info = table_;
+ ACE_TSS_Info info_arr[ACE_DEFAULT_THREAD_KEYS];
+ int info_ix = 0;
+
+ // While holding the lock, we only collect the ACE_TSS_Info objects
+ // in an array without invoking the according destructors.
{
ACE_TSS_CLEANUP_GUARD
- // if not initialized or already cleaned up
- ACE_TSS_Keys *this_thread_keys = 0;
- if (! find_tss_keys (this_thread_keys) )
- {
- return;
- }
+ // Iterate through all the thread-specific items and free them all
+ // up.
- // Minor hack: Iterating in reverse order means the LOG buffer which is
- // accidentally allocated first will be accidentally deallocated (almost)
- // last -- in case someone logs something from the other destructors.
- // applications should not count on this behavior because platforms which
- // do not use ACE_TSS_Cleanup may delete objects in other orders.
- unsigned int key_index = ACE_DEFAULT_THREAD_KEYS;
- while( key_index > 0)
+ for (unsigned int i = 0;
+ i < ACE_DEFAULT_THREAD_KEYS;
+ ++key_info, ++i)
{
- --key_index;
- ACE_TSS_Info & info = this->table_[key_index];
- // if this key is in use by this thread
- if (this_thread_keys->is_set(info.key_))
+ if (key_info->key_ == ACE_OS::NULL_key ||
+ ! key_info->key_in_use ()) continue;
+
+ // If the key's ACE_TSS_Info in-use bit for this thread was set,
+ // unset it and decrement the key's thread_count_.
+ if (! tss_keys ()->test_and_clear (key_info->key_))
{
- // defer deleting the in-use key until all others have been deleted
- if(info.key_ != this->in_use_)
- {
- destructor[d_count] = 0;
- tss_obj[d_count] = 0;
- this->thread_release (info, destructor[d_count], tss_obj[d_count]);
- if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
- {
- ++d_count;
- }
- this->remove_key (info);
- }
+ --key_info->thread_count_;
}
- }
- // remove the in_use bit vector last
- ACE_KEY_INDEX (use_index, this->in_use_);
- ACE_TSS_Info & info = this->table_[use_index];
- destructor[d_count] = 0;
- tss_obj[d_count] = 0;
- this->thread_release (info, destructor[d_count], tss_obj[d_count]);
- if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
- {
- ++d_count;
+ void *tss_info = 0;
+
+ if (key_info->destructor_
+ && ACE_OS::thr_getspecific (key_info->key_, &tss_info) == 0
+ && tss_info)
+ {
+ info_arr[info_ix].key_ = key_info->key_;
+ info_arr[info_ix].destructor_ = key_info->destructor_;
+ info_arr[info_ix++].tss_obj_ = key_info->tss_obj_;
+ }
}
- this->remove_key (info);
- } // end of guard scope
- // WARNING:
- // Once the guard is released this ACE_TSS_Cleanup may be deleted -- especially
- // because we are about to delete a Thread_Exit object.
- // Do not attempt to use any data members for the rest of this method.
+ }
- for (unsigned int d_index = 0; d_index < d_count; ++d_index)
+ // Now we have given up the ACE_TSS_Cleanup::lock_ and we start
+ // invoking destructors, in the reverse order of creation.
+ for (int i = info_ix - 1; i >= 0; --i)
{
- (*destructor[d_index])(tss_obj[d_index]);
+ void *tss_info = 0;
+
+ ACE_OS::thr_getspecific (info_arr[i].key_, &tss_info);
+
+ if (tss_info != 0)
+ {
+ // Only call the destructor if the value is non-zero for this
+ // thread.
+ (*info_arr[i].destructor_)(tss_info);
+ }
}
+
+ // Acquire the ACE_TSS_CLEANUP_LOCK, then free TLS keys and remove
+ // entries from ACE_TSS_Info table.
+ {
+ ACE_TSS_CLEANUP_GUARD
+
+# if 0
+ // We shouldn't free the key and remove it from the table here
+ // because if we do and some thread ends before other threads
+ // even get started (or their TSS object haven't been created yet,)
+ // it's entry will be removed from the table and we are in big chaos.
+ // For TSS object, these have been done in ACE_TSS_Cleanup::detach.
+ // Two other use cases will be user managed TSS'es and system wide
+ // TSS, ones are users responsibilities and the others should be
+ // persistant system wide.
+ for (int i = 0; i < index; i++)
+ {
+# if defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
+ // Calling thr_keyfree here ensure the key
+ // gets removed appropriately. Notice that
+ // a key should be removed before freeing it.
+ ACE_OS::thr_keyfree (key_info->key_);
+# else
+ // don't bother to free the key
+ this->remove (key_info->key_);
+# endif /* ACE_WIN32 */
+ }
+# endif /* 0 */
+ }
+}
+
+int
+ACE_TSS_Cleanup::free_all_keys_left (void)
+ // This is called from ACE_OS::cleanup_tss (). When this gets
+ // called, all threads should have exited except the main thread.
+ // No key should be freed from this routine. It there's any,
+ // something might be wrong.
+{
+ ACE_thread_key_t key_arr[ACE_DEFAULT_THREAD_KEYS];
+ ACE_TSS_TABLE_ITERATOR key_info = table_;
+ unsigned int idx = 0;
+ unsigned int i;
+
+ for (i = 0;
+ i < ACE_DEFAULT_THREAD_KEYS;
+ ++key_info, ++i)
+# if defined (ACE_HAS_TSS_EMULATION)
+ if (key_info->key_ != in_use_key_)
+# endif /* ACE_HAS_TSS_EMULATION */
+ // Don't call ACE_OS::thr_keyfree () on ACE_TSS_Cleanup's own
+ // key. See the comments in ACE_OS::thr_key_detach (): the key
+ // doesn't get detached, so it will be in the table here.
+ // However, there's no resource associated with it, so we don't
+ // need to keyfree it. The dynamic memory associated with it
+ // was already deleted by ACE_TSS_Cleanup::exit (), so we don't
+ // want to access it again.
+ key_arr [idx++] = key_info->key_;
+
+ for (i = 0; i < idx; i++)
+ if (key_arr[i] != ACE_OS::NULL_key)
+# if defined (ACE_HAS_TSS_EMULATION)
+ ACE_OS::thr_keyfree (key_arr[i]);
+# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)
+ // Don't call ACE_OS::thr_keyfree here. It will try to use
+ // <in_use_> which has already been cleaned up here.
+ ::tsd_delete (key_arr[i]);
+# else /* ACE_WIN32 */
+ // Don't call ACE_OS::thr_keyfree here. It will try to use
+ // <in_use_> which has already been cleaned up here.
+ TlsFree (key_arr[i]);
+# endif /* ACE_HAS_TSS_EMULATION */
+
+ return 0;
}
extern "C" void
@@ -834,6 +860,11 @@ ACE_TSS_Cleanup_keys_destroyer (void *tss_keys)
ACE_TSS_Cleanup::ACE_TSS_Cleanup (void)
: in_use_ (ACE_OS::NULL_key)
+# if defined (ACE_HAS_TSS_EMULATION)
+ // ACE_TSS_Emulation::total_keys () provides the value of the next
+ // key to be created.
+ , in_use_key_ (ACE_TSS_Emulation::total_keys ())
+# endif /* ACE_HAS_TSS_EMULATION */
{
ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
}
@@ -885,118 +916,77 @@ ACE_TSS_Cleanup::remove (ACE_thread_key_t key)
{
ACE_OS_TRACE ("ACE_TSS_Cleanup::remove");
ACE_TSS_CLEANUP_GUARD
+
ACE_KEY_INDEX (key_index, key);
if (key_index < ACE_DEFAULT_THREAD_KEYS)
{
- remove_key (this->table_ [key_index]);
+ // "Remove" the TSS_Info table entry by zeroing out its key_ and
+ // destructor_ fields. Also, keep track of the number threads
+ // using the key.
+ ACE_TSS_Info &info = this->table_ [key_index];
+
+ // Don't bother to test/clear the in "use bit" if the program is
+ // shutting down. Doing so will cause a new ACE_TSS object to be
+ // created again.
+ if (!ACE_OS_Object_Manager::shutting_down ())
+ tss_keys ()->test_and_clear (info.key_);
+ info.key_in_use (0);
+ info.key_ = ACE_OS::NULL_key;
+ info.destructor_ = 0;
return 0;
}
- return -1;
+ else
+ return -1;
}
-void
-ACE_TSS_Cleanup::remove_key (ACE_TSS_Info &info)
+int
+ACE_TSS_Cleanup::detach (void *inst)
{
- // assume CLEANUP_GUARD is held by caller
- ACE_OS_TRACE ("ACE_TSS_Cleanup::remove_key");
+ ACE_TSS_CLEANUP_GUARD
- // only remove it if all threads are done with it
- // and there is no ACE_TSS holding on to it.
- if (info.thread_count_ == 0 && info.tss_inst_ == 0)
+ ACE_TSS_TABLE_ITERATOR key_info = table_;
+ int success = 0;
+ int ref_cnt = 0;
+
+ // Mark the key as detached in the TSS_Info table.
+ // It only works for the first key that "inst" owns.
+ // I don't know why.
+ for (unsigned int i = 0;
+ i < ACE_DEFAULT_THREAD_KEYS;
+ ++key_info, ++i)
{
+ if (key_info->tss_obj_ == inst)
+ {
+ key_info->tss_obj_ = 0;
+ ref_cnt = --key_info->thread_count_;
+ success = 1;
+ break;
+ }
+ }
+
+ if (success == 0)
+ return -1;
+ else if (ref_cnt == 0)
+ {
+ // Mark the key as no longer being used.
+ key_info->key_in_use (0);
+# if defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
+ ACE_thread_key_t temp_key = key_info->key_;
+# endif /* ACE_WIN32 */
+ int retv = this->remove (key_info->key_);
+
# if defined (ACE_WIN32)
- ACE_thread_key_t temp_key = info.key_;
::TlsFree (temp_key);
# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)
- ACE_thread_key_t temp_key = info.key_;
::tsd_delete (temp_key);
# endif /* ACE_WIN32 */
- if (info.key_ == this->in_use_)
- {
- this->in_use_ = ACE_OS::NULL_key;
- }
- info.key_in_use (0);
- info.destructor_ = 0;
+ return retv;
}
-}
-
-int
-ACE_TSS_Cleanup::detach (ACE_thread_key_t key, void *inst)
-{
- // variables to hold the destructor and the object to be destructed
- // the actual call is deferred until the guard is released
- ACE_TSS_Info::Destructor destructor = 0;
- void * tss_obj = 0;
-
- // scope the guard
- {
- ACE_TSS_CLEANUP_GUARD
-
- ACE_KEY_INDEX (key_index, key);
- ACE_ASSERT (key_index < sizeof(this->table_)/sizeof(this->table_[0])
- && this->table_[key_index].key_ == key);
- ACE_TSS_Info &info = this->table_ [key_index];
-
-
- // sanity check
- if (!info.key_in_use ())
- {
- return -1;
- }
- // if we are detaching from a TSS<x>
- // clear the inst info so we'll actually release the key
- if (inst != 0)
- {
- ACE_ASSERT (info.tss_inst_ == inst);
- info.tss_inst_ = 0;
- }
- this->thread_release (info, destructor, tss_obj);
-
- // try to remove this key
- this->remove_key (info);
-
- } // end of scope for the Guard
- // if there's a destructor and an object to be destroyed
- if (destructor != 0 && tss_obj != 0)
- {
- (*destructor) (tss_obj);
- }
return 0;
}
void
-ACE_TSS_Cleanup::thread_release (
- ACE_TSS_Info &info,
- ACE_TSS_Info::Destructor & destructor,
- void *& tss_obj)
-{
- // assume guard is held by caller
- // Find the TSS keys (if any) for this thread
- // do not create them if they don't exist
- ACE_TSS_Keys * thread_keys = 0;
- if (find_tss_keys (thread_keys))
- {
- // if this key is in use by this thread
- if (thread_keys->test_and_clear(info.key_) == 0)
- {
- // save destructor & pointer to tss object
- // until after the guard is released
- destructor = info.destructor_;
- ACE_OS::thr_getspecific (info.key_, &tss_obj);
- ACE_ASSERT (info.thread_count_ > 0);
- --info.thread_count_;
-#ifdef ACE_DEBUGGING_TSS_CLEANUP
- ACE_DEBUG ((LM_DEBUG,
- ACE_TEXT ("(%P|%t) ACE_TSS_Cleanup::thread_release[%d] decrement %d\n"),
- key,info.thread_count_));
-#endif //ACE_DEBUGGING_TSS_CLEANUP
- }
- }
-}
-
-
-void
ACE_TSS_Cleanup::key_used (ACE_thread_key_t key)
{
// If the key's ACE_TSS_Info in-use bit for this thread is not set,
@@ -1029,24 +1019,10 @@ ACE_TSS_Cleanup::dump (void)
# endif /* ACE_HAS_DUMP */
}
-bool
-ACE_TSS_Cleanup::find_tss_keys (ACE_TSS_Keys *& tss_keys) const
-{
- if (this->in_use_ == ACE_OS::NULL_key)
- return false;
- if (ACE_OS::thr_getspecific (in_use_,
- reinterpret_cast<void **> (&tss_keys)) == -1)
- {
- ACE_ASSERT (false);
- return false; // This should not happen!
- }
- return tss_keys != 0;
-}
-
ACE_TSS_Keys *
ACE_TSS_Cleanup::tss_keys ()
{
- if (this->in_use_ == ACE_OS::NULL_key)
+ if (in_use_ == ACE_OS::NULL_key)
{
ACE_TSS_CLEANUP_GUARD
// Double-check;
@@ -1055,20 +1031,14 @@ ACE_TSS_Cleanup::tss_keys ()
// Initialize in_use_ with a new key.
if (ACE_OS::thr_keycreate (&in_use_,
&ACE_TSS_Cleanup_keys_destroyer))
- {
- ACE_ASSERT (false);
- return 0; // Major problems, this should *never* happen!
- }
+ return 0; // Major problems, this should *never* happen!
}
}
ACE_TSS_Keys *ts_keys = 0;
if (ACE_OS::thr_getspecific (in_use_,
ACE_reinterpret_cast (void **, &ts_keys)) == -1)
- {
- ACE_ASSERT (false);
- return 0; // This should not happen!
- }
+ return 0; // This should not happen!
if (ts_keys == 0)
{
@@ -1081,7 +1051,6 @@ ACE_TSS_Cleanup::tss_keys ()
ACE_reinterpret_cast (void *,
ts_keys)) == -1)
{
- ACE_ASSERT (false);
delete ts_keys;
return 0; // Major problems, this should *never* happen!
}
@@ -1123,8 +1092,7 @@ ACE_OS::cleanup_tss (const u_int main_thread)
{
#if defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
// Call TSS destructors for current thread.
- if (ACE_TSS_Cleanup::lockable ())
- ACE_TSS_Cleanup::instance ()->exit (0);
+ ACE_TSS_Cleanup::instance ()->exit (0);
#endif /* ACE_HAS_TSS_EMULATION || ACE_WIN32 || ACE_PSOS_HAS_TSS */
if (main_thread)
@@ -1138,11 +1106,19 @@ ACE_OS::cleanup_tss (const u_int main_thread)
#endif /* ! ACE_HAS_TSS_EMULATION && ! ACE_HAS_MINIMAL_ACE_OS */
#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
+# if ! defined (ACE_HAS_TSS_EMULATION)
+ // Don't do this with TSS_Emulation, because the the
+ // ACE_TSS_Cleanup::instance () has already exited (). We can't
+ // safely access the TSS values that were created by the main
+ // thread.
+
+ // Remove all TSS_Info table entries.
+ ACE_TSS_Cleanup::instance ()->free_all_keys_left ();
+# endif /* ! ACE_HAS_TSS_EMULATION */
+
// Finally, free up the ACE_TSS_Cleanup instance. This method gets
// called by the ACE_Object_Manager.
- if (ACE_TSS_Cleanup::lockable ())
- delete ACE_TSS_Cleanup::instance ();
-
+ delete ACE_TSS_Cleanup::instance ();
#endif /* WIN32 || ACE_HAS_TSS_EMULATION || ACE_PSOS_HAS_TSS */
#if defined (ACE_HAS_TSS_EMULATION)
@@ -3222,11 +3198,11 @@ ACE_OS::thr_join (ACE_thread_t waiter_id,
#endif /* VXWORKS */
int
-ACE_OS::thr_key_detach (ACE_thread_key_t key, void * inst)
+ACE_OS::thr_key_detach (void *inst)
{
#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
if (ACE_TSS_Cleanup::lockable ())
- return ACE_TSS_Cleanup::instance()->detach (key, inst);
+ return ACE_TSS_Cleanup::instance()->detach (inst);
else
// We're in static constructor/destructor phase. Don't
// try to use the ACE_TSS_Cleanup instance because its lock
@@ -3234,7 +3210,6 @@ ACE_OS::thr_key_detach (ACE_thread_key_t key, void * inst)
// destroyed already. Just leak the key . . .
return -1;
#else
- ACE_UNUSED_ARG (key);
ACE_UNUSED_ARG (inst);
ACE_NOTSUP_RETURN (-1);
#endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
@@ -3385,7 +3360,7 @@ ACE_OS::thr_keycreate (ACE_thread_key_t *key,
// Extract out the thread-specific table instance and stash away
// the key and destructor so that we can free it up later on...
return ACE_TSS_Cleanup::instance ()->insert (*key, dest, inst);
- }
+ }
else
ACE_FAIL_RETURN (-1);
/* NOTREACHED */
@@ -3411,10 +3386,7 @@ ACE_OS::thr_keyfree (ACE_thread_key_t key)
# if defined (ACE_HAS_TSS_EMULATION)
// Release the key in the TSS_Emulation administration
ACE_TSS_Emulation::release_key (key);
- if (ACE_TSS_Cleanup::lockable ())
- return ACE_TSS_Cleanup::instance ()->remove (key);
- else
- return -1;
+ return ACE_TSS_Cleanup::instance ()->remove (key);
# elif defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)
ACE_UNUSED_ARG (key);
ACE_NOTSUP_RETURN (-1);
@@ -3428,14 +3400,12 @@ ACE_OS::thr_keyfree (ACE_thread_key_t key)
# elif defined (ACE_HAS_WTHREADS)
// Extract out the thread-specific table instance and free up
// the key and destructor.
- if (ACE_TSS_Cleanup::lockable ())
- return ACE_TSS_Cleanup::instance ()->remove (key);
+ ACE_TSS_Cleanup::instance ()->remove (key);
ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), ace_result_), int, -1);
# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)
// Extract out the thread-specific table instance and free up
// the key and destructor.
- if (ACE_TSS_Cleanup::lockable ())
- return ACE_TSS_Cleanup::instance ()->remove (key);
+ ACE_TSS_Cleanup::instance ()->remove (key);
return (::tsd_delete (key) == 0) ? 0 : -1;
# else
ACE_UNUSED_ARG (key);