diff options
author | dhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2002-05-30 10:47:05 +0000 |
---|---|---|
committer | dhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2002-05-30 10:47:05 +0000 |
commit | 2a5a195b5826c4ed2c6cb1636e4c78c634b4219f (patch) | |
tree | 1f845e1609c2abbfda6b4736f321e8f6ff67919c | |
parent | b8644c0563e107d57a57896a1561dc2df965c55d (diff) | |
download | ATCD-2a5a195b5826c4ed2c6cb1636e4c78c634b4219f.tar.gz |
ChangeLogTag:Thu May 30 10:18:27 UTC 2002 Don Hinton <dhinton@ieee.org>
-rw-r--r-- | ChangeLog | 38 | ||||
-rw-r--r-- | ChangeLogs/ChangeLog-02a | 38 | ||||
-rw-r--r-- | ChangeLogs/ChangeLog-03a | 38 | ||||
-rw-r--r-- | ace/DLL.cpp | 4 | ||||
-rw-r--r-- | ace/DLL.h | 7 | ||||
-rw-r--r-- | ace/DLL_Manager.cpp | 88 | ||||
-rw-r--r-- | ace/DLL_Manager.h | 34 | ||||
-rw-r--r-- | ace/config-all.h | 26 | ||||
-rw-r--r-- | tests/Framework_Component_DLL.cpp | 4 | ||||
-rw-r--r-- | tests/Framework_Component_Test.cpp | 19 |
10 files changed, 228 insertions, 68 deletions
diff --git a/ChangeLog b/ChangeLog index 72ee83e5de2..af1adb7e100 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,41 @@ +Thu May 30 10:18:27 UTC 2002 Don Hinton <dhinton@ieee.org> + + * tests/Framework_Component_Test.cpp: + + Modified test to use the new macro definitions and method names. + + * tests/Framework_Component_DLL.cpp: + + Added ACE_DLL_UNLOAD_POLICY declaration specifying LAZY unloading. + Changed an errant ACE_LIB_TEXT macro to ACE_TEXT. + + * ace/config-all.h: + + Added the dll unloading policies mentioned below as well as an + ACE_DLL_UNLOAD_POLICY macro dlls can use to set/export their own + policy. If no policy is exported, the current per-process policy + is used. + + * ace/DLL_Manager.{h,cpp}: + + Renamed unload_strategy to unload_policy and moved the policy + definitions to config-all.h so that they can be used without + including DLL_Manager.h (which includes OS.h, etc...). + + Refactored the unloading policies and implemented the per-dll + case by probing the dll for a "_get_dll_unload_policy" function + that returns the dll specific policy--if the dll chose to + implement it. + + Added missing template instantiations. + + * ace/DLL.{h,cpp} (symbol): + * ace/DLL_Manager.{h,cpp} (symbol): + + Added additional default parameter, ignore_errors, so the dll + can be probed for symbols without sending error messages to + the log. + Thu May 30 08:53:12 2002 Johnny Willemsen <jwillemsen@remedy.nl> * tests/Codecs_Test.cpp: diff --git a/ChangeLogs/ChangeLog-02a b/ChangeLogs/ChangeLog-02a index 72ee83e5de2..af1adb7e100 100644 --- a/ChangeLogs/ChangeLog-02a +++ b/ChangeLogs/ChangeLog-02a @@ -1,3 +1,41 @@ +Thu May 30 10:18:27 UTC 2002 Don Hinton <dhinton@ieee.org> + + * tests/Framework_Component_Test.cpp: + + Modified test to use the new macro definitions and method names. + + * tests/Framework_Component_DLL.cpp: + + Added ACE_DLL_UNLOAD_POLICY declaration specifying LAZY unloading. + Changed an errant ACE_LIB_TEXT macro to ACE_TEXT. + + * ace/config-all.h: + + Added the dll unloading policies mentioned below as well as an + ACE_DLL_UNLOAD_POLICY macro dlls can use to set/export their own + policy. If no policy is exported, the current per-process policy + is used. + + * ace/DLL_Manager.{h,cpp}: + + Renamed unload_strategy to unload_policy and moved the policy + definitions to config-all.h so that they can be used without + including DLL_Manager.h (which includes OS.h, etc...). + + Refactored the unloading policies and implemented the per-dll + case by probing the dll for a "_get_dll_unload_policy" function + that returns the dll specific policy--if the dll chose to + implement it. + + Added missing template instantiations. + + * ace/DLL.{h,cpp} (symbol): + * ace/DLL_Manager.{h,cpp} (symbol): + + Added additional default parameter, ignore_errors, so the dll + can be probed for symbols without sending error messages to + the log. + Thu May 30 08:53:12 2002 Johnny Willemsen <jwillemsen@remedy.nl> * tests/Codecs_Test.cpp: diff --git a/ChangeLogs/ChangeLog-03a b/ChangeLogs/ChangeLog-03a index 72ee83e5de2..af1adb7e100 100644 --- a/ChangeLogs/ChangeLog-03a +++ b/ChangeLogs/ChangeLog-03a @@ -1,3 +1,41 @@ +Thu May 30 10:18:27 UTC 2002 Don Hinton <dhinton@ieee.org> + + * tests/Framework_Component_Test.cpp: + + Modified test to use the new macro definitions and method names. + + * tests/Framework_Component_DLL.cpp: + + Added ACE_DLL_UNLOAD_POLICY declaration specifying LAZY unloading. + Changed an errant ACE_LIB_TEXT macro to ACE_TEXT. + + * ace/config-all.h: + + Added the dll unloading policies mentioned below as well as an + ACE_DLL_UNLOAD_POLICY macro dlls can use to set/export their own + policy. If no policy is exported, the current per-process policy + is used. + + * ace/DLL_Manager.{h,cpp}: + + Renamed unload_strategy to unload_policy and moved the policy + definitions to config-all.h so that they can be used without + including DLL_Manager.h (which includes OS.h, etc...). + + Refactored the unloading policies and implemented the per-dll + case by probing the dll for a "_get_dll_unload_policy" function + that returns the dll specific policy--if the dll chose to + implement it. + + Added missing template instantiations. + + * ace/DLL.{h,cpp} (symbol): + * ace/DLL_Manager.{h,cpp} (symbol): + + Added additional default parameter, ignore_errors, so the dll + can be probed for symbols without sending error messages to + the log. + Thu May 30 08:53:12 2002 Johnny Willemsen <jwillemsen@remedy.nl> * tests/Codecs_Test.cpp: diff --git a/ace/DLL.cpp b/ace/DLL.cpp index 70ca3a15854..8ebc8b9d336 100644 --- a/ace/DLL.cpp +++ b/ace/DLL.cpp @@ -132,13 +132,13 @@ ACE_DLL::open_i (const ACE_TCHAR *dll_filename, // The symbol refernce of the name specified is obtained. void * -ACE_DLL::symbol (const ACE_TCHAR *sym_name) +ACE_DLL::symbol (const ACE_TCHAR *sym_name, int ignore_errors) { ACE_TRACE ("ACE_DLL::symbol"); this->error_ = 0; - void *sym = this->dll_handle_->symbol (sym_name); + void *sym = this->dll_handle_->symbol (sym_name, ignore_errors); if (!sym) this->error_ = 1; diff --git a/ace/DLL.h b/ace/DLL.h index 77db56e6f88..8d9c49ca30a 100644 --- a/ace/DLL.h +++ b/ace/DLL.h @@ -85,8 +85,11 @@ public: ~ACE_DLL (void); /// If <symbol_name> is in the symbol table of the DLL a pointer to - /// the <symbol_name> is returned. Otherwise, returns 0. - void *symbol (const ACE_TCHAR *symbol_name); + /// the <symbol_name> is returned. Otherwise, returns 0. Setting + /// ignore_errors = 1 allows you to probe a dll without generating + /// error messages in the log. Handy for determining the capabilities + /// of a library. + void *symbol (const ACE_TCHAR *symbol_name, int ignore_errors = 0); /// Returns a pointer to a string explaining that an error occured. You /// will need to consult the error log for the actual error string diff --git a/ace/DLL_Manager.cpp b/ace/DLL_Manager.cpp index d8dcfe56fdf..68fe3488f87 100644 --- a/ace/DLL_Manager.cpp +++ b/ace/DLL_Manager.cpp @@ -161,7 +161,7 @@ ACE_DLL_Handle::refcount (void) const } void * -ACE_DLL_Handle::symbol (const ACE_TCHAR *sym_name) +ACE_DLL_Handle::symbol (const ACE_TCHAR *sym_name, int ignore_errors) { ACE_TRACE ("ACE_DLL_Handle::symbol"); ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); @@ -173,7 +173,7 @@ ACE_DLL_Handle::symbol (const ACE_TCHAR *sym_name) // Linux says that the symbol could be null and that it isn't an error. // So you should check the error message also, but since null symbols // won't do us much good anyway, let's still report an error. - if (!sym) + if (!sym && ignore_errors != 1) ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("ACE_DLL_Handle::symbol (\"%s\") \"%s\"."), auto_name.get (), this->error ()->c_str ()), @@ -205,7 +205,8 @@ ACE_DLL_Handle::get_handle (int become_owner) ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE_DLL_Handle::get_handle: ") ACE_LIB_TEXT ("handle %s, refcount %d\n"), - this->handle_ == ACE_SHLIB_INVALID_HANDLE ? "invalid" : "valid", + this->handle_ == ACE_SHLIB_INVALID_HANDLE ? + ACE_LIB_TEXT ("invalid") : ACE_LIB_TEXT ("valid"), this->refcount_)); return handle; @@ -228,7 +229,7 @@ ACE_DLL_Manager_Ex::ACE_DLL_Manager_Ex (int size) : handle_vector_ (0), current_size_ (0), total_size_ (0), - unload_strategy_ (0) + unload_policy_ (ACE_DLL_UNLOAD_POLICY_PER_DLL) { ACE_TRACE ("ACE_DLL_Manager_Ex::ACE_DLL_Manager_Ex"); @@ -301,34 +302,38 @@ ACE_DLL_Manager_Ex::close_dll (const ACE_TCHAR *dll_name) } u_long -ACE_DLL_Manager_Ex::unload_strategy (void) const +ACE_DLL_Manager_Ex::unload_policy (void) const { ACE_TRACE ("ACE_DLL_Manager_Ex::unload_strategy"); - return this->unload_strategy_; + return this->unload_policy_; } void -ACE_DLL_Manager_Ex::unload_strategy (u_long unload_strategy) +ACE_DLL_Manager_Ex::unload_policy (u_long unload_policy) { ACE_TRACE ("ACE_DLL_Manager_Ex::unload_strategy"); ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->lock_)); - u_long old_strategy = this->unload_strategy_; - this->unload_strategy_ = unload_strategy; - - // If going from LAZY to EAGER, inform all the ACE_DLL_Handle - // objects with - if (this->handle_vector_ && - ACE_BIT_ENABLED (old_strategy, LAZY) && - ACE_BIT_DISABLED (unload_strategy, LAZY)) - { - for (int i = this->current_size_ - 1; i >= 0; i--) - { - if (this->handle_vector_[i] && - this->handle_vector_[i]->refcount () == 0) - this->handle_vector_[i]->close (1); - } - } + u_long old_policy = this->unload_policy_; + this->unload_policy_ = unload_policy; + + // If going from LAZY to EAGER or from PER_DLL to PER_PROCESS|EAGER, + // call close(1) on all the ACE_DLL_Handle objects with refcount == 0 + // which will force those that are still loaded to be unloaded. + if (this->handle_vector_) + if (( ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_LAZY) && + ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) ) || + ( ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) && + ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_PER_DLL) && + ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_PER_DLL) )) + { + for (int i = this->current_size_ - 1; i >= 0; i--) + { + if (this->handle_vector_[i] && + this->handle_vector_[i]->refcount () == 0) + this->handle_vector_[i]->close (1); + } + } } int @@ -393,28 +398,43 @@ ACE_DLL_Manager_Ex::find_dll (const ACE_TCHAR *dll_name) const } int -ACE_DLL_Manager_Ex::unload_dll (ACE_DLL_Handle *dll_handle, int force_close) +ACE_DLL_Manager_Ex::unload_dll (ACE_DLL_Handle *dll_handle, int force_unload) { ACE_TRACE ("ACE_DLL_Manager_Ex::unload_dll"); if (dll_handle) { - int close = force_close; - if (close == 0) + int unload = force_unload; + if (unload == 0) { // apply strategy - if (ACE_BIT_DISABLED (this->unload_strategy_, PER_DLL)) + if (ACE_BIT_DISABLED (this->unload_policy_, + ACE_DLL_UNLOAD_POLICY_PER_DLL)) { - close = ACE_BIT_DISABLED (this->unload_strategy_, LAZY); + unload = ACE_BIT_DISABLED (this->unload_policy_, + ACE_DLL_UNLOAD_POLICY_LAZY); } else { - // need to get it from the dll, so just dummy it up for now - close = ACE_BIT_DISABLED (this->unload_strategy_, LAZY); + // Declare the type of the symbol: + typedef int (*dll_unload_policy)(void); + + // Try to get the symbol, and have symbol() ignore errors. + void *foo = dll_handle->symbol (ACE_TEXT ("_get_dll_unload_policy"), 1); + + // Cast the void* to long first. + long tmp = ACE_reinterpret_cast (long, foo); + dll_unload_policy the_policy = ACE_reinterpret_cast (dll_unload_policy, tmp); + if (the_policy != 0) + unload = ACE_BIT_DISABLED (the_policy (), + ACE_DLL_UNLOAD_POLICY_LAZY); + else + unload = ACE_BIT_DISABLED (this->unload_policy_, + ACE_DLL_UNLOAD_POLICY_LAZY); } } - if (dll_handle->close (close) != 0) + if (dll_handle->close (unload) != 0) ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("ACE_DLL_Manager_Ex::unload error.\n")), -1); @@ -427,3 +447,9 @@ ACE_DLL_Manager_Ex::unload_dll (ACE_DLL_Handle *dll_handle, int force_close) return 0; } + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class ACE_Singleton< ACE_DLL_Manager_Ex, ACE_SYNCH_MUTEX >; +#elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#pragma instantiate ACE_Singleton< ACE_DLL_Manager_Ex, ACE_SYNCH_MUTEX > +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/ace/DLL_Manager.h b/ace/DLL_Manager.h index b8d1ab5f13f..e184c423c43 100644 --- a/ace/DLL_Manager.h +++ b/ace/DLL_Manager.h @@ -84,8 +84,11 @@ public: sig_atomic_t refcount (void) const; /// If <symbol_name> is in the symbol table of the DLL a pointer to - /// the <symbol_name> is returned. Otherwise, returns 0. - void *symbol (const ACE_TCHAR *symbol_name); + /// the <symbol_name> is returned. Otherwise, returns 0. Set the + /// ignore_errors flag to supress logging errors if symbol_name isn't + /// found. This is nice if you just want to probe a dll to see what's + /// available, since missing functions in that case aren't really errors. + void *symbol (const ACE_TCHAR *symbol_name, int ignore_errors = 0); /** * Return the handle to the caller. If <become_owner> is non-0 then @@ -145,21 +148,6 @@ public: DEFAULT_SIZE = ACE_DEFAULT_DLL_MANAGER_SIZE }; - enum UNLOAD_STRATEGY - { - /// The default strategy is to use a per-process strategy - /// and unload dlls eagerly, i.e., as soon as the refcount - /// reaches zero. - DEFAULT = 0, - /// Use strategies on a per-dll basis. If dll doesn't - /// define a strategy, use the default one. - PER_DLL = 1, - - /// Apply the unload_strategy hook method to decide when to - /// unload the dll, defaults to program exit. - LAZY = PER_DLL << 1 - }; - /// Default constructor. ACE_DLL_Manager_Ex (int size = ACE_DLL_Manager_Ex::DEFAULT_SIZE); @@ -175,13 +163,13 @@ public: /// Close the underlying dll. Decrements the refcount. int close_dll (const ACE_TCHAR *dll_name); - /// Returns the current UNLOAD_STRATEGY. - u_long unload_strategy (void) const; + /// Returns the current per-process UNLOAD_POLICY. + u_long unload_policy (void) const; - /// Set the UNLOAD_STRATEGY. If the strategy is changed for + /// Set the per-process UNLOAD_POLICY. If the policy is changed from /// LAZY to EAGER, then it will also unload any dlls with zero /// refcounts. - void unload_strategy (u_long unload_strategy = 0); + void unload_policy (u_long unload_policy); protected: // Allocate handle_vector_. @@ -194,7 +182,7 @@ protected: ACE_DLL_Handle *find_dll (const ACE_TCHAR *dll_name) const; // Applies strategy for unloading dll. - int unload_dll (ACE_DLL_Handle *dll_handle, int force_close = 0); + int unload_dll (ACE_DLL_Handle *dll_handle, int force_unload = 0); private: @@ -208,7 +196,7 @@ private: int total_size_; /// Unload strategy. - u_long unload_strategy_; + u_long unload_policy_; #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) /// Synchronization variable for the MT_SAFE Repository diff --git a/ace/config-all.h b/ace/config-all.h index 94082ac193d..b4170f4fc7c 100644 --- a/ace/config-all.h +++ b/ace/config-all.h @@ -635,6 +635,32 @@ typedef void *(*ACE_THR_C_FUNC)(void *); #endif /* ACE_HAS_PACE */ // ============================================================================ +// Macros for controlling the lifetimes of dlls loaded by ACE_DLL--including +// all dlls loaded via the ACE Service Config framework. +// +// Please don't change these values or add new ones wantonly, since we use +// the ACE_BIT_ENABLED, etc..., macros to test them. +// ============================================================================ + +// Per-process policy that unloads dlls eagerly. +#define ACE_DLL_UNLOAD_POLICY_PER_PROCESS 0 +// Apply policy on a per-dll basis. If the dll doesn't use one of the macros +// below, the current per-process policy will be used. +#define ACE_DLL_UNLOAD_POLICY_PER_DLL 1 +// Don't unload dll when refcount reaches zero, i.e., wait for either an +// explicit unload request or program exit. +#define ACE_DLL_UNLOAD_POLICY_LAZY 2 +// Default policy allows dlls to control their own destinies, but will +// unload those that don't make a choice eagerly. +#define ACE_DLL_UNLOAD_POLICY_DEFAULT ACE_DLL_UNLOAD_POLICY_PER_DLL + +// Add this macro you one of your cpp file in your dll. X should +// be either ACE_DLL_UNLOAD_POLICY_DEFAULT or ACE_DLL_UNLOAD_POLICY_LAZY. +#define ACE_DLL_UNLOAD_POLICY(CLS,X) \ +extern "C" u_long CLS##_Export _get_dll_unload_policy (void) \ + { return X;} + +// ============================================================================ // ACE_USES_CLASSIC_SVC_CONF macro // ============================================================================ diff --git a/tests/Framework_Component_DLL.cpp b/tests/Framework_Component_DLL.cpp index 533b9dbea05..c658c02b9e8 100644 --- a/tests/Framework_Component_DLL.cpp +++ b/tests/Framework_Component_DLL.cpp @@ -7,6 +7,8 @@ ACE_RCSID (tests, Framework_Component_DLL, "$Id$") +ACE_DLL_UNLOAD_POLICY (Framework_Component_DLL, ACE_DLL_UNLOAD_POLICY_LAZY) + Simple_Service::Simple_Service (void) { FRAMEWORK_COMPONENT_DLL_TRACE ("Simple_Service::Simple_Service"); @@ -41,7 +43,7 @@ public: FWCT_DLL_Singleton_Adapter_T <Simple_Service> *ss = SS_SINGLETON::instance (); ACE_DEBUG ((LM_DEBUG, - ACE_LIB_TEXT ("Server_T::init() dll_name: %s\n"), + ACE_TEXT ("Server_T::init() dll_name: %s\n"), ss->dll_name ())); return 0; } diff --git a/tests/Framework_Component_Test.cpp b/tests/Framework_Component_Test.cpp index 0f452176b69..61d8ca77f7d 100644 --- a/tests/Framework_Component_Test.cpp +++ b/tests/Framework_Component_Test.cpp @@ -46,7 +46,8 @@ ACE_RCSID(tests, Framework_Component_Test, "$Id$") ACE_TEXT ("path='Framework_Component_DLL' params=''/> </dynamic>") # define REMOVE_SERVICE(X) \ - ACE_TEXT ( "<?xml version='1.0'?> <remove id='Server_") ACE_TEXT(#X) ACE_TEXT("'> </remove>") + ACE_TEXT ( "<?xml version='1.0'?> <remove id='Server_") ACE_TEXT(#X) \ + ACE_TEXT("'> </remove>") #endif /* ACE_USES_CLASSIC_SVC_CONF */ @@ -54,12 +55,12 @@ int run_test (u_long unload_mask = 0) { ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Running test with mask = %s|%s\n"), - ACE_BIT_ENABLED(unload_mask, ACE_DLL_Manager_Ex::PER_DLL) == 0 + ACE_BIT_ENABLED(unload_mask, ACE_DLL_UNLOAD_POLICY_PER_DLL) == 0 ? ACE_TEXT ("PER_PROCESS") : ACE_TEXT ("PER_DLL"), - ACE_BIT_ENABLED(unload_mask, ACE_DLL_Manager_Ex::LAZY) == 0 + ACE_BIT_ENABLED(unload_mask, ACE_DLL_UNLOAD_POLICY_LAZY) == 0 ? ACE_TEXT ("EAGER") : ACE_TEXT ("LAZY"))); - ACE_DLL_Manager::instance ()->unload_strategy (unload_mask); + ACE_DLL_Manager::instance ()->unload_policy (unload_mask); // Now, let the ACE Service Configurator framework load our service from a // dll, which contains a singleton. @@ -90,7 +91,7 @@ run_test (u_long unload_mask = 0) ACE_Service_Config::process_directive (REMOVE_SERVICE(2)); // Force unloading so we'll be ready for the next test. - ACE_DLL_Manager::instance ()->unload_strategy (ACE_DLL_Manager_Ex::DEFAULT); + ACE_DLL_Manager::instance ()->unload_policy (ACE_DLL_UNLOAD_POLICY_DEFAULT); ACE_Service_Config::close (); return 0; @@ -104,16 +105,16 @@ ACE_TMAIN (int, ACE_TCHAR *[]) int retval = 0; // Use defaults, i.e., per process, eager unloading. - retval += run_test (); + retval += run_test (ACE_DLL_UNLOAD_POLICY_DEFAULT); // Per process, lazy unloading - retval += run_test (ACE_DLL_Manager_Ex::LAZY); + retval += run_test (ACE_DLL_UNLOAD_POLICY_LAZY); // Per dll, eager unloading - retval += run_test (ACE_DLL_Manager_Ex::PER_DLL); + retval += run_test (ACE_DLL_UNLOAD_POLICY_PER_DLL); // Per dll, lazy unloading. - retval += run_test (ACE_DLL_Manager_Ex::PER_DLL | ACE_DLL_Manager_Ex::LAZY); + retval += run_test (ACE_DLL_UNLOAD_POLICY_PER_DLL | ACE_DLL_UNLOAD_POLICY_LAZY); ACE_END_TEST; return retval == 0 ? 0 : -1; |