summaryrefslogtreecommitdiff
path: root/ACE/ace/DLL_Manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ace/DLL_Manager.cpp')
-rw-r--r--ACE/ace/DLL_Manager.cpp756
1 files changed, 756 insertions, 0 deletions
diff --git a/ACE/ace/DLL_Manager.cpp b/ACE/ace/DLL_Manager.cpp
new file mode 100644
index 00000000000..b796c4b6e55
--- /dev/null
+++ b/ACE/ace/DLL_Manager.cpp
@@ -0,0 +1,756 @@
+// $Id$
+
+#include "ace/DLL_Manager.h"
+
+#include "ace/Log_Msg.h"
+#include "ace/ACE.h"
+#include "ace/Framework_Component.h"
+
+#include "ace/Lib_Find.h"
+#include "ace/Object_Manager.h"
+#include "ace/SString.h"
+#include "ace/Recursive_Thread_Mutex.h"
+#include "ace/Guard_T.h"
+#include "ace/OS_NS_dlfcn.h"
+#include "ace/OS_NS_string.h"
+
+ACE_RCSID (ace,
+ DLL_Manager,
+ "DLL_Manager.cpp,v 4.23 2003/11/05 23:30:46 shuston Exp")
+
+/******************************************************************/
+
+ ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+sig_atomic_t ACE_DLL_Handle::open_called_ = 0;
+
+ACE_DLL_Handle::ACE_DLL_Handle (void)
+ : refcount_ (0),
+ dll_name_ (0),
+ handle_ (ACE_SHLIB_INVALID_HANDLE)
+{
+ ACE_TRACE ("ACE_DLL_Handle::ACE_DLL_Handle");
+}
+
+ACE_DLL_Handle::~ACE_DLL_Handle (void)
+{
+ ACE_TRACE ("ACE_DLL_Handle::~ACE_DLL_Handle");
+ this->close (1);
+ delete[] this->dll_name_;
+}
+
+const ACE_TCHAR *
+ACE_DLL_Handle::dll_name (void) const
+{
+ ACE_TRACE ("ACE_DLL_Handle::dll_name");
+ return this->dll_name_;
+}
+
+int
+ACE_DLL_Handle::open (const ACE_TCHAR *dll_name,
+ int open_mode,
+ ACE_SHLIB_HANDLE handle)
+{
+ ACE_TRACE ("ACE_DLL_Handle::open");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ if (this->dll_name_)
+ {
+ // Once dll_name_ has been set, it can't be changed..
+ if (ACE_OS::strcmp (this->dll_name_, dll_name) != 0)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("(%P|%t) DLL_Handle::open: error, ")
+ ACE_LIB_TEXT ("tried to reopen %s with name %s\n"),
+ this->dll_name_,
+ dll_name));
+
+ return -1;
+ }
+ }
+ else
+ this->dll_name_ = ACE::strnew (dll_name);
+
+ if (!this->open_called_)
+ this->open_called_ = 1;
+
+ // If it hasn't been loaded yet, go ahead and do that now.
+ if (this->handle_ == ACE_SHLIB_INVALID_HANDLE)
+ {
+ if (handle)
+ this->handle_ = handle;
+ else
+ {
+ /*
+ ** Get the set of names to try loading. We need to do this to
+ ** properly support the ability for a user to specify a simple,
+ ** unadorned name (for example, "ACE") that will work across
+ ** platforms. We apply platform specifics to get a name that will
+ ** work (e.g. libACE, ACEd.dll, ACE.dll, etc.) We rely on the
+ ** underlying dlopen() implementation to "Do The Right Thing" in
+ ** terms of using relative paths, LD_LIBRARY_PATH, system security
+ ** rules, etc. except when ACE_MUST_HELP_DLOPEN_SEARCH_PATH is set.
+ ** If it is set, then ACE::ldfind() scans the configured path
+ ** looking for a match on the name and prefix/suffix applications.
+ ** NOTE: having ACE scan for a file and then pass a fully-qualified
+ ** pathname to dlopen() is a potential security hole; therefore,
+ ** do not use ACE_MUST_HELP_DLOPEN_SEARCH_PATH unless necessary
+ ** and only after considering the risks.
+ */
+ ACE_Array<ACE_TString> dll_names;
+ dll_names.max_size (10); // Decent guess to avoid realloc later
+
+#if defined (ACE_MUST_HELP_DLOPEN_SEARCH_PATH)
+ // Find out where the library is
+ ACE_TCHAR dll_pathname[MAXPATHLEN + 1];
+
+ // Transform the pathname into the appropriate dynamic link library
+ // by searching the ACE_LD_SEARCH_PATH.
+ ACE::ldfind (dll_name,
+ dll_pathname,
+ (sizeof dll_pathname / sizeof (ACE_TCHAR)));
+ ACE_TString dll_str (dll_pathname);
+ dll_names.size (1);
+ dll_names.set (dll_str, 0);
+#else
+ this->get_dll_names (dll_name, dll_names);
+#endif
+
+ ACE_Array_Iterator<ACE_TString> name_iter (dll_names);
+ ACE_TString *name = 0;
+ while (name_iter.next (name))
+ {
+ // The ACE_SHLIB_HANDLE object is obtained.
+ this->handle_ = ACE_OS::dlopen (name->c_str (),
+ open_mode);
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE (%P|%t) DLL_Handle::open ")
+ ACE_LIB_TEXT ("(\"%s\", 0x%x) -> %s: %s\n"),
+ name->c_str (),
+ open_mode,
+ ((this->handle_ != ACE_SHLIB_INVALID_HANDLE)
+ ? ACE_LIB_TEXT ("succeeded")
+ : ACE_LIB_TEXT ("failed")),
+ this->error()->c_str()));
+ }
+
+ if (this->handle_ != ACE_SHLIB_INVALID_HANDLE) // Good one?
+ break;
+
+ // If errno is ENOENT we just skip over this one,
+ // anything else - like an undefined symbol, for
+ // instance must be flagged here or the next error will
+ // mask it.
+ // @TODO: If we've found our DLL _and_ it's
+ // broken, should we continue at all?
+ if ((errno != 0) && (errno != ENOENT) && ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE (%P|%t) DLL_Handle::open ")
+ ACE_LIB_TEXT ("(\'%s\') failed, errno=")
+ ACE_LIB_TEXT ("%d: %s\n"),
+ name->c_str (),
+ errno,
+ this->error ()->c_str ()));
+
+#if defined (AIX)
+ // AIX often puts the shared library file (most often named
+ // shr.o) inside an archive library. If this is an archive
+ // library name, then try appending [shr.o] and retry.
+ if (ACE_TString::npos != name->strstr (ACE_LIB_TEXT (".a")))
+ {
+ ACE_TCHAR aix_pathname[MAXPATHLEN + 1];
+ ACE_OS::strncpy (aix_pathname,
+ name->c_str (),
+ name->length ());
+ aix_pathname[name->length ()] = '\0';
+ ACE_OS::strcat (aix_pathname, ACE_LIB_TEXT ("(shr.o)"));
+ open_mode |= RTLD_MEMBER;
+
+ if (ACE::debug ())
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE (%P|%t) DLL_Handle::open ")
+ ACE_LIB_TEXT ("(\"%s\", 0x%x) -> %s: %s\n"),
+ aix_pathname,
+ open_mode,
+ ACE_LIB_TEXT ((this->handle_ != ACE_SHLIB_INVALID_HANDLE)
+ ? "succeeded"
+ : "failed"),
+ this->error()->c_str()));
+ }
+
+ this->handle_ = ACE_OS::dlopen (aix_pathname, open_mode);
+ if (this->handle_ != ACE_SHLIB_INVALID_HANDLE)
+ break;
+
+ // If errno is ENOENT we just skip over this one, anything
+ // else - like an undefined symbol, for instance
+ // must be flagged here or the next error will mask it.
+ //
+ // @TODO: If we've found our DLL _and_ it's broken,
+ // should we continue at all?
+ if (ACE::debug () && (errno != 0) && (errno != ENOENT))
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE (%P|%t) DLL_Handle::open ")
+ ACE_LIB_TEXT ("(\'%s\') failed, errno=")
+ ACE_LIB_TEXT ("%d: %s\n"),
+ name->c_str (),
+ errno,
+ this->error ()->c_str ()));
+
+ }
+#endif /* AIX */
+
+ name_iter.advance ();
+ }
+
+ if (this->handle_ == ACE_SHLIB_INVALID_HANDLE)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE (%P|%t) DLL_Handle::open (\"%s\"): ")
+ ACE_LIB_TEXT ("Invalid handle error: %s\n"),
+ this->dll_name_,
+ this->error ()->c_str ()));
+
+ return -1;
+ }
+ }
+ }
+
+ ++this->refcount_;
+ return 0;
+}
+
+int
+ACE_DLL_Handle::close (int unload)
+{
+ ACE_TRACE ("ACE_DLL_Handle::close");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ int retval = 0;
+
+ // Since we don't actually unload the dll as soon as the refcount
+ // reaches zero, we need to make sure we don't decrement it below
+ // zero.
+ if (this->refcount_ > 0)
+ --this->refcount_;
+ else
+ this->refcount_ = 0;
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE (%P|%t) DLL_Handle::close: ")
+ ACE_LIB_TEXT ("closing %s (%d), refcount is down to %d\n"),
+ this->dll_name_,
+ this->handle_,
+ this->refcount_));
+
+ if (this->refcount_ == 0 &&
+ this->handle_ != ACE_SHLIB_INVALID_HANDLE &&
+ unload == 1)
+ {
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE (%P|%t) DLL_Handle::close: ")
+ ACE_LIB_TEXT ("Unloading %s (%d)\n"),
+ this->dll_name_,
+ this->handle_));
+
+ // First remove any associated Framework Components.
+ ACE_Framework_Repository * frPtr= ACE_Framework_Repository::instance ();
+
+ if (frPtr)
+ {
+ frPtr->remove_dll_components (this->dll_name_);
+ }
+
+ retval = ACE_OS::dlclose (this->handle_);
+ this->handle_ = ACE_SHLIB_INVALID_HANDLE;
+ }
+
+ if (retval != 0)
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE (%P|%t) DLL_Handle::close: ")
+ ACE_LIB_TEXT ("failed with: \"%s\".\n"),
+ this->error ()->c_str ()));
+
+ return retval;
+}
+
+sig_atomic_t
+ACE_DLL_Handle::refcount (void) const
+{
+ return this->refcount_;
+}
+
+void *
+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));
+
+ ACE_Auto_Array_Ptr <ACE_TCHAR> auto_name (ACE::ldname (sym_name));
+ // handle_ can be invalid especially when ACE_DLL_Handle resigned ownership
+ // BTW. Handle lifecycle management is a little crazy in ACE
+ if (this->handle_ != ACE_SHLIB_INVALID_HANDLE)
+ {
+#if defined (ACE_OPENVMS)
+ void *sym = ACE::ldsymbol (this->handle_, auto_name.get ());
+#else
+ void *sym = ACE_OS::dlsym (this->handle_, auto_name.get ());
+#endif
+
+ // 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 && ignore_errors != 1)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE (%P|%t) DLL_Handle::symbol (\"%s\") ")
+ ACE_LIB_TEXT (" failed with \"%s\".\n"),
+ auto_name.get (),
+ this->error ()->c_str ()));
+
+ return 0;
+ }
+ return sym;
+ }
+ return 0;
+}
+
+ACE_SHLIB_HANDLE
+ACE_DLL_Handle::get_handle (int become_owner)
+{
+ ACE_TRACE ("ACE_DLL_Handle::get_handle");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ ACE_SHLIB_HANDLE handle = ACE_SHLIB_INVALID_HANDLE;
+
+ if (this->refcount_ == 0 && become_owner != 0)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE (%P|%t) DLL_Handle::get_handle: ")
+ ACE_LIB_TEXT ("cannot become owner, refcount == 0.\n")));
+
+ return ACE_SHLIB_INVALID_HANDLE;
+ }
+
+ handle = this->handle_;
+
+ if (become_owner != 0)
+ {
+ if (--this->refcount_ == 0)
+ this->handle_ = ACE_SHLIB_INVALID_HANDLE;
+ }
+
+ if (ACE::debug ())
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_LIB_TEXT ("ACE (%P|%t) ACE_DLL_Handle::get_handle: ")
+ ACE_LIB_TEXT ("post call: handle %s, refcount %d\n"),
+ this->handle_ == ACE_SHLIB_INVALID_HANDLE ?
+ ACE_LIB_TEXT ("invalid") : ACE_LIB_TEXT ("valid"),
+ this->refcount_));
+
+ return handle;
+}
+
+// This method is used return the last error of a library operation.
+
+auto_ptr <ACE_TString>
+ACE_DLL_Handle::error (void)
+{
+ ACE_TRACE ("ACE_DLL_Handle::error");
+ const ACE_TCHAR *error = ACE_OS::dlerror ();
+ auto_ptr<ACE_TString> str
+ (new ACE_TString (error ? error : ACE_LIB_TEXT ("no error")));
+ return str;
+}
+
+void
+ACE_DLL_Handle::get_dll_names (const ACE_TCHAR *dll_name,
+ ACE_Array<ACE_TString> &try_names)
+{
+ // Build the array of DLL names to try on this platform by applying the
+ // proper prefixes and/or suffixes to the specified dll_name.
+ ACE_TString base (dll_name);
+ ACE_TString base_dir, base_file, base_suffix;
+
+ // 1. Separate the dll_name into the dir part and the file part. We
+ // only decorate the file part to determine the names to try loading.
+ ACE_TString::size_type pos = base.rfind (ACE_DIRECTORY_SEPARATOR_CHAR);
+ if (pos != ACE_TString::npos)
+ {
+ base_dir = base.substr (0, pos + 1);
+ base_file = base.substr (pos + 1);
+ }
+ else
+ base_file = base;
+
+ // 2. Locate the file suffix, if there is one. Move the '.' and the
+ // suffix to base_suffix.
+ if ((pos = base_file.rfind (ACE_LIB_TEXT ('.'))) != ACE_TString::npos)
+ {
+ base_suffix = base_file.substr (pos);
+ base_file = base_file.substr (0, pos);
+ }
+
+ // 3. Build the combinations to try for this platform.
+ // Try these combinations:
+ // - name with decorator and platform's suffix appended (if not supplied)
+ // - name with platform's suffix appended (if not supplied)
+ // - name with platform's dll prefix (if it has one) and suffix
+ // - name with platform's dll prefix, decorator, and suffix.
+ // - name as originally given
+ // We first try to find the file using the decorator so that when a
+ // filename with and without decorator is used, we get the file with
+ // the same decorator as the ACE dll has and then as last resort
+ // the one without. For example with msvc, the debug build has a "d"
+ // decorator, but the release build has none and we really want to get
+ // the debug version of the library in a debug application instead
+ // of the release one.
+ // So we need room for 5 entries in try_names.
+ try_names.size (0);
+ if ((try_names.max_size () - try_names.size ()) < 5)
+ try_names.max_size (try_names.max_size () + 5);
+#if defined (ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ ACE_TString decorator (ACE_LD_DECORATOR_STR);
+#endif
+ ACE_TString suffix (ACE_DLL_SUFFIX);
+ ACE_TString prefix (ACE_DLL_PREFIX);
+
+ for (size_t i = 0; i < 5 && try_names.size () < try_names.max_size (); ++i)
+ {
+ ACE_TString try_this;
+ size_t j = try_names.size ();
+ switch (i)
+ {
+ case 0: // Name + decorator + suffix
+ case 1: // Name + suffix
+ case 2: // Prefix + name + decorator + suffix
+ case 3: // Prefix + name + suffix
+ if (
+ base_suffix.length () > 0
+#if !(defined(ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK))
+ || (i == 1 || i == 3) // No decorator desired; skip
+#endif
+ )
+ break;
+ try_this = base_dir;
+ if (i > 1)
+ try_this += prefix;
+ try_this += base_file;
+ if (base_suffix.length () > 0)
+ try_this += base_suffix;
+ else
+ {
+#if defined (ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
+ try_this += decorator;
+#endif
+ try_this += suffix;
+ }
+ break;
+ case 4:
+ try_this = dll_name;
+ break;
+ }
+
+ if (try_this.length ())
+ {
+ try_names.size (j + 1);
+ try_names.set (try_this, j);
+ }
+ }
+ return;
+}
+
+/******************************************************************/
+
+// Pointer to the Singleton instance.
+ACE_DLL_Manager *ACE_DLL_Manager::instance_ = 0;
+
+
+ACE_DLL_Manager *
+ACE_DLL_Manager::instance (int size)
+{
+ ACE_TRACE ("ACE_DLL_Manager::instance");
+
+ if (ACE_DLL_Manager::instance_ == 0)
+ {
+ // Perform Double-Checked Locking Optimization.
+ ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance (), 0));
+ if (ACE_DLL_Manager::instance_ == 0)
+ {
+ ACE_NEW_RETURN (ACE_DLL_Manager::instance_,
+ ACE_DLL_Manager (size),
+ 0);
+ }
+ }
+
+ return ACE_DLL_Manager::instance_;
+}
+
+void
+ACE_DLL_Manager::close_singleton (void)
+{
+ ACE_TRACE ("ACE_DLL_Manager::close_singleton");
+
+ ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
+ *ACE_Static_Object_Lock::instance ()));
+
+ delete ACE_DLL_Manager::instance_;
+ ACE_DLL_Manager::instance_ = 0;
+}
+
+ACE_DLL_Manager::ACE_DLL_Manager (int size)
+ : handle_vector_ (0),
+ current_size_ (0),
+ total_size_ (0),
+ unload_policy_ (ACE_DLL_UNLOAD_POLICY_PER_DLL)
+{
+ ACE_TRACE ("ACE_DLL_Manager::ACE_DLL_Manager");
+
+ if (this->open (size) != 0 && ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_DLL_Manager ctor failed to allocate ")
+ ACE_LIB_TEXT ("handle_vector_.\n")));
+}
+
+ACE_DLL_Manager::~ACE_DLL_Manager (void)
+{
+ ACE_TRACE ("ACE_DLL_Manager::~ACE_DLL_Manager");
+
+ if (this->close () != 0 && ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_DLL_Manager dtor failed to close ")
+ ACE_LIB_TEXT ("properly.\n")));
+}
+
+ACE_DLL_Handle *
+ACE_DLL_Manager::open_dll (const ACE_TCHAR *dll_name,
+ int open_mode,
+ ACE_SHLIB_HANDLE handle)
+{
+ ACE_TRACE ("ACE_DLL_Manager::open_dll");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ ACE_DLL_Handle *temp_handle = 0;
+ ACE_DLL_Handle *dll_handle = this->find_dll (dll_name);
+ if (!dll_handle)
+ {
+ if (this->current_size_ < this->total_size_)
+ {
+ ACE_NEW_RETURN (temp_handle,
+ ACE_DLL_Handle,
+ 0);
+
+ dll_handle = temp_handle;
+ }
+ }
+
+ if (dll_handle)
+ {
+ if (dll_handle->open (dll_name, open_mode, handle) != 0)
+ {
+ // Error while openind dll. Free temp handle
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_DLL_Manager::open_dll: Could not ")
+ ACE_LIB_TEXT ("open dll %s.\n"),
+ dll_name));
+
+ delete temp_handle;
+ return 0;
+ }
+
+ // Add the handle to the vector only if the dll is successfully
+ // opened.
+ if (temp_handle != NULL)
+ {
+ this->handle_vector_[this->current_size_] = dll_handle;
+ this->current_size_++;
+ }
+ }
+
+ return dll_handle;
+}
+
+int
+ACE_DLL_Manager::close_dll (const ACE_TCHAR *dll_name)
+{
+ ACE_TRACE ("ACE_DLL_Manager::close_dll");
+ ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
+
+ ACE_DLL_Handle *handle = this->find_dll (dll_name);
+ if (handle)
+ {
+ return this->unload_dll (handle, 0);
+ }
+
+ return -1;
+}
+
+u_long
+ACE_DLL_Manager::unload_policy (void) const
+{
+ ACE_TRACE ("ACE_DLL_Manager::unload_policy");
+ return this->unload_policy_;
+}
+
+void
+ACE_DLL_Manager::unload_policy (u_long unload_policy)
+{
+ ACE_TRACE ("ACE_DLL_Manager::unload_policy");
+ ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->lock_));
+
+ 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
+ACE_DLL_Manager::open (int size)
+{
+ ACE_TRACE ("ACE_DLL_Manager::open");
+
+ ACE_DLL_Handle **temp = 0;
+
+ ACE_NEW_RETURN (temp,
+ ACE_DLL_Handle *[size],
+ -1);
+
+ this->handle_vector_ = temp;
+ this->total_size_ = size;
+ return 0;
+}
+
+int
+ACE_DLL_Manager::close (void)
+{
+ ACE_TRACE ("ACE_DLL_Manager::close");
+
+ int force_close = 1;
+
+ if (this->handle_vector_ != 0)
+ {
+ // Delete components in reverse order.
+ for (int i = this->current_size_ - 1; i >= 0; i--)
+ {
+ if (this->handle_vector_[i])
+ {
+ ACE_DLL_Handle *s =
+ const_cast<ACE_DLL_Handle *> (this->handle_vector_[i]);
+ this->handle_vector_[i] = 0;
+ this->unload_dll (s, force_close);
+ delete s;
+ }
+ }
+
+ delete [] this->handle_vector_;
+ this->handle_vector_ = 0;
+ this->current_size_ = 0;
+ }
+ return 0;
+}
+
+ACE_DLL_Handle *
+ACE_DLL_Manager::find_dll (const ACE_TCHAR *dll_name) const
+{
+ ACE_TRACE ("ACE_DLL_Manager::find_dll");
+
+ int i;
+ for (i = 0; i < this->current_size_; i++)
+ if (this->handle_vector_[i] &&
+ ACE_OS::strcmp (this->handle_vector_[i]->dll_name (), dll_name) == 0)
+ {
+ return this->handle_vector_[i];
+ }
+
+ return 0;
+}
+
+int
+ACE_DLL_Manager::unload_dll (ACE_DLL_Handle *dll_handle, int force_unload)
+{
+ ACE_TRACE ("ACE_DLL_Manager::unload_dll");
+
+ if (dll_handle)
+ {
+ int unload = force_unload;
+ if (unload == 0)
+ {
+ // apply strategy
+ if (ACE_BIT_DISABLED (this->unload_policy_,
+ ACE_DLL_UNLOAD_POLICY_PER_DLL))
+ {
+ unload = ACE_BIT_DISABLED (this->unload_policy_,
+ ACE_DLL_UNLOAD_POLICY_LAZY);
+ }
+ else
+ {
+ // Declare the type of the symbol:
+ typedef int (*dll_unload_policy)(void);
+ dll_unload_policy the_policy = 0;
+ void *unload_policy_ptr =
+ dll_handle->symbol (ACE_LIB_TEXT ("_get_dll_unload_policy"), 1);
+ ptrdiff_t temp_p =
+ reinterpret_cast<ptrdiff_t> (unload_policy_ptr);
+ the_policy =
+ reinterpret_cast<dll_unload_policy> (temp_p);
+ 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 (unload) != 0)
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_DLL_Manager::unload error.\n")));
+
+ return -1;
+ }
+ }
+ else
+ {
+ if (ACE::debug ())
+ ACE_ERROR ((LM_ERROR,
+ ACE_LIB_TEXT ("ACE_DLL_Manager::unload_dll called with ")
+ ACE_LIB_TEXT ("null pointer.\n")));
+
+ return -1;
+ }
+
+ return 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL