// $Id$ #include "ace/Cleanup.h" ACE_RCSID (ace, Cleanup, "$Id$") #if !defined (ACE_HAS_INLINED_OSCALLS) # include "ace/Cleanup.inl" #endif /* ACE_HAS_INLINED_OSCALLS */ #include "ace/OS_Memory.h" ACE_BEGIN_VERSIONED_NAMESPACE_DECL void ACE_Cleanup::cleanup (void *) { delete this; } ACE_Cleanup::~ACE_Cleanup (void) { } /*****************************************************************************/ extern "C" void ACE_CLEANUP_DESTROYER_NAME (ACE_Cleanup *object, void *param) { object->cleanup (param); } /*****************************************************************************/ ACE_Cleanup_Info::ACE_Cleanup_Info (void) : object_ (0), cleanup_hook_ (0), param_ (0) { } bool ACE_Cleanup_Info::operator== (const ACE_Cleanup_Info &o) const { return o.object_ == this->object_ && o.cleanup_hook_ == this->cleanup_hook_ && o.param_ == this->param_; } bool ACE_Cleanup_Info::operator!= (const ACE_Cleanup_Info &o) const { return !(*this == o); } /*****************************************************************************/ /** * @class ACE_Cleanup_Info_Node * * @brief For maintaining a list of ACE_Cleanup_Info items. * * For internal use by ACE_Object_Manager. */ class ACE_Cleanup_Info_Node { public: ACE_Cleanup_Info_Node (void); ACE_Cleanup_Info_Node (const ACE_Cleanup_Info &new_info, ACE_Cleanup_Info_Node *next); ~ACE_Cleanup_Info_Node (void); ACE_Cleanup_Info_Node *insert (const ACE_Cleanup_Info &); private: ACE_Cleanup_Info cleanup_info_; ACE_Cleanup_Info_Node *next_; friend class ACE_OS_Exit_Info; }; ACE_Cleanup_Info_Node::ACE_Cleanup_Info_Node (void) : cleanup_info_ (), next_ (0) { } ACE_Cleanup_Info_Node::ACE_Cleanup_Info_Node (const ACE_Cleanup_Info &new_info, ACE_Cleanup_Info_Node *next) : cleanup_info_ (new_info), next_ (next) { } ACE_Cleanup_Info_Node::~ACE_Cleanup_Info_Node (void) { delete next_; } ACE_Cleanup_Info_Node * ACE_Cleanup_Info_Node::insert (const ACE_Cleanup_Info &new_info) { ACE_Cleanup_Info_Node *new_node = 0; ACE_NEW_RETURN (new_node, ACE_Cleanup_Info_Node (new_info, this), 0); return new_node; } /*****************************************************************************/ ACE_OS_Exit_Info::ACE_OS_Exit_Info (void) { ACE_NEW (registered_objects_, ACE_Cleanup_Info_Node); } ACE_OS_Exit_Info::~ACE_OS_Exit_Info (void) { delete registered_objects_; registered_objects_ = 0; } int ACE_OS_Exit_Info::at_exit_i (void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param) { ACE_Cleanup_Info new_info; new_info.object_ = object; new_info.cleanup_hook_ = cleanup_hook; new_info.param_ = param; // Return -1 and sets errno if unable to allocate storage. Enqueue // at the head and dequeue from the head to get LIFO ordering. ACE_Cleanup_Info_Node *new_node = 0; if ((new_node = registered_objects_->insert (new_info)) == 0) return -1; else { registered_objects_ = new_node; return 0; } } int ACE_OS_Exit_Info::find (void *object) { // Check for already in queue, and return 1 if so. for (ACE_Cleanup_Info_Node *iter = registered_objects_; iter && iter->next_ != 0; iter = iter->next_) { if (iter->cleanup_info_.object_ == object) { // The object has already been registered. return 1; } } return 0; } void ACE_OS_Exit_Info::call_hooks (void) { // Call all registered cleanup hooks, in reverse order of // registration. for (ACE_Cleanup_Info_Node *iter = registered_objects_; iter && iter->next_ != 0; iter = iter->next_) { ACE_Cleanup_Info &info = iter->cleanup_info_; if (info.cleanup_hook_ == reinterpret_cast ( ACE_CLEANUP_DESTROYER_NAME)) // The object is an ACE_Cleanup. ACE_CLEANUP_DESTROYER_NAME ( reinterpret_cast (info.object_), info.param_); else if (info.object_ == &ace_exit_hook_marker) // The hook is an ACE_EXIT_HOOK. (* reinterpret_cast (info.cleanup_hook_)) (); else (*info.cleanup_hook_) (info.object_, info.param_); } } ACE_END_VERSIONED_NAMESPACE_DECL