GitHub Actions: Try MSVC builds with /std:c++17 and 20
[ACE_TAO.git] / ACE / ace / DLL_Manager.cpp
blob39aa918d2fbc76d8c9c1b4e5766f5b8f3f7b56d5
1 #include "ace/DLL_Manager.h"
3 #include "ace/Auto_Ptr.h"
4 #include "ace/Log_Category.h"
5 #include "ace/ACE.h"
6 #include "ace/Framework_Component.h"
8 #include "ace/Lib_Find.h"
9 #include "ace/Object_Manager.h"
10 #include "ace/SString.h"
11 #include "ace/Recursive_Thread_Mutex.h"
12 #include "ace/Guard_T.h"
13 #include "ace/OS_NS_dlfcn.h"
14 #include "ace/OS_NS_string.h"
16 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
18 sig_atomic_t ACE_DLL_Handle::open_called_ = 0;
20 ACE_DLL_Handle::ACE_DLL_Handle (void)
21 : refcount_ (0),
22 dll_name_ (0),
23 handle_ (ACE_SHLIB_INVALID_HANDLE)
25 ACE_TRACE ("ACE_DLL_Handle::ACE_DLL_Handle");
28 ACE_DLL_Handle::~ACE_DLL_Handle (void)
30 ACE_TRACE ("ACE_DLL_Handle::~ACE_DLL_Handle");
31 this->close (1);
32 #if defined (ACE_HAS_ALLOC_HOOKS)
33 ACE_Allocator::instance()->free(this->dll_name_);
34 #else
35 delete[] this->dll_name_;
36 #endif /* ACE_HAS_ALLOC_HOOKS */
39 ACE_ALLOC_HOOK_DEFINE(ACE_DLL_Handle)
41 const ACE_TCHAR *
42 ACE_DLL_Handle::dll_name (void) const
44 ACE_TRACE ("ACE_DLL_Handle::dll_name");
45 return this->dll_name_;
48 int
49 ACE_DLL_Handle::open (const ACE_TCHAR *dll_name,
50 int open_mode,
51 ACE_SHLIB_HANDLE handle,
52 ERROR_STACK *errors)
54 ACE_TRACE ("ACE_DLL_Handle::open");
55 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
57 if (this->dll_name_)
59 // Once dll_name_ has been set, it can't be changed..
60 if (ACE_OS::strcmp (this->dll_name_, dll_name) != 0)
62 if (ACE::debug ())
63 ACELIB_ERROR ((LM_ERROR,
64 ACE_TEXT ("ACE (%P|%t) DLL_Handle::open: error, ")
65 ACE_TEXT ("tried to reopen <%s> with name <%s>\n"),
66 this->dll_name_,
67 dll_name));
69 return -1;
72 else
73 this->dll_name_ = ACE::strnew (dll_name);
75 if (!this->open_called_)
76 this->open_called_ = 1;
78 // If it hasn't been loaded yet, go ahead and do that now.
79 if (this->handle_ == ACE_SHLIB_INVALID_HANDLE)
81 if (handle)
82 this->handle_ = handle;
83 else
86 ** Get the set of names to try loading. We need to do this to
87 ** properly support the ability for a user to specify a simple,
88 ** unadorned name (for example, "ACE") that will work across
89 ** platforms. We apply platform specifics to get a name that will
90 ** work (e.g. libACE, ACEd.dll, ACE.dll, etc.) We rely on the
91 ** underlying dlopen() implementation to "Do The Right Thing" in
92 ** terms of using relative paths, LD_LIBRARY_PATH, system security
93 ** rules, etc. except when ACE_MUST_HELP_DLOPEN_SEARCH_PATH is set.
94 ** If it is set, then ACE::ldfind() scans the configured path
95 ** looking for a match on the name and prefix/suffix applications.
96 ** NOTE: having ACE scan for a file and then pass a fully-qualified
97 ** pathname to dlopen() is a potential security hole; therefore,
98 ** do not use ACE_MUST_HELP_DLOPEN_SEARCH_PATH unless necessary
99 ** and only after considering the risks.
101 ACE_Array<ACE_TString> dll_names;
102 dll_names.max_size (10); // Decent guess to avoid realloc later
104 #if defined (ACE_MUST_HELP_DLOPEN_SEARCH_PATH)
105 // Find out where the library is
106 ACE_TCHAR dll_pathname[MAXPATHLEN + 1];
108 // Transform the pathname into the appropriate dynamic link library
109 // by searching the ACE_LD_SEARCH_PATH.
110 ACE::ldfind (dll_name,
111 dll_pathname,
112 (sizeof dll_pathname / sizeof (ACE_TCHAR)));
113 ACE_TString dll_str (dll_pathname);
114 dll_names.size (1);
115 dll_names.set (dll_str, 0);
116 #else
117 this->get_dll_names (dll_name, dll_names);
118 #endif
120 ACE_TString *name = 0;
121 for (ACE_Array_Iterator<ACE_TString> name_iter (dll_names);
122 name_iter.next (name); name_iter.advance ())
124 if (this->open_i (name->c_str (), open_mode, errors))
125 break;
127 #if defined (AIX)
128 # define SHR_O ACE_TEXT("(shr.o)")
129 # define SHR_O_LEN (sizeof (SHR_O) / sizeof(ACE_TCHAR) - 1)
130 // AIX often puts the shared library file (most often named
131 // shr.o) inside an archive library. If this is an archive
132 // library name, then try appending [shr.o] and retry.
133 if (ACE_TString::npos != name->strstr (ACE_TEXT (".a")))
135 ACE_TCHAR aix_pathname[MAXPATHLEN + 1];
136 if (name->length () + SHR_O_LEN <= MAXPATHLEN)
138 ACE_OS::strcpy (aix_pathname, name->c_str());
139 ACE_OS::strcat (aix_pathname, SHR_O);
141 else
143 if (errors)
145 errors->push ("path is too long");
148 if (ACE::debug ())
150 ACELIB_ERROR ((LM_ERROR,
151 ACE_TEXT ("ACE (%P|%t) DLL_Handle::open: ")
152 ACE_TEXT ("('%s(shr.o)') is too long\n"),
153 name->c_str()));
156 return -1;
158 open_mode |= RTLD_MEMBER;
160 if (this->open_i (aix_pathname, open_mode, errors))
161 break;
163 #endif /* AIX */
166 if (this->handle_ == ACE_SHLIB_INVALID_HANDLE)
168 if (ACE::debug ())
170 ACE_TString errtmp;
171 this->error (errtmp);
172 ACELIB_ERROR ((LM_ERROR,
173 ACE_TEXT ("ACE (%P|%t) DLL_Handle::open (\"%s\"): ")
174 ACE_TEXT ("Invalid handle error: %s\n"),
175 this->dll_name_,
176 errtmp.c_str ()));
178 return -1;
183 ++this->refcount_;
185 if (ACE::debug ())
186 ACELIB_DEBUG ((LM_DEBUG,
187 ACE_TEXT ("ACE (%P|%t) DLL_Handle::open - <%s> (%d), refcount=%d\n"),
188 this->dll_name_,
189 this->handle_,
190 this->refcount_));
191 return 0;
196 ACE_DLL_Handle::close (int unload)
198 ACE_TRACE ("ACE_DLL_Handle::close");
200 int retval = 0;
201 ACE_SHLIB_HANDLE h = ACE_SHLIB_INVALID_HANDLE;
203 // Only hold the lock until it comes time to dlclose() the DLL. Closing
204 // the DLL can cause further shutdowns as DLLs and their dependents are
205 // unloaded.
207 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
209 // Since we don't actually unload the dll as soon as the refcount
210 // reaches zero, we need to make sure we don't decrement it below
211 // zero.
212 if (this->refcount_ > 0)
213 --this->refcount_;
214 else
215 this->refcount_ = 0;
217 if (ACE::debug ())
218 ACELIB_DEBUG ((LM_DEBUG,
219 ACE_TEXT ("ACE (%P|%t) DLL_Handle::close - ")
220 ACE_TEXT ("<%s> (handle=%d, refcount=%d)\n"),
221 this->dll_name_,
222 this->handle_,
223 this->refcount_));
225 if (this->refcount_ == 0 &&
226 this->handle_ != ACE_SHLIB_INVALID_HANDLE &&
227 unload == 1)
229 if (ACE::debug ())
230 ACELIB_DEBUG ((LM_DEBUG,
231 ACE_TEXT ("ACE (%P|%t) DLL_Handle::close: ")
232 ACE_TEXT ("Unloading <%s> (handle=%d)\n"),
233 this->dll_name_,
234 this->handle_));
236 // First remove any associated Framework Components.
237 ACE_Framework_Repository *frPtr= ACE_Framework_Repository::instance ();
238 if (frPtr)
240 frPtr->remove_dll_components (this->dll_name_);
243 h = this->handle_;
244 this->handle_ = ACE_SHLIB_INVALID_HANDLE;
246 } // Release lock_ here
248 if (h != ACE_SHLIB_INVALID_HANDLE)
250 retval = ACE_OS::dlclose (h);
252 if (retval != 0 && ACE::debug ())
254 ACE_TString err;
255 ACELIB_ERROR ((LM_ERROR,
256 ACE_TEXT ("ACE (%P|%t) DLL_Handle::close - ")
257 ACE_TEXT ("Failed with: <%s>\n"),
258 this->error (err).c_str ()));
262 return retval;
265 sig_atomic_t
266 ACE_DLL_Handle::refcount (void) const
268 return this->refcount_;
271 void *
272 ACE_DLL_Handle::symbol (const ACE_TCHAR *sym_name, bool ignore_errors)
274 ACE_TString error;
275 return this->symbol (sym_name, ignore_errors, error);
278 void *
279 ACE_DLL_Handle::symbol (const ACE_TCHAR *sym_name, bool ignore_errors, ACE_TString &error)
281 ACE_TRACE ("ACE_DLL_Handle::symbol");
282 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
284 ACE_Auto_Array_Ptr <ACE_TCHAR> auto_name (ACE::ldname (sym_name));
285 // handle_ can be invalid especially when ACE_DLL_Handle resigned ownership
286 // BTW. Handle lifecycle management is a little crazy in ACE
287 if (this->handle_ != ACE_SHLIB_INVALID_HANDLE)
289 #if defined (ACE_OPENVMS)
290 void *sym = ACE::ldsymbol (this->handle_, auto_name.get ());
291 #else
292 void *sym = ACE_OS::dlsym (this->handle_, auto_name.get ());
293 #endif
295 // Linux says that the symbol could be null and that it isn't an
296 // error. So you should check the error message also, but since
297 // null symbols won't do us much good anyway, let's still report
298 // an error.
299 if (!sym && !ignore_errors)
301 this->error (error);
303 if (ACE::debug ())
304 ACELIB_ERROR ((LM_ERROR,
305 ACE_TEXT ("ACE (%P|%t) DLL_Handle::symbol <%s>")
306 ACE_TEXT (" failed with <%s>\n"),
307 auto_name.get (),
308 error.c_str ()));
310 return 0;
312 return sym;
314 return 0;
317 ACE_SHLIB_HANDLE
318 ACE_DLL_Handle::get_handle (bool become_owner)
320 ACE_TRACE ("ACE_DLL_Handle::get_handle");
321 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
323 if (this->refcount_ == 0 && become_owner)
325 if (ACE::debug ())
326 ACELIB_ERROR ((LM_ERROR,
327 ACE_TEXT ("ACE (%P|%t) DLL_Handle::get_handle: ")
328 ACE_TEXT ("cannot become owner, refcount == 0.\n")));
330 return ACE_SHLIB_INVALID_HANDLE;
333 ACE_SHLIB_HANDLE handle = this->handle_;
335 if (become_owner)
337 if (--this->refcount_ == 0)
338 this->handle_ = ACE_SHLIB_INVALID_HANDLE;
341 if (ACE::debug ())
342 ACELIB_DEBUG ((LM_DEBUG,
343 ACE_TEXT ("ACE (%P|%t) DLL_Handle::get_handle: ")
344 ACE_TEXT ("post call: handle %s, refcount %d\n"),
345 this->handle_ == ACE_SHLIB_INVALID_HANDLE ?
346 ACE_TEXT ("invalid") : ACE_TEXT ("valid"),
347 this->refcount_));
349 return handle;
352 // This method is used return the last error of a library operation.
353 ACE_TString &
354 ACE_DLL_Handle::error (ACE_TString &err)
356 ACE_TRACE ("ACE_DLL_Handle::error");
357 const ACE_TCHAR *error = ACE_OS::dlerror ();
358 if (error)
360 err = error;
362 return err;
365 void
366 ACE_DLL_Handle::get_dll_names (const ACE_TCHAR *dll_name,
367 ACE_Array<ACE_TString> &try_names)
369 // Build the array of DLL names to try on this platform by applying the
370 // proper prefixes and/or suffixes to the specified dll_name.
371 ACE_TString base (dll_name);
372 ACE_TString base_dir, base_file, base_suffix;
374 // 1. Separate the dll_name into the dir part and the file part. We
375 // only decorate the file part to determine the names to try loading.
376 ACE_TString::size_type pos = base.rfind (ACE_DIRECTORY_SEPARATOR_CHAR);
377 if (pos != ACE_TString::npos)
379 base_dir = base.substr (0, pos + 1);
380 base_file = base.substr (pos + 1);
382 else
383 base_file = base;
385 // 2. Locate the file suffix, if there is one. Move the '.' and the
386 // suffix to base_suffix.
387 if ((pos = base_file.rfind (ACE_TEXT ('.'))) != ACE_TString::npos)
389 base_suffix = base_file.substr (pos);
390 base_file = base_file.substr (0, pos);
393 // 3. Build the combinations to try for this platform.
394 // Try these combinations:
395 // - name with platform's dll prefix (if it has one) and suffix
396 // - name with platform's dll prefix, decorator, and suffix.
397 // - name with decorator and platform's suffix appended (if not supplied)
398 // - name with platform's suffix appended (if not supplied)
399 // - name as originally given
400 // We first try to find the file using the decorator so that when a
401 // filename with and without decorator is used, we get the file with
402 // the same decorator as the ACE dll has and then as last resort
403 // the one without. For example with msvc, the debug build has a "d"
404 // decorator, but the release build has none and we really want to get
405 // the debug version of the library in a debug application instead
406 // of the release one.
407 // So we need room for 5 entries in try_names.
408 try_names.size (0);
409 if ((try_names.max_size () - try_names.size ()) < 5)
410 try_names.max_size (try_names.max_size () + 5);
411 #if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
412 ACE_TString decorator (ACE_LD_DECORATOR_STR);
413 #endif
414 ACE_TString suffix (ACE_DLL_SUFFIX);
415 ACE_TString prefix (ACE_DLL_PREFIX);
417 for (size_t i = 0; i < 5 && try_names.size () < try_names.max_size (); ++i)
419 ACE_TString try_this;
420 size_t const j = try_names.size ();
421 switch (i)
423 case 0: // Prefix + name + decorator + suffix
424 case 1: // Prefix + name + suffix
425 case 2: // Name + decorator + suffix
426 case 3: // Name + suffix
427 if (
428 base_suffix.length () > 0
429 #if !(defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK))
430 || (i == 1 || i == 3) // No decorator desired; skip
431 #endif
433 break;
434 try_this = base_dir;
435 if (i < 2)
436 try_this += prefix;
437 try_this += base_file;
438 if (base_suffix.length () > 0)
439 try_this += base_suffix;
440 else
442 #if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
443 try_this += decorator;
444 #endif
445 try_this += suffix;
447 break;
448 case 4:
449 try_this = dll_name;
450 break;
453 if (try_this.length ())
455 try_names.size (j + 1);
456 try_names.set (try_this, j);
459 return;
462 bool
463 ACE_DLL_Handle::open_i (const ACE_TCHAR *dll_name, int open_mode, ERROR_STACK* errors)
465 // The ACE_SHLIB_HANDLE object is obtained.
466 this->handle_ = ACE_OS::dlopen (dll_name, open_mode);
468 if (errors || ACE::debug ())
470 ACE_TString err;
471 this->error (err);
472 if (errors && err.length () > 0)
474 errors->push (err);
476 if (ACE::debug ())
478 ACELIB_DEBUG ((LM_DEBUG,
479 ACE_TEXT ("ACE (%P|%t) DLL_Handle::open_i ")
480 ACE_TEXT ("<%s>, 0x%x) -> <%s>: <%s>\n"),
481 dll_name,
482 open_mode,
483 ((this->handle_ != ACE_SHLIB_INVALID_HANDLE)
484 ? ACE_TEXT ("succeeded")
485 : ACE_TEXT ("failed")),
486 err.c_str ()));
490 return this->handle_ != ACE_SHLIB_INVALID_HANDLE;
493 /******************************************************************/
495 // Pointer to the Singleton instance.
496 ACE_DLL_Manager *ACE_DLL_Manager::instance_ = 0;
499 ACE_DLL_Manager *
500 ACE_DLL_Manager::instance (int size)
502 ACE_TRACE ("ACE_DLL_Manager::instance");
504 if (ACE_DLL_Manager::instance_ == 0)
506 // Perform Double-Checked Locking Optimization.
507 ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
508 *ACE_Static_Object_Lock::instance (), 0));
509 if (ACE_DLL_Manager::instance_ == 0)
511 ACE_NEW_RETURN (ACE_DLL_Manager::instance_,
512 ACE_DLL_Manager (size),
517 return ACE_DLL_Manager::instance_;
520 void
521 ACE_DLL_Manager::close_singleton (void)
523 ACE_TRACE ("ACE_DLL_Manager::close_singleton");
525 ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
526 *ACE_Static_Object_Lock::instance ()));
528 delete ACE_DLL_Manager::instance_;
529 ACE_DLL_Manager::instance_ = 0;
532 ACE_DLL_Manager::ACE_DLL_Manager (int size)
533 : handle_vector_ (0),
534 current_size_ (0),
535 total_size_ (0),
536 unload_policy_ (ACE_DLL_UNLOAD_POLICY_PER_DLL)
538 ACE_TRACE ("ACE_DLL_Manager::ACE_DLL_Manager");
540 if (this->open (size) != 0 && ACE::debug ())
541 ACELIB_ERROR ((LM_ERROR,
542 ACE_TEXT ("ACE (%P|%t) DLL_Manager ctor failed to allocate ")
543 ACE_TEXT ("handle_vector_.\n")));
546 ACE_DLL_Manager::~ACE_DLL_Manager (void)
548 ACE_TRACE ("ACE_DLL_Manager::~ACE_DLL_Manager");
550 if (this->close () != 0 && ACE::debug ())
551 ACELIB_ERROR ((LM_ERROR,
552 ACE_TEXT ("ACE (%P|%t) DLL_Manager dtor failed to close ")
553 ACE_TEXT ("properly.\n")));
556 ACE_ALLOC_HOOK_DEFINE(ACE_DLL_Manager)
558 ACE_DLL_Handle *
559 ACE_DLL_Manager::open_dll (const ACE_TCHAR *dll_name,
560 int open_mode,
561 ACE_SHLIB_HANDLE handle,
562 ACE_DLL_Handle::ERROR_STACK *errors)
564 ACE_TRACE ("ACE_DLL_Manager::open_dll");
566 ACE_DLL_Handle *temp_handle = 0;
567 ACE_DLL_Handle *dll_handle = 0;
569 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
570 dll_handle = this->find_dll (dll_name);
571 if (!dll_handle)
573 if (this->current_size_ < this->total_size_)
575 ACE_NEW_RETURN (temp_handle,
576 ACE_DLL_Handle,
579 dll_handle = temp_handle;
584 if (dll_handle)
586 if (dll_handle->open (dll_name, open_mode, handle, errors) != 0)
588 // Error while opening dll. Free temp handle
589 if (ACE::debug ())
590 ACELIB_ERROR ((LM_ERROR,
591 ACE_TEXT ("ACE (%P|%t) DLL_Manager::open_dll: Could not ")
592 ACE_TEXT ("open dll <%s>\n"),
593 dll_name));
595 delete temp_handle;
596 return 0;
599 // Add the handle to the vector only if the dll is successfully
600 // opened.
601 if (temp_handle != 0)
603 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
604 this->handle_vector_[this->current_size_] = dll_handle;
605 ++this->current_size_;
609 return dll_handle;
613 ACE_DLL_Manager::close_dll (const ACE_TCHAR *dll_name)
615 ACE_TRACE ("ACE_DLL_Manager::close_dll");
616 ACE_DLL_Handle *handle = 0;
619 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
620 handle = this->find_dll (dll_name);
623 if (handle)
625 return this->unload_dll (handle, 0);
628 return -1;
631 u_long
632 ACE_DLL_Manager::unload_policy (void) const
634 ACE_TRACE ("ACE_DLL_Manager::unload_policy");
635 return this->unload_policy_;
638 void
639 ACE_DLL_Manager::unload_policy (u_long unload_policy)
641 ACE_TRACE ("ACE_DLL_Manager::unload_policy");
642 ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->lock_));
644 u_long old_policy = this->unload_policy_;
645 this->unload_policy_ = unload_policy;
647 // If going from LAZY to EAGER or from PER_DLL to PER_PROCESS|EAGER,
648 // call close(1) on all the ACE_DLL_Handle objects with refcount == 0
649 // which will force those that are still loaded to be unloaded.
650 if (this->handle_vector_)
651 if (( ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_LAZY) &&
652 ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) ) ||
653 ( ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) &&
654 ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_PER_DLL) &&
655 ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_PER_DLL) ))
657 for (int i = this->current_size_ - 1; i >= 0; i--)
659 if (this->handle_vector_[i] &&
660 this->handle_vector_[i]->refcount () == 0)
661 this->handle_vector_[i]->close (1);
667 ACE_DLL_Manager::open (int size)
669 ACE_TRACE ("ACE_DLL_Manager::open");
671 ACE_DLL_Handle **temp = 0;
673 #if defined (ACE_HAS_ALLOC_HOOKS)
674 ACE_ALLOCATOR_RETURN (temp,
675 static_cast<ACE_DLL_Handle**> (ACE_Allocator::instance()->malloc(sizeof (ACE_DLL_Handle*) * size)),
676 -1);
677 #else
678 ACE_NEW_RETURN (temp,
679 ACE_DLL_Handle *[size],
680 -1);
681 #endif /* ACE_HAS_ALLOC_HOOKS */
683 this->handle_vector_ = temp;
684 this->total_size_ = size;
685 return 0;
689 ACE_DLL_Manager::close (void)
691 ACE_TRACE ("ACE_DLL_Manager::close");
693 int force_close = 1;
695 if (this->handle_vector_ != 0)
697 // Delete components in reverse order.
698 for (int i = this->current_size_ - 1; i >= 0; i--)
700 if (this->handle_vector_[i])
702 ACE_DLL_Handle *s =
703 const_cast<ACE_DLL_Handle *> (this->handle_vector_[i]);
704 this->handle_vector_[i] = 0;
705 this->unload_dll (s, force_close);
706 delete s;
710 #if defined (ACE_HAS_ALLOC_HOOKS)
711 ACE_Allocator::instance()->free(this->handle_vector_);
712 #else
713 delete [] this->handle_vector_;
714 #endif /* ACE_HAS_ALLOC_HOOKS */
716 this->handle_vector_ = 0;
717 this->current_size_ = 0;
719 return 0;
722 ACE_DLL_Handle *
723 ACE_DLL_Manager::find_dll (const ACE_TCHAR *dll_name) const
725 ACE_TRACE ("ACE_DLL_Manager::find_dll");
727 for (int i = 0; i < this->current_size_; i++)
728 if (this->handle_vector_[i] &&
729 ACE_OS::strcmp (this->handle_vector_[i]->dll_name (), dll_name) == 0)
731 return this->handle_vector_[i];
734 return 0;
738 ACE_DLL_Manager::unload_dll (ACE_DLL_Handle *dll_handle, int force_unload)
740 ACE_TRACE ("ACE_DLL_Manager::unload_dll");
742 if (dll_handle)
744 int unload = force_unload;
745 if (unload == 0)
747 // apply strategy
748 if (ACE_BIT_DISABLED (this->unload_policy_,
749 ACE_DLL_UNLOAD_POLICY_PER_DLL))
751 unload = ACE_BIT_DISABLED (this->unload_policy_,
752 ACE_DLL_UNLOAD_POLICY_LAZY);
754 else
756 // Declare the type of the symbol:
757 typedef int (*dll_unload_policy)(void);
759 void * const unload_policy_ptr =
760 dll_handle->symbol (ACE_TEXT ("_get_dll_unload_policy"), 1);
761 #if defined (ACE_OPENVMS) && (!defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64))
762 int const temp_p =
763 reinterpret_cast<int> (unload_policy_ptr);
764 #else
765 intptr_t const temp_p =
766 reinterpret_cast<intptr_t> (unload_policy_ptr);
767 #endif
769 dll_unload_policy const the_policy =
770 reinterpret_cast<dll_unload_policy> (temp_p);
772 if (the_policy != 0)
773 unload = ACE_BIT_DISABLED (the_policy (),
774 ACE_DLL_UNLOAD_POLICY_LAZY);
775 else
776 unload = ACE_BIT_DISABLED (this->unload_policy_,
777 ACE_DLL_UNLOAD_POLICY_LAZY);
781 if (dll_handle->close (unload) != 0)
783 if (ACE::debug ())
784 ACELIB_ERROR ((LM_ERROR,
785 ACE_TEXT ("ACE (%P|%t) DLL_Manager::unload error.\n")));
787 return -1;
790 else
792 if (ACE::debug ())
793 ACELIB_ERROR ((LM_ERROR,
794 ACE_TEXT ("ACE (%P|%t) DLL_Manager::unload_dll called with ")
795 ACE_TEXT ("null pointer.\n")));
797 return -1;
800 return 0;
803 ACE_END_VERSIONED_NAMESPACE_DECL