ACE_TSS_Cleanup Class Reference

Singleton that helps to manage the lifetime of TSS objects and keys. More...

Collaboration diagram for ACE_TSS_Cleanup:

Collaboration graph
[legend]
List of all members.

Public Member Functions

int insert (ACE_thread_key_t key, void(*destructor)(void *))
void thread_use_key (ACE_thread_key_t key)
 Mark a key as being used by this thread.

int thread_detach_key (ACE_thread_key_t key)
int free_key (ACE_thread_key_t key)
void thread_exit (void)

Private Types

typedef ACE_TSS_Info ACE_TSS_TABLE [ACE_DEFAULT_THREAD_KEYS]
typedef ACE_TSS_InfoACE_TSS_TABLE_ITERATOR

Private Member Functions

void dump (void)
void thread_release (ACE_TSS_Info &info, ACE_TSS_Info::Destructor &destructor, void *&tss_obj)
int remove_key (ACE_TSS_Info &info)
bool find_tss_keys (ACE_TSS_Keys *&thread_keys) const
ACE_TSS_Keystss_keys ()
 ACE_TSS_Cleanup (void)
 Ensure singleton.

 ~ACE_TSS_Cleanup (void)

Private Attributes

ACE_TSS_TABLE table_
 Table of 's.

ACE_thread_key_t in_use_

Friends

class TSS_Cleanup_Instance
 ACE_TSS_Cleanup access only via TSS_Cleanup_Instance.


Detailed Description

Singleton that helps to manage the lifetime of TSS objects and keys.

Definition at line 532 of file OS_NS_Thread.cpp.


Member Typedef Documentation

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

Definition at line 591 of file OS_NS_Thread.cpp.

typedef ACE_TSS_Info* ACE_TSS_Cleanup::ACE_TSS_TABLE_ITERATOR [private]
 

Definition at line 592 of file OS_NS_Thread.cpp.

Referenced by dump().


Constructor & Destructor Documentation

ACE_TSS_Cleanup::ACE_TSS_Cleanup void   )  [private]
 

Ensure singleton.

Definition at line 854 of file OS_NS_Thread.cpp.

References ACE_OS_TRACE.

00855   : in_use_ (ACE_OS::NULL_key)
00856 {
00857   ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
00858 }

ACE_TSS_Cleanup::~ACE_TSS_Cleanup void   )  [private]
 

Definition at line 771 of file OS_NS_Thread.cpp.

00772 {
00773 }


Member Function Documentation

void ACE_TSS_Cleanup::dump void   )  [private]
 

Definition at line 1003 of file OS_NS_Thread.cpp.

References ACE_DEFAULT_THREAD_KEYS, ACE_TSS_TABLE_ITERATOR, and ACE_TSS_Info::dump().

01004 {
01005 # if defined (ACE_HAS_DUMP)
01006   // Iterate through all the thread-specific items and dump them all.
01007 
01008   ACE_TSS_TABLE_ITERATOR key_info = table_;
01009   for (unsigned int i = 0;
01010        i < ACE_DEFAULT_THREAD_KEYS;
01011        ++key_info, ++i)
01012     key_info->dump ();
01013 # endif /* ACE_HAS_DUMP */
01014 }

bool ACE_TSS_Cleanup::find_tss_keys ACE_TSS_Keys *&  thread_keys  )  const [private]
 

Find the TSS keys (if any) for this thread.

Parameters:
thread_keys reference to pointer to be filled in by this function.
Returns:
false if keys don't exist.

Definition at line 1017 of file OS_NS_Thread.cpp.

References ACE_ASSERT, in_use_, and ACE_OS::thr_getspecific().

Referenced by thread_exit(), and thread_release().

01018 {
01019   if (this->in_use_ == ACE_OS::NULL_key)
01020     return false;
01021   if (ACE_OS::thr_getspecific (in_use_,
01022           reinterpret_cast<void **> (&tss_keys)) == -1)
01023     {
01024       ACE_ASSERT (false);
01025       return false; // This should not happen!
01026     }
01027   return tss_keys != 0;
01028 }

int ACE_TSS_Cleanup::free_key ACE_thread_key_t  key  ) 
 

This key is no longer used Release key if use count == 0 fail if use_count != 0;

Parameters:
key the key to be released

Definition at line 884 of file OS_NS_Thread.cpp.

References ACE_DEFAULT_THREAD_KEYS, ACE_KEY_INDEX, ACE_OS_TRACE, ACE_thread_key_t, ACE_TSS_CLEANUP_GUARD, and remove_key().

00885 {
00886   ACE_OS_TRACE ("ACE_TSS_Cleanup::free_key");
00887   ACE_TSS_CLEANUP_GUARD
00888   ACE_KEY_INDEX (key_index, key);
00889   if (key_index < ACE_DEFAULT_THREAD_KEYS)
00890     {
00891       return remove_key (this->table_ [key_index]);
00892     }
00893   return -1;
00894 }

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

Register a newly-allocated key

Parameters:
key the key to be monitored
destructor the function to call to delete objects stored via this key

Definition at line 861 of file OS_NS_Thread.cpp.

References ACE_ASSERT, ACE_DEFAULT_THREAD_KEYS, ACE_KEY_INDEX, ACE_OS_TRACE, ACE_thread_key_t, ACE_TSS_CLEANUP_GUARD, and ACE_TSS_Info::thread_count_.

00863 {
00864   ACE_OS_TRACE ("ACE_TSS_Cleanup::insert");
00865   ACE_TSS_CLEANUP_GUARD
00866 
00867   ACE_KEY_INDEX (key_index, key);
00868   ACE_ASSERT (key_index < ACE_DEFAULT_THREAD_KEYS);
00869   if (key_index < ACE_DEFAULT_THREAD_KEYS)
00870     {
00871       ACE_ASSERT (table_[key_index].thread_count_ == -1);
00872       table_[key_index] = ACE_TSS_Info (key, destructor);
00873       table_[key_index].thread_count_ = 0; // inserting it does not use it
00874                                            // but it does "allocate" it
00875       return 0;
00876     }
00877   else
00878     {
00879       return -1;
00880     }
00881 }

int ACE_TSS_Cleanup::remove_key ACE_TSS_Info info  )  [private]
 

remove key if it's unused (thread_count == 0)

Parameters:
info reference to the info for this key

Definition at line 897 of file OS_NS_Thread.cpp.

References ACE_OS_thread_key_t, ACE_OS_TRACE, ACE_TSS_Info::destructor_, in_use_, ACE_TSS_Info::key_, ACE_TSS_Info::key_in_use(), and ACE_TSS_Info::thread_count_.

Referenced by free_key().

00898 {
00899   // assume CLEANUP_GUARD is held by caller
00900   ACE_OS_TRACE ("ACE_TSS_Cleanup::remove_key");
00901 
00902 #if 0 // This was a good idea, but POSIX says it's legal to delete used keys.
00903       // When this is done, any existing TSS objects controlled by this key are leaked
00904       // There is no "right thing" to do in this case
00905 
00906   // only remove it if all threads are done with it
00907   if (info.thread_count_ != 0)
00908     {
00909       return -1;
00910     }
00911 #endif // 0
00912 
00913 #if !defined (ACE_HAS_TSS_EMULATION)
00914   ACE_OS_thread_key_t temp_key = info.key_;
00915   ACE_OS::thr_keyfree_native (temp_key);
00916 #endif /* !ACE_HAS_TSS_EMULATION */
00917   if (info.key_ == this->in_use_)
00918     {
00919       this->in_use_ = ACE_OS::NULL_key;
00920     }
00921   info.key_in_use (0);
00922   info.destructor_ = 0;
00923   return 0;
00924 }

int ACE_TSS_Cleanup::thread_detach_key ACE_thread_key_t  key  ) 
 

This thread is no longer using this key call destructor if appropriate

Definition at line 927 of file OS_NS_Thread.cpp.

References ACE_ASSERT, ACE_KEY_INDEX, ACE_thread_key_t, ACE_TSS_CLEANUP_GUARD, ACE_TSS_Info::Destructor, ACE_TSS_Info::key_in_use(), and thread_release().

00928 {
00929   // variables to hold the destructor and the object to be destructed
00930   // the actual call is deferred until the guard is released
00931   ACE_TSS_Info::Destructor destructor = 0;
00932   void * tss_obj = 0;
00933 
00934   // scope the guard
00935   {
00936     ACE_TSS_CLEANUP_GUARD
00937 
00938     ACE_KEY_INDEX (key_index, key);
00939     ACE_ASSERT (key_index < sizeof(this->table_)/sizeof(this->table_[0])
00940         && this->table_[key_index].key_ == key);
00941     ACE_TSS_Info &info = this->table_ [key_index];
00942 
00943     // sanity check
00944     if (!info.key_in_use ())
00945       {
00946         return -1;
00947       }
00948 
00949     this->thread_release (info, destructor, tss_obj);
00950   } // end of scope for the Guard
00951   // if there's a destructor and an object to be destroyed
00952   if (destructor != 0 && tss_obj != 0)
00953     {
00954       (*destructor) (tss_obj);
00955     }
00956   return 0;
00957 }

void ACE_TSS_Cleanup::thread_exit void   ) 
 

Cleanup the thread-specific objects. Does _NOT_ exit the thread. For each used key perform the same actions as free_key.

Definition at line 776 of file OS_NS_Thread.cpp.

References ACE_DEFAULT_THREAD_KEYS, ACE_KEY_INDEX, ACE_OS_TRACE, ACE_TSS_CLEANUP_GUARD, ACE_TSS_Info::Destructor, find_tss_keys(), in_use_, ACE_TSS_Info::key_, ACE_TSS_Info::key_in_use(), and thread_release().

00777 {
00778   ACE_OS_TRACE ("ACE_TSS_Cleanup::thread_exit");
00779   // variables to hold the destructors
00780   // and pointers to the object to be destructed
00781   // the actual destruction is deferred until the guard is released
00782   ACE_TSS_Info::Destructor destructor[ACE_DEFAULT_THREAD_KEYS];
00783   void * tss_obj[ACE_DEFAULT_THREAD_KEYS];
00784   // count of items to be destroyed
00785   unsigned int d_count = 0;
00786 
00787   // scope the guard
00788   {
00789     ACE_TSS_CLEANUP_GUARD
00790 
00791     // if not initialized or already cleaned up
00792     ACE_TSS_Keys *this_thread_keys = 0;
00793     if (! find_tss_keys (this_thread_keys) )
00794       {
00795         return;
00796       }
00797 
00798     // Minor hack: Iterating in reverse order means the LOG buffer which is
00799     // accidentally allocated first will be accidentally deallocated (almost)
00800     // last -- in case someone logs something from the other destructors.
00801     // applications should not count on this behavior because platforms which
00802     // do not use ACE_TSS_Cleanup may delete objects in other orders.
00803     unsigned int key_index = ACE_DEFAULT_THREAD_KEYS;
00804     while( key_index > 0)
00805       {
00806         --key_index;
00807         ACE_TSS_Info & info = this->table_[key_index];
00808         // if this key is in use by this thread
00809         if (info.key_in_use () && this_thread_keys->is_set(info.key_))
00810           {
00811             // defer deleting the in-use key until all others have been deleted
00812             if(info.key_ != this->in_use_)
00813               {
00814                 destructor[d_count] = 0;
00815                 tss_obj[d_count] = 0;
00816                 this->thread_release (info, destructor[d_count], tss_obj[d_count]);
00817                 if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
00818                   {
00819                     ++d_count;
00820                   }
00821               }
00822           }
00823       }
00824 
00825     // remove the in_use bit vector last
00826     ACE_KEY_INDEX (use_index, this->in_use_);
00827     ACE_TSS_Info & info = this->table_[use_index];
00828     destructor[d_count] = 0;
00829     tss_obj[d_count] = 0;
00830     this->thread_release (info, destructor[d_count], tss_obj[d_count]);
00831     if (destructor[d_count] != 0 &&  tss_obj[d_count] != 0)
00832       {
00833         ++d_count;
00834       }
00835 #if defined (ACE_HAS_TSS_EMULATION)
00836     ACE_TSS_Emulation::ts_object (this->in_use_) = 0;
00837 #else // defined (ACE_HAS_TSS_EMULATION)
00838     ACE_OS::thr_setspecific_native (info.key_, 0);
00839 #endif // defined (ACE_HAS_TSS_EMULATION)
00840 
00841   } // end of guard scope
00842   for (unsigned int d_index = 0; d_index < d_count; ++d_index)
00843     {
00844       (*destructor[d_index])(tss_obj[d_index]);
00845     }
00846 }

void ACE_TSS_Cleanup::thread_release ACE_TSS_Info info,
ACE_TSS_Info::Destructor destructor,
void *&  tss_obj
[private]
 

Release a key used by this thread

Parameters:
info reference to the info for this key
destructor out arg to receive destructor function ptr
tss_obj out arg to receive pointer to deletable object

Definition at line 960 of file OS_NS_Thread.cpp.

References ACE_ASSERT, ACE_TSS_Info::Destructor, ACE_TSS_Info::destructor_, find_tss_keys(), ACE_TSS_Info::key_, ACE_TSS_Keys::test_and_clear(), ACE_OS::thr_getspecific(), and ACE_TSS_Info::thread_count_.

Referenced by thread_detach_key(), and thread_exit().

00964 {
00965   // assume guard is held by caller
00966   // Find the TSS keys (if any) for this thread
00967   // do not create them if they don't exist
00968   ACE_TSS_Keys * thread_keys = 0;
00969   if (find_tss_keys (thread_keys))
00970     {
00971         // if this key is in use by this thread
00972       if (thread_keys->test_and_clear(info.key_) == 0)
00973       {
00974         // save destructor & pointer to tss object
00975         // until after the guard is released
00976         destructor = info.destructor_;
00977         ACE_OS::thr_getspecific (info.key_, &tss_obj);
00978         ACE_ASSERT (info.thread_count_ > 0);
00979         --info.thread_count_;
00980       }
00981     }
00982 }

void ACE_TSS_Cleanup::thread_use_key ACE_thread_key_t  key  ) 
 

Mark a key as being used by this thread.

Definition at line 985 of file OS_NS_Thread.cpp.

References ACE_ASSERT, ACE_KEY_INDEX, ACE_thread_key_t, ACE_TSS_CLEANUP_GUARD, ACE_TSS_Info::key_in_use(), ACE_TSS_Keys::test_and_set(), ACE_TSS_Info::thread_count_, and tss_keys().

00986 {
00987   // If the key's ACE_TSS_Info in-use bit for this thread is not set,
00988   // set it and increment the key's thread_count_.
00989   if (! tss_keys ()->test_and_set (key))
00990     {
00991       ACE_TSS_CLEANUP_GUARD
00992 
00993       // Retrieve the key's ACE_TSS_Info and increment its thread_count_.
00994       ACE_KEY_INDEX (key_index, key);
00995       ACE_TSS_Info &key_info = this->table_ [key_index];
00996 
00997       ACE_ASSERT (key_info.key_in_use ());
00998       ++key_info.thread_count_;
00999     }
01000 }

ACE_TSS_Keys * ACE_TSS_Cleanup::tss_keys  )  [private]
 

Accessor for this threads ACE_TSS_Keys instance. Creates the keys if necessary.

Definition at line 1031 of file OS_NS_Thread.cpp.

References ACE_ASSERT, ACE_NEW_RETURN, ACE_TSS_CLEANUP_GUARD, ACE_TSS_Cleanup_keys_destroyer(), in_use_, ACE_OS::thr_getspecific(), ACE_OS::thr_keycreate(), and ACE_OS::thr_setspecific().

Referenced by thread_use_key().

01032 {
01033   if (this->in_use_ == ACE_OS::NULL_key)
01034     {
01035       ACE_TSS_CLEANUP_GUARD
01036       // Double-check;
01037       if (in_use_ == ACE_OS::NULL_key)
01038         {
01039           // Initialize in_use_ with a new key.
01040           if (ACE_OS::thr_keycreate (&in_use_,
01041                                      &ACE_TSS_Cleanup_keys_destroyer))
01042             {
01043               ACE_ASSERT (false);
01044               return 0; // Major problems, this should *never* happen!
01045             }
01046         }
01047     }
01048 
01049   ACE_TSS_Keys *ts_keys = 0;
01050   if (ACE_OS::thr_getspecific (in_use_,
01051                                reinterpret_cast <void **> (&ts_keys)) == -1)
01052     {
01053       ACE_ASSERT (false);
01054       return 0; // This should not happen!
01055     }
01056 
01057   if (ts_keys == 0)
01058     {
01059       ACE_NEW_RETURN (ts_keys,
01060                       ACE_TSS_Keys,
01061                       0);
01062       // Store the dynamically allocated pointer in thread-specific
01063       // storage.
01064       if (ACE_OS::thr_setspecific (in_use_,
01065                                    reinterpret_cast <void *> (ts_keys)) == -1)
01066         {
01067           ACE_ASSERT (false);
01068           delete ts_keys;
01069           return 0; // Major problems, this should *never* happen!
01070         }
01071     }
01072 
01073   return ts_keys;
01074 }


Friends And Related Function Documentation

friend class TSS_Cleanup_Instance [friend]
 

ACE_TSS_Cleanup access only via TSS_Cleanup_Instance.

Definition at line 587 of file OS_NS_Thread.cpp.


Member Data Documentation

ACE_thread_key_t ACE_TSS_Cleanup::in_use_ [private]
 

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.

Definition at line 601 of file OS_NS_Thread.cpp.

Referenced by find_tss_keys(), remove_key(), thread_exit(), and tss_keys().

ACE_TSS_TABLE ACE_TSS_Cleanup::table_ [private]
 

Table of 's.

Definition at line 595 of file OS_NS_Thread.cpp.


The documentation for this class was generated from the following file:
Generated on Sun Jan 27 12:59:12 2008 for ACE by doxygen 1.3.6