ACE_TSS<TYPE>::ACE_TSS (TYPE *ts_obj) : once_ (false), key_ (ACE_OS::NULL_key) { // If caller has passed us a non-NULL TYPE *, then we'll just use // this to initialize the thread-specific value. Thus, subsequent // calls to operator->() will return this value. This is useful // since it enables us to assign objects to thread-specific data // that have arbitrarily complex constructors! if (ts_obj != 0) { if (this->ts_init () == -1) { // Save/restore errno. ACE_Errno_Guard error (errno); // What should we do if this call fails?! #if defined (ACE_HAS_WINCE) ::MessageBox (0, ACE_TEXT ("ACE_Thread::keycreate() failed!"), ACE_TEXT ("ACE_TSS::ACE_TSS"), MB_OK); #else ACE_OS::fprintf (stderr, "ACE_Thread::keycreate() failed!"); #endif /* ACE_HAS_WINCE */ return; } #if defined (ACE_HAS_THR_C_DEST) // Encapsulate a ts_obj and it's destructor in an // ACE_TSS_Adapter. ACE_TSS_Adapter *tss_adapter = 0; ACE_NEW (tss_adapter, ACE_TSS_Adapter ((void *) ts_obj, ACE_TSS<TYPE>::cleanup)); // Put the adapter in thread specific storage if (ACE_Thread::setspecific (this->key_, (void *) tss_adapter) != 0) { delete tss_adapter; ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("ACE_Thread::setspecific() failed!"))); } #else if (ACE_Thread::setspecific (this->key_, (void *) ts_obj) != 0) ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("ACE_Thread::setspecific() failed!"))); #endif /* ACE_HAS_THR_C_DEST */ } }
template <class TYPE> TYPE * ACE_TSS<TYPE>::ts_object (TYPE *new_ts_obj) { // Note, we shouldn't hold the keylock at this point because // <ts_init> does it for us and we'll end up with deadlock // otherwise... if (this->once_ == 0) { // Create and initialize thread-specific ts_obj. if (this->ts_init () == -1) return 0; } // Ensure that we are serialized! ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->keylock_, 0); TYPE *ts_obj = 0; #if defined (ACE_HAS_THR_C_DEST) ACE_TSS_Adapter *tss_adapter = 0; if (ACE_Thread::getspecific (this->key_, (void **) &tss_adapter) == -1) return 0; // This should not happen! if (tss_adapter != 0) { ts_obj = (TYPE *) tss_adapter->ts_obj_; delete tss_adapter; // don't need this anymore } ACE_NEW_RETURN (tss_adapter, ACE_TSS_Adapter ((void *) new_ts_obj, ACE_TSS<TYPE>::cleanup), 0); if (ACE_Thread::setspecific (this->key_, (void *) tss_adapter) == -1) { delete tss_adapter; return ts_obj; // This should not happen! } #else if (ACE_Thread::getspecific (this->key_, (void **) &ts_obj) == -1) return 0; // This should not happen! if (ACE_Thread::setspecific (this->key_, (void *) new_ts_obj) == -1) return ts_obj; // This should not happen! #endif /* ACE_HAS_THR_C_DEST */ return ts_obj; }
template <class TYPE> TYPE * ACE_TSS<TYPE>::ts_object (TYPE *new_ts_obj) { // Note, we shouldn't hold the keylock at this point because // <ts_init> does it for us and we'll end up with deadlock // otherwise... if (!this->once_) { // Create and initialize thread-specific ts_obj. if (this->ts_init () == -1) return 0; } TYPE *ts_obj = 0; #if defined (ACE_HAS_THR_C_DEST) ACE_TSS_Adapter *tss_adapter = 0; void *temp = tss_adapter; // Need this temp to keep G++ from complaining. if (ACE_Thread::getspecific (this->key_, &temp) == -1) return 0; // This should not happen! tss_adapter = static_cast <ACE_TSS_Adapter *> (temp); if (tss_adapter != 0) { ts_obj = static_cast <TYPE *> (tss_adapter->ts_obj_); delete tss_adapter; // don't need this anymore } ACE_NEW_RETURN (tss_adapter, ACE_TSS_Adapter ((void *) new_ts_obj, ACE_TSS<TYPE>::cleanup), 0); if (ACE_Thread::setspecific (this->key_, (void *) tss_adapter) == -1) { delete tss_adapter; return ts_obj; // This should not happen! } #else void *temp = ts_obj; // Need this temp to keep G++ from complaining. if (ACE_Thread::getspecific (this->key_, &temp) == -1) return 0; // This should not happen! ts_obj = static_cast <TYPE *> (temp); if (ACE_Thread::setspecific (this->key_, (void *) new_ts_obj) == -1) return ts_obj; // This should not happen! #endif /* ACE_HAS_THR_C_DEST */ return ts_obj; }
template <class TYPE> TYPE * ACE_TSS<TYPE>::ts_object (TYPE *new_ts_obj) { // Note, we shouldn't hold the keylock at this point because // <ts_init> does it for us and we'll end up with deadlock // otherwise... if (!this->once_) { // Create and initialize thread-specific ts_obj. if (this->ts_init () == -1) return 0; } TYPE *ts_obj = 0; #if defined (ACE_HAS_THR_C_DEST) ACE_TSS_Adapter *tss_adapter = this->ts_value (); if (tss_adapter != 0) { ts_obj = static_cast <TYPE *> (tss_adapter->ts_obj_); // Don't delete tss_adapter yet. It can be double-deleted // in case setspecific below fails. } ACE_TSS_Adapter *new_tss_adapter = 0; ACE_NEW_RETURN (new_tss_adapter, ACE_TSS_Adapter ((void *) new_ts_obj, ACE_TSS<TYPE>::cleanup), 0); if (this->ts_value (new_tss_adapter) == -1) { delete new_tss_adapter; } else { // Now it's fine to delete the old tss_adapter. delete tss_adapter; } #else ts_obj = this->ts_value (); this->ts_value (new_ts_obj); #endif /* ACE_HAS_THR_C_DEST */ return ts_obj; }
ACE_TSS_Read_Guard<ACE_LOCK>::ACE_TSS_Read_Guard (ACE_LOCK &lock, bool block) { this->init_key (); Guard_Type *guard = 0; ACE_NEW (guard, Read_Guard_Type (lock, block)); #if defined (ACE_HAS_THR_C_DEST) ACE_TSS_Adapter *tss_adapter; ACE_NEW (tss_adapter, ACE_TSS_Adapter ((void *)guard, ACE_TSS_Guard<ACE_LOCK>::cleanup)); ACE_Thread::setspecific (this->key_, (void *) tss_adapter); #else ACE_Thread::setspecific (this->key_, (void *) guard); #endif /* ACE_HAS_THR_C_DEST */ }
ACE_TSS_Read_Guard<ACE_LOCK>::ACE_TSS_Read_Guard (ACE_LOCK &lock, int block) { // ACE_TRACE ("ACE_TSS_Read_Guard<ACE_LOCK>::ACE_TSS_Read_Guard"); this->init_key (); ACE_Guard<ACE_LOCK> *guard; ACE_NEW (guard, ACE_Read_Guard<ACE_LOCK> (lock, block)); #if defined (ACE_HAS_THR_C_DEST) ACE_TSS_Adapter *tss_adapter; ACE_NEW (tss_adapter, ACE_TSS_Adapter ((void *)guard, ACE_TSS_Guard<ACE_LOCK>::cleanup)); ACE_Thread::setspecific (this->key_, (void *) tss_adapter); #else ACE_Thread::setspecific (this->key_, (void *) guard); #endif /* ACE_HAS_THR_C_DEST */ }
template <class TYPE> TYPE * ACE_TSS<TYPE>::ts_get (void) const { if (!this->once_) { // Create and initialize thread-specific ts_obj. if (const_cast< ACE_TSS < TYPE > * >(this)->ts_init () == -1) // Seriously wrong.. return 0; } TYPE *ts_obj = 0; #if defined (ACE_HAS_THR_C_DEST) ACE_TSS_Adapter *tss_adapter = this->ts_value (); ACE_TSS_Adapter *fake_tss_adapter = 0; // If tss_adapter is not 0 but its ts_obj_ is 0 then we still need to create // a proper ts_obj. That's the intent of this member function. if (tss_adapter != 0 && tss_adapter->ts_obj_ == 0) { fake_tss_adapter = tss_adapter; tss_adapter = 0; } // Check to see if this is the first time in for this thread. if (tss_adapter == 0) #else ts_obj = this->ts_value (); // Check to see if this is the first time in for this thread. if (ts_obj == 0) #endif /* ACE_HAS_THR_C_DEST */ { // Allocate memory off the heap and store it in a pointer in // thread-specific storage (on the stack...). ts_obj = this->make_TSS_TYPE (); if (ts_obj == 0) return 0; #if defined (ACE_HAS_THR_C_DEST) // Encapsulate a ts_obj and it's destructor in an // ACE_TSS_Adapter. ACE_NEW_RETURN (tss_adapter, ACE_TSS_Adapter (ts_obj, ACE_TSS<TYPE>::cleanup), 0); // Put the adapter in thread specific storage if (this->ts_value (tss_adapter) == -1) { delete tss_adapter; delete ts_obj; return 0; // Major problems, this should *never* happen! } #else // Store the dynamically allocated pointer in thread-specific // storage. if (this->ts_value (ts_obj) == -1) { delete ts_obj; return 0; // Major problems, this should *never* happen! } #endif /* ACE_HAS_THR_C_DEST */ } #if defined (ACE_HAS_THR_C_DEST) // Delete the adapter that didn't actually have a real ts_obj. delete fake_tss_adapter; // Return the underlying ts object. return static_cast <TYPE *> (tss_adapter->ts_obj_); #else return ts_obj; #endif /* ACE_HAS_THR_C_DEST */ }
template <class TYPE> TYPE * ACE_TSS<TYPE>::ts_get (void) const { if (!this->once_) { // Create and initialize thread-specific ts_obj. if (const_cast< ACE_TSS < TYPE > * >(this)->ts_init () == -1) // Seriously wrong.. return 0; } TYPE *ts_obj = 0; #if defined (ACE_HAS_THR_C_DEST) ACE_TSS_Adapter *tss_adapter = 0; // Get the adapter from thread-specific storage void *temp = tss_adapter; // Need this temp to keep G++ from complaining. if (ACE_Thread::getspecific (this->key_, &temp) == -1) return 0; // This should not happen! tss_adapter = static_cast <ACE_TSS_Adapter *> (temp); // Check to see if this is the first time in for this thread. if (tss_adapter == 0) #else // Get the ts_obj from thread-specific storage. Note that no locks // are required here... void *temp = ts_obj; // Need this temp to keep G++ from complaining. if (ACE_Thread::getspecific (this->key_, &temp) == -1) return 0; // This should not happen! ts_obj = static_cast <TYPE *> (temp); // Check to see if this is the first time in for this thread. if (ts_obj == 0) #endif /* ACE_HAS_THR_C_DEST */ { // Allocate memory off the heap and store it in a pointer in // thread-specific storage (on the stack...). ts_obj = this->make_TSS_TYPE (); if (ts_obj == 0) return 0; #if defined (ACE_HAS_THR_C_DEST) // Encapsulate a ts_obj and it's destructor in an // ACE_TSS_Adapter. ACE_NEW_RETURN (tss_adapter, ACE_TSS_Adapter (ts_obj, ACE_TSS<TYPE>::cleanup), 0); // Put the adapter in thread specific storage if (ACE_Thread::setspecific (this->key_, (void *) tss_adapter) != 0) { delete tss_adapter; delete ts_obj; return 0; // Major problems, this should *never* happen! } #else // Store the dynamically allocated pointer in thread-specific // storage. if (ACE_Thread::setspecific (this->key_, (void *) ts_obj) != 0) { delete ts_obj; return 0; // Major problems, this should *never* happen! } #endif /* ACE_HAS_THR_C_DEST */ } #if defined (ACE_HAS_THR_C_DEST) // Return the underlying ts object. return static_cast <TYPE *> (tss_adapter->ts_obj_); #else return ts_obj; #endif /* ACE_HAS_THR_C_DEST */ }