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 585 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 644 of file OS_NS_Thread.cpp.

typedef ACE_TSS_Info* ACE_TSS_Cleanup::ACE_TSS_TABLE_ITERATOR [private]
 

Definition at line 645 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 907 of file OS_NS_Thread.cpp.

References ACE_OS_TRACE.

00908   : in_use_ (ACE_OS::NULL_key)
00909 {
00910   ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
00911 }

ACE_TSS_Cleanup::~ACE_TSS_Cleanup void   )  [private]
 

Definition at line 824 of file OS_NS_Thread.cpp.

00825 {
00826 }


Member Function Documentation

void ACE_TSS_Cleanup::dump void   )  [private]
 

Definition at line 1056 of file OS_NS_Thread.cpp.

References ACE_TSS_TABLE_ITERATOR, and ACE_TSS_Info::dump().

01057 {
01058 # if defined (ACE_HAS_DUMP)
01059   // Iterate through all the thread-specific items and dump them all.
01060 
01061   ACE_TSS_TABLE_ITERATOR key_info = table_;
01062   for (unsigned int i = 0;
01063        i < ACE_DEFAULT_THREAD_KEYS;
01064        ++key_info, ++i)
01065     key_info->dump ();
01066 # endif /* ACE_HAS_DUMP */
01067 }

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 1070 of file OS_NS_Thread.cpp.

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

Referenced by thread_exit(), and thread_release().

01071 {
01072   if (this->in_use_ == ACE_OS::NULL_key)
01073     return false;
01074   if (ACE_OS::thr_getspecific (in_use_,
01075           reinterpret_cast<void **> (&tss_keys)) == -1)
01076     {
01077       ACE_ASSERT (false);
01078       return false; // This should not happen!
01079     }
01080   return tss_keys != 0;
01081 }

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 937 of file OS_NS_Thread.cpp.

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

00938 {
00939   ACE_OS_TRACE ("ACE_TSS_Cleanup::free_key");
00940   ACE_TSS_CLEANUP_GUARD
00941   ACE_KEY_INDEX (key_index, key);
00942   if (key_index < ACE_DEFAULT_THREAD_KEYS)
00943     {
00944       return remove_key (this->table_ [key_index]);
00945     }
00946   return -1;
00947 }

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 914 of file OS_NS_Thread.cpp.

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

00916 {
00917   ACE_OS_TRACE ("ACE_TSS_Cleanup::insert");
00918   ACE_TSS_CLEANUP_GUARD
00919 
00920   ACE_KEY_INDEX (key_index, key);
00921   ACE_ASSERT (key_index < ACE_DEFAULT_THREAD_KEYS);
00922   if (key_index < ACE_DEFAULT_THREAD_KEYS)
00923     {
00924       ACE_ASSERT (table_[key_index].thread_count_ == -1);
00925       table_[key_index] = ACE_TSS_Info (key, destructor);
00926       table_[key_index].thread_count_ = 0; // inserting it does not use it
00927                                            // but it does "allocate" it
00928       return 0;
00929     }
00930   else
00931     {
00932       return -1;
00933     }
00934 }

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 950 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().

00951 {
00952   // assume CLEANUP_GUARD is held by caller
00953   ACE_OS_TRACE ("ACE_TSS_Cleanup::remove_key");
00954 
00955 #if 0 // This was a good idea, but POSIX says it's legal to delete used keys.
00956       // When this is done, any existing TSS objects controlled by this key are leaked
00957       // There is no "right thing" to do in this case
00958 
00959   // only remove it if all threads are done with it
00960   if (info.thread_count_ != 0)
00961     {
00962       return -1;
00963     }
00964 #endif // 0
00965 
00966 #if !defined (ACE_HAS_TSS_EMULATION)
00967   ACE_OS_thread_key_t temp_key = info.key_;
00968   ACE_OS::thr_keyfree_native (temp_key);
00969 #endif /* !ACE_HAS_TSS_EMULATION */
00970   if (info.key_ == this->in_use_)
00971     {
00972       this->in_use_ = ACE_OS::NULL_key;
00973     }
00974   info.key_in_use (0);
00975   info.destructor_ = 0;
00976   return 0;
00977 }

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 980 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().

00981 {
00982   // variables to hold the destructor and the object to be destructed
00983   // the actual call is deferred until the guard is released
00984   ACE_TSS_Info::Destructor destructor = 0;
00985   void * tss_obj = 0;
00986 
00987   // scope the guard
00988   {
00989     ACE_TSS_CLEANUP_GUARD
00990 
00991     ACE_KEY_INDEX (key_index, key);
00992     ACE_ASSERT (key_index < sizeof(this->table_)/sizeof(this->table_[0])
00993         && this->table_[key_index].key_ == key);
00994     ACE_TSS_Info &info = this->table_ [key_index];
00995 
00996     // sanity check
00997     if (!info.key_in_use ())
00998       {
00999         return -1;
01000       }
01001 
01002     this->thread_release (info, destructor, tss_obj);
01003   } // end of scope for the Guard
01004   // if there's a destructor and an object to be destroyed
01005   if (destructor != 0 && tss_obj != 0)
01006     {
01007       (*destructor) (tss_obj);
01008     }
01009   return 0;
01010 }

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 829 of file OS_NS_Thread.cpp.

References 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().

00830 {
00831   ACE_OS_TRACE ("ACE_TSS_Cleanup::thread_exit");
00832   // variables to hold the destructors
00833   // and pointers to the object to be destructed
00834   // the actual destruction is deferred until the guard is released
00835   ACE_TSS_Info::Destructor destructor[ACE_DEFAULT_THREAD_KEYS];
00836   void * tss_obj[ACE_DEFAULT_THREAD_KEYS];
00837   // count of items to be destroyed
00838   unsigned int d_count = 0;
00839 
00840   // scope the guard
00841   {
00842     ACE_TSS_CLEANUP_GUARD
00843 
00844     // if not initialized or already cleaned up
00845     ACE_TSS_Keys *this_thread_keys = 0;
00846     if (! find_tss_keys (this_thread_keys) )
00847       {
00848         return;
00849       }
00850 
00851     // Minor hack: Iterating in reverse order means the LOG buffer which is
00852     // accidentally allocated first will be accidentally deallocated (almost)
00853     // last -- in case someone logs something from the other destructors.
00854     // applications should not count on this behavior because platforms which
00855     // do not use ACE_TSS_Cleanup may delete objects in other orders.
00856     unsigned int key_index = ACE_DEFAULT_THREAD_KEYS;
00857     while( key_index > 0)
00858       {
00859         --key_index;
00860         ACE_TSS_Info & info = this->table_[key_index];
00861         // if this key is in use by this thread
00862         if (info.key_in_use () && this_thread_keys->is_set(info.key_))
00863           {
00864             // defer deleting the in-use key until all others have been deleted
00865             if(info.key_ != this->in_use_)
00866               {
00867                 destructor[d_count] = 0;
00868                 tss_obj[d_count] = 0;
00869                 this->thread_release (info, destructor[d_count], tss_obj[d_count]);
00870                 if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
00871                   {
00872                     ++d_count;
00873                   }
00874               }
00875           }
00876       }
00877 
00878     // remove the in_use bit vector last
00879     ACE_KEY_INDEX (use_index, this->in_use_);
00880     ACE_TSS_Info & info = this->table_[use_index];
00881     destructor[d_count] = 0;
00882     tss_obj[d_count] = 0;
00883     this->thread_release (info, destructor[d_count], tss_obj[d_count]);
00884     if (destructor[d_count] != 0 &&  tss_obj[d_count] != 0)
00885       {
00886         ++d_count;
00887       }
00888 #if defined (ACE_HAS_TSS_EMULATION)
00889     ACE_TSS_Emulation::ts_object (this->in_use_) = 0;
00890 #else // defined (ACE_HAS_TSS_EMULATION)
00891     ACE_OS::thr_setspecific_native (info.key_, 0);
00892 #endif // defined (ACE_HAS_TSS_EMULATION)
00893 
00894   } // end of guard scope
00895   for (unsigned int d_index = 0; d_index < d_count; ++d_index)
00896     {
00897       (*destructor[d_index])(tss_obj[d_index]);
00898     }
00899 }

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 1013 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().

01017 {
01018   // assume guard is held by caller
01019   // Find the TSS keys (if any) for this thread
01020   // do not create them if they don't exist
01021   ACE_TSS_Keys * thread_keys = 0;
01022   if (find_tss_keys (thread_keys))
01023     {
01024         // if this key is in use by this thread
01025       if (thread_keys->test_and_clear(info.key_) == 0)
01026       {
01027         // save destructor & pointer to tss object
01028         // until after the guard is released
01029         destructor = info.destructor_;
01030         ACE_OS::thr_getspecific (info.key_, &tss_obj);
01031         ACE_ASSERT (info.thread_count_ > 0);
01032         --info.thread_count_;
01033       }
01034     }
01035 }

void ACE_TSS_Cleanup::thread_use_key ACE_thread_key_t  key  ) 
 

Mark a key as being used by this thread.

Definition at line 1038 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().

01039 {
01040   // If the key's ACE_TSS_Info in-use bit for this thread is not set,
01041   // set it and increment the key's thread_count_.
01042   if (! tss_keys ()->test_and_set (key))
01043     {
01044       ACE_TSS_CLEANUP_GUARD
01045 
01046       // Retrieve the key's ACE_TSS_Info and increment its thread_count_.
01047       ACE_KEY_INDEX (key_index, key);
01048       ACE_TSS_Info &key_info = this->table_ [key_index];
01049 
01050       ACE_ASSERT (key_info.key_in_use ());
01051       ++key_info.thread_count_;
01052     }
01053 }

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 1084 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().

01085 {
01086   if (this->in_use_ == ACE_OS::NULL_key)
01087     {
01088       ACE_TSS_CLEANUP_GUARD
01089       // Double-check;
01090       if (in_use_ == ACE_OS::NULL_key)
01091         {
01092           // Initialize in_use_ with a new key.
01093           if (ACE_OS::thr_keycreate (&in_use_,
01094                                      &ACE_TSS_Cleanup_keys_destroyer))
01095             {
01096               ACE_ASSERT (false);
01097               return 0; // Major problems, this should *never* happen!
01098             }
01099         }
01100     }
01101 
01102   ACE_TSS_Keys *ts_keys = 0;
01103   if (ACE_OS::thr_getspecific (in_use_,
01104                                reinterpret_cast <void **> (&ts_keys)) == -1)
01105     {
01106       ACE_ASSERT (false);
01107       return 0; // This should not happen!
01108     }
01109 
01110   if (ts_keys == 0)
01111     {
01112       ACE_NEW_RETURN (ts_keys,
01113                       ACE_TSS_Keys,
01114                       0);
01115       // Store the dynamically allocated pointer in thread-specific
01116       // storage.
01117       if (ACE_OS::thr_setspecific (in_use_,
01118                                    reinterpret_cast <void *> (ts_keys)) == -1)
01119         {
01120           ACE_ASSERT (false);
01121           delete ts_keys;
01122           return 0; // Major problems, this should *never* happen!
01123         }
01124     }
01125 
01126   return ts_keys;
01127 }


Friends And Related Function Documentation

friend class TSS_Cleanup_Instance [friend]
 

ACE_TSS_Cleanup access only via TSS_Cleanup_Instance.

Definition at line 640 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 654 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 648 of file OS_NS_Thread.cpp.


The documentation for this class was generated from the following file:
Generated on Thu Nov 9 11:31:59 2006 for ACE by doxygen 1.3.6