Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

ACE_TSS_Cleanup Class Reference

Singleton that knows how to clean up all the thread-specific resources for Win32. More...

Collaboration diagram for ACE_TSS_Cleanup:

Collaboration graph
[legend]
List of all members.

Public Methods

 ~ACE_TSS_Cleanup (void)
void exit (void *status)
 Cleanup the thread-specific objects. Does _NOT_ exit the thread. More...

int insert (ACE_thread_key_t key, void(*destructor)(void *), void *inst)
 Insert a <key, destructor> tuple into the table. More...

int remove (ACE_thread_key_t key)
 Remove a <key, destructor> tuple from the table. More...

int detach (void *inst)
 Detaches a tss_instance from its key. More...

void key_used (ACE_thread_key_t key)
 Mark a key as being used by this thread. More...

int free_all_keys_left (void)
 Free all keys left in the table before destruction. More...


Static Public Methods

ACE_TSS_Cleanup * instance (void)
int lockable ()
 Indication of whether the ACE_TSS_CLEANUP_LOCK is usable, and therefore whether we are in static constructor/destructor phase or not. More...


Protected Methods

void dump (void)
 ACE_TSS_Cleanup (void)
 Ensure singleton. More...


Private Types

typedef ACE_TSS_Info ACE_TSS_TABLE [ACE_DEFAULT_THREAD_KEYS]
typedef ACE_TSS_InfoACE_TSS_TABLE_ITERATOR

Private Methods

ACE_TSS_Keystss_keys ()
 Accessor for this threads ACE_TSS_Keys instance. More...


Private Attributes

ACE_TSS_TABLE table_
 Table of <ACE_TSS_Info>'s. More...

ACE_thread_key_t in_use_
 Key for the thread-specific array of whether each TSS key is in use. More...


Static Private Attributes

ACE_TSS_Cleanup * instance_ = 0
 Pointer to the singleton instance. More...


Detailed Description

Singleton that knows how to clean up all the thread-specific resources for Win32.

All this nonsense is required since Win32 doesn't automatically cleanup thread-specific storage on thread exit, unlike real operating systems... ;-)

Definition at line 1789 of file OS.cpp.


Member Typedef Documentation

typedef ACE_TSS_Info ACE_TSS_Cleanup::ACE_TSS_TABLE[ACE_DEFAULT_THREAD_KEYS] [private]
 

Definition at line 1827 of file OS.cpp.

typedef ACE_TSS_Info* ACE_TSS_Cleanup::ACE_TSS_TABLE_ITERATOR [private]
 

Definition at line 1828 of file OS.cpp.


Constructor & Destructor Documentation

ACE_TSS_Cleanup::~ACE_TSS_Cleanup void   
 

Definition at line 1855 of file OS.cpp.

References instance_.

01856 {
01857   // Zero out the instance pointer to support lockable () accessor.
01858   ACE_TSS_Cleanup::instance_ = 0;
01859 }

ACE_TSS_Cleanup::ACE_TSS_Cleanup void    [protected]
 

Ensure singleton.

Definition at line 2001 of file OS.cpp.

References ACE_OS_TRACE.

02002   : in_use_ (ACE_OS::NULL_key)
02003 #if defined (ACE_HAS_TSS_EMULATION)
02004     // ACE_TSS_Emulation::total_keys () provides the value of the next
02005     // key to be created.
02006   , in_use_key_ (ACE_TSS_Emulation::total_keys ())
02007 #endif /* ACE_HAS_TSS_EMULATION */
02008 {
02009   ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
02010 }


Member Function Documentation

int ACE_TSS_Cleanup::detach void *    inst
 

Detaches a tss_instance from its key.

Definition at line 2083 of file OS.cpp.

References ACE_thread_key_t, ACE_TSS_CLEANUP_GUARD, remove, table_, and ACE_TSS_Info::tss_obj_.

Referenced by ACE_OS::thr_key_detach.

02084 {
02085   ACE_TSS_CLEANUP_GUARD
02086 
02087   ACE_TSS_TABLE_ITERATOR key_info = table_;
02088   int success = 0;
02089   int ref_cnt = 0;
02090 
02091   // Mark the key as detached in the TSS_Info table.
02092   // It only works for the first key that "inst" owns.
02093   // I don't know why.
02094   for (unsigned int i = 0;
02095        i < ACE_DEFAULT_THREAD_KEYS;
02096        ++key_info, ++i)
02097     {
02098       if (key_info->tss_obj_ == inst)
02099         {
02100           key_info->tss_obj_ = 0;
02101           ref_cnt = --key_info->thread_count_;
02102           success = 1;
02103           break;
02104         }
02105     }
02106 
02107   if (success == 0)
02108     return -1;
02109   else if (ref_cnt == 0)
02110     {
02111       // Mark the key as no longer being used.
02112       key_info->key_in_use (0);
02113 # if defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
02114       ACE_thread_key_t temp_key = key_info->key_;
02115 # endif /* ACE_WIN32 */
02116       int retv = this->remove (key_info->key_);
02117 
02118 # if defined (ACE_WIN32)
02119       ::TlsFree (temp_key);
02120 # elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)
02121       ::tsd_delete (temp_key);
02122 # endif /* ACE_WIN32 */
02123       return retv;
02124     }
02125 
02126   return 0;
02127 }

void ACE_TSS_Cleanup::dump void    [protected]
 

Definition at line 2149 of file OS.cpp.

References ACE_TSS_Info::dump, and table_.

02150 {
02151   // Iterate through all the thread-specific items and dump them all.
02152 
02153   ACE_TSS_TABLE_ITERATOR key_info = table_;
02154   for (unsigned int i = 0;
02155        i < ACE_DEFAULT_THREAD_KEYS;
02156        ++key_info, ++i)
02157     key_info->dump ();
02158 }

void ACE_TSS_Cleanup::exit void *    status
 

Cleanup the thread-specific objects. Does _NOT_ exit the thread.

Definition at line 1862 of file OS.cpp.

References ACE_OS_TRACE, ACE_TSS_CLEANUP_GUARD, ACE_TSS_Info::destructor_, ACE_TSS_Info::key_, ACE_TSS_Info::key_in_use, ACE_OS::NULL_key, remove, table_, ACE_TSS_Keys::test_and_clear, ACE_OS::thr_getspecific, ACE_OS::thr_keyfree, ACE_TSS_Info::thread_count_, tss_keys, and ACE_TSS_Info::tss_obj_.

Referenced by ACE_OS::cleanup_tss.

01863 {
01864   ACE_OS_TRACE ("ACE_TSS_Cleanup::exit");
01865 
01866   ACE_TSS_TABLE_ITERATOR key_info = table_;
01867   ACE_TSS_Info info_arr[ACE_DEFAULT_THREAD_KEYS];
01868   int info_ix = 0;
01869 
01870   // While holding the lock, we only collect the ACE_TSS_Info objects
01871   // in an array without invoking the according destructors.
01872   {
01873     ACE_TSS_CLEANUP_GUARD
01874 
01875     // Iterate through all the thread-specific items and free them all
01876     // up.
01877 
01878     for (unsigned int i = 0;
01879          i < ACE_DEFAULT_THREAD_KEYS;
01880          ++key_info, ++i)
01881       {
01882         if (key_info->key_ == ACE_OS::NULL_key  ||
01883             ! key_info->key_in_use ()) continue;
01884 
01885         // If the key's ACE_TSS_Info in-use bit for this thread was set,
01886         // unset it and decrement the key's thread_count_.
01887         if (! tss_keys ()->test_and_clear (key_info->key_))
01888           {
01889             --key_info->thread_count_;
01890           }
01891 
01892         void *tss_info = 0;
01893 
01894         if (key_info->destructor_
01895             && ACE_OS::thr_getspecific (key_info->key_, &tss_info) == 0
01896             && tss_info)
01897           {
01898             info_arr[info_ix].key_ = key_info->key_;
01899             info_arr[info_ix].destructor_ = key_info->destructor_;
01900             info_arr[info_ix++].tss_obj_ = key_info->tss_obj_;
01901           }
01902       }
01903   }
01904 
01905   // Now we have given up the ACE_TSS_Cleanup::lock_ and we start
01906   // invoking destructors, in the reverse order of creation.
01907   for (int i = info_ix - 1; i >= 0; --i)
01908     {
01909       void *tss_info = 0;
01910 
01911       ACE_OS::thr_getspecific (info_arr[i].key_, &tss_info);
01912 
01913       if (tss_info != 0)
01914         {
01915           // Only call the destructor if the value is non-zero for this
01916           // thread.
01917           (*info_arr[i].destructor_)(tss_info);
01918         }
01919     }
01920 
01921   // Acquire the ACE_TSS_CLEANUP_LOCK, then free TLS keys and remove
01922   // entries from ACE_TSS_Info table.
01923   {
01924     ACE_TSS_CLEANUP_GUARD
01925 
01926 # if 0
01927     // We shouldn't free the key and remove it from the table here
01928     // because if we do and some thread ends before other threads
01929     // even get started (or their TSS object haven't been created yet,)
01930     // it's entry will be removed from the table and we are in big chaos.
01931     // For TSS object, these have been done in ACE_TSS_Cleanup::detach.
01932     // Two other use cases will be user managed TSS'es and system wide
01933     // TSS, ones are users responsibilities and the others should be
01934     // persistant system wide.
01935     for (int i = 0; i < index; i++)
01936       {
01937 # if defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
01938         // Calling thr_keyfree here ensure the key
01939         // gets removed appropriately.  Notice that
01940         // a key should be removed before freeing it.
01941         ACE_OS::thr_keyfree (key_info->key_);
01942 # else
01943         // don't bother to free the key
01944         this->remove (key_info->key_);
01945 # endif /* ACE_WIN32 */
01946       }
01947 # endif /* 0 */
01948   }
01949 }

int ACE_TSS_Cleanup::free_all_keys_left void   
 

Free all keys left in the table before destruction.

Definition at line 1952 of file OS.cpp.

References ACE_thread_key_t, ACE_TSS_Info::key_, ACE_OS::NULL_key, and ACE_OS::thr_keyfree.

Referenced by ACE_OS::cleanup_tss.

01957 {
01958   ACE_thread_key_t key_arr[ACE_DEFAULT_THREAD_KEYS];
01959   ACE_TSS_TABLE_ITERATOR key_info = table_;
01960   unsigned int idx = 0;
01961   unsigned int i;
01962 
01963   for (i = 0;
01964        i < ACE_DEFAULT_THREAD_KEYS;
01965        ++key_info, ++i)
01966 #if defined (ACE_HAS_TSS_EMULATION)
01967     if (key_info->key_ != in_use_key_)
01968 #endif /* ACE_HAS_TSS_EMULATION */
01969       // Don't call ACE_OS::thr_keyfree () on ACE_TSS_Cleanup's own
01970       // key.  See the comments in ACE_OS::thr_key_detach ():  the key
01971       // doesn't get detached, so it will be in the table here.
01972       // However, there's no resource associated with it, so we don't
01973       // need to keyfree it.  The dynamic memory associated with it
01974       // was already deleted by ACE_TSS_Cleanup::exit (), so we don't
01975       // want to access it again.
01976       key_arr [idx++] = key_info->key_;
01977 
01978   for (i = 0; i < idx; i++)
01979     if (key_arr[i] != ACE_OS::NULL_key)
01980 #if defined (ACE_HAS_TSS_EMULATION)
01981       ACE_OS::thr_keyfree (key_arr[i]);
01982 #elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)
01983       // Don't call ACE_OS::thr_keyfree here.  It will try to use
01984       // <in_use_> which has already been cleaned up here.
01985       ::tsd_delete (key_arr[i]);
01986 #else /* ACE_WIN32 */
01987       // Don't call ACE_OS::thr_keyfree here.  It will try to use
01988       // <in_use_> which has already been cleaned up here.
01989       TlsFree (key_arr[i]);
01990 #endif /* ACE_HAS_TSS_EMULATION */
01991 
01992   return 0;
01993 }

int ACE_TSS_Cleanup::insert ACE_thread_key_t    key,
void(*    destructor)(void *),
void *    inst
 

Insert a <key, destructor> tuple into the table.

Definition at line 2035 of file OS.cpp.

References ACE_KEY_INDEX, ACE_OS_TRACE, ACE_thread_key_t, ACE_TSS_CLEANUP_GUARD, and table_.

Referenced by ACE_OS::thr_keycreate.

02038 {
02039   ACE_OS_TRACE ("ACE_TSS_Cleanup::insert");
02040   ACE_TSS_CLEANUP_GUARD
02041 
02042   ACE_KEY_INDEX (key_index, key);
02043   if (key_index < ACE_DEFAULT_THREAD_KEYS)
02044     {
02045       table_[key_index] = ACE_TSS_Info (key, destructor, inst);
02046       return 0;
02047     }
02048   else
02049     {
02050       return -1;
02051     }
02052 }

ACE_TSS_Cleanup * ACE_TSS_Cleanup::instance void    [static]
 

Definition at line 2013 of file OS.cpp.

References ACE_NEW_RETURN, ACE_OS_TRACE, ACE_TSS_CLEANUP_GUARD, and instance_.

Referenced by ACE_OS::cleanup_tss, ACE_OS::thr_key_detach, ACE_OS::thr_key_used, ACE_OS::thr_keycreate, ACE_OS::thr_keyfree, and ACE_OS::thr_setspecific.

02014 {
02015   ACE_OS_TRACE ("ACE_TSS_Cleanup::instance");
02016 
02017   // Create and initialize thread-specific key.
02018   if (ACE_TSS_Cleanup::instance_ == 0)
02019     {
02020       // Insure that we are serialized!
02021       ACE_TSS_CLEANUP_GUARD
02022 
02023       // Now, use the Double-Checked Locking pattern to make sure we
02024       // only create the ACE_TSS_Cleanup instance once.
02025       if (ACE_TSS_Cleanup::instance_ == 0)
02026         ACE_NEW_RETURN (ACE_TSS_Cleanup::instance_,
02027                         ACE_TSS_Cleanup,
02028                         0);
02029     }
02030 
02031   return ACE_TSS_Cleanup::instance_;
02032 }

void ACE_TSS_Cleanup::key_used ACE_thread_key_t    key
 

Mark a key as being used by this thread.

Definition at line 2130 of file OS.cpp.

References ACE_KEY_INDEX, ACE_thread_key_t, ACE_TSS_CLEANUP_GUARD, ACE_TSS_Info::key_in_use, table_, ACE_TSS_Keys::test_and_set, ACE_TSS_Info::thread_count_, and tss_keys.

Referenced by ACE_OS::thr_key_used, and ACE_OS::thr_setspecific.

02131 {
02132   // If the key's ACE_TSS_Info in-use bit for this thread is not set,
02133   // set it and increment the key's thread_count_.
02134   if (! tss_keys ()->test_and_set (key))
02135     {
02136       ACE_TSS_CLEANUP_GUARD
02137 
02138       // Retrieve the key's ACE_TSS_Info and increment its thread_count_.
02139       ACE_KEY_INDEX (key_index, key);
02140       ACE_TSS_Info &key_info = this->table_ [key_index];
02141       if (!key_info.key_in_use ())
02142         key_info.key_in_use (1);
02143       else
02144         ++key_info.thread_count_;
02145     }
02146 }

int ACE_TSS_Cleanup::lockable   [inline, static]
 

Indication of whether the ACE_TSS_CLEANUP_LOCK is usable, and therefore whether we are in static constructor/destructor phase or not.

Definition at line 1817 of file OS.cpp.

References instance_.

Referenced by ACE_OS::thr_key_detach.

01817 { return instance_ != 0; }

int ACE_TSS_Cleanup::remove ACE_thread_key_t    key
 

Remove a <key, destructor> tuple from the table.

Definition at line 2055 of file OS.cpp.

References ACE_KEY_INDEX, ACE_OS_TRACE, ACE_thread_key_t, ACE_TSS_CLEANUP_GUARD, ACE_TSS_Info::destructor_, ACE_TSS_Info::key_, ACE_TSS_Info::key_in_use, ACE_OS::NULL_key, ACE_OS_Object_Manager::shutting_down, table_, ACE_TSS_Keys::test_and_clear, and tss_keys.

Referenced by detach, exit, and ACE_OS::thr_keyfree.

02056 {
02057   ACE_OS_TRACE ("ACE_TSS_Cleanup::remove");
02058   ACE_TSS_CLEANUP_GUARD
02059 
02060   ACE_KEY_INDEX (key_index, key);
02061   if (key_index < ACE_DEFAULT_THREAD_KEYS)
02062     {
02063       // "Remove" the TSS_Info table entry by zeroing out its key_ and
02064       // destructor_ fields.  Also, keep track of the number threads
02065       // using the key.
02066       ACE_TSS_Info &info = this->table_ [key_index];
02067 
02068       // Don't bother to test/clear the in "use bit" if the program is
02069       // shutting down.  Doing so will cause a new ACE_TSS object to be
02070       // created again.
02071       if (!ACE_OS_Object_Manager::shutting_down ())
02072         tss_keys ()->test_and_clear (info.key_);
02073       info.key_in_use (0);
02074       info.key_ = ACE_OS::NULL_key;
02075       info.destructor_ = 0;
02076       return 0;
02077     }
02078   else
02079     return -1;
02080 }

ACE_TSS_Keys * ACE_TSS_Cleanup::tss_keys   [private]
 

Accessor for this threads ACE_TSS_Keys instance.

Definition at line 2161 of file OS.cpp.

References ACE_NEW_RETURN, ACE_TSS_CLEANUP_GUARD, ACE_TSS_Cleanup_keys_destroyer, in_use_, ACE_OS::NULL_key, ACE_OS::thr_getspecific, ACE_OS::thr_keycreate, and ACE_OS::thr_setspecific.

Referenced by exit, key_used, and remove.

02162 {
02163   if (in_use_ == ACE_OS::NULL_key)
02164     {
02165       ACE_TSS_CLEANUP_GUARD
02166       // Double-check;
02167       if (in_use_ == ACE_OS::NULL_key)
02168         {
02169           // Initialize in_use_ with a new key.
02170           if (ACE_OS::thr_keycreate (&in_use_,
02171                                      &ACE_TSS_Cleanup_keys_destroyer))
02172             return 0; // Major problems, this should *never* happen!
02173         }
02174     }
02175 
02176   ACE_TSS_Keys *ts_keys = 0;
02177   if (ACE_OS::thr_getspecific (in_use_,
02178         ACE_reinterpret_cast (void **, &ts_keys)) == -1)
02179     return 0; // This should not happen!
02180 
02181   if (ts_keys == 0)
02182     {
02183       ACE_NEW_RETURN (ts_keys,
02184                       ACE_TSS_Keys,
02185                       0);
02186       // Store the dynamically allocated pointer in thread-specific
02187       // storage.
02188       if (ACE_OS::thr_setspecific (in_use_,
02189             ACE_reinterpret_cast (void *,
02190                                   ts_keys)) == -1)
02191         {
02192           delete ts_keys;
02193           return 0; // Major problems, this should *never* happen!
02194         }
02195     }
02196 
02197   return ts_keys;
02198 }


Member Data Documentation

ACE_thread_key_t ACE_TSS_Cleanup::in_use_ [private]
 

Key for the thread-specific array of whether each TSS key is in use.

Definition at line 1834 of file OS.cpp.

Referenced by tss_keys.

ACE_TSS_Cleanup * ACE_TSS_Cleanup::instance_ = 0 [static, private]
 

Pointer to the singleton instance.

Definition at line 1853 of file OS.cpp.

Referenced by instance, lockable, and ~ACE_TSS_Cleanup.

ACE_TSS_TABLE ACE_TSS_Cleanup::table_ [private]
 

Table of <ACE_TSS_Info>'s.

Definition at line 1831 of file OS.cpp.

Referenced by detach, dump, exit, insert, key_used, and remove.


The documentation for this class was generated from the following file:
Generated on Mon Jun 16 12:58:42 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002