00001 // -*- C++ -*- 00002 00003 //============================================================================= 00004 /** 00005 * @file DLL_Manager.h 00006 * 00007 * $Id: DLL_Manager.h 80826 2008-03-04 14:51:23Z wotte $ 00008 * 00009 * @author Don Hinton <dhinton@ieee.org> 00010 */ 00011 //============================================================================= 00012 00013 #ifndef ACE_DLL_MANAGER_H 00014 #define ACE_DLL_MANAGER_H 00015 #include /**/ "ace/pre.h" 00016 00017 #include /**/ "ace/ACE_export.h" 00018 00019 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00020 # pragma once 00021 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00022 00023 #include "ace/Auto_Ptr.h" 00024 #include "ace/Containers_T.h" 00025 #include "ace/SStringfwd.h" 00026 #include "ace/os_include/os_dlfcn.h" 00027 00028 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) 00029 # include "ace/Thread_Mutex.h" 00030 #endif /* ACE_MT_SAFE */ 00031 00032 #define ACE_DEFAULT_DLL_MANAGER_SIZE 1024 00033 00034 00035 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00036 00037 /** 00038 * @class ACE_DLL_Handle 00039 * 00040 * @brief Provides an abstract interface for handling various DLL 00041 * operations. 00042 * 00043 * This class is an wrapper over the various methods for utilizing a 00044 * dynamically linked library (DLL), which is called a shared library 00045 * on some platforms. It is refcounted and managed by 00046 * ACE_DLL_Manager, so there will only be a single instance of this 00047 * class for each dll loaded, no matter how many instances of ACE_DLL 00048 * an application has open. Operations <open>, <close>, and <symbol> 00049 * have been implemented to help opening/closing and extracting symbol 00050 * information from a DLL, respectively. 00051 * 00052 * Most of this class came from the original ACE_DLL class. ACE_DLL 00053 * is now just an interface that passed all it's calls either directly 00054 * or via ACE_DLL_Manager to this class for execution. 00055 * 00056 */ 00057 class ACE_Export ACE_DLL_Handle 00058 { 00059 public: 00060 00061 /// Default construtor. 00062 ACE_DLL_Handle (void); 00063 00064 /// Destructor. 00065 ~ACE_DLL_Handle (void); 00066 00067 /// Returns the name of the shared library (without prefixes or suffixes). 00068 const ACE_TCHAR *dll_name () const; 00069 00070 /** 00071 * This method opens and dynamically links @a dll_name. The default 00072 * mode is <RTLD_LAZY>, which loads identifier symbols but not the 00073 * symbols for functions, which are loaded dynamically on-demand. 00074 * Other supported modes include: <RTLD_NOW>, which performs all 00075 * necessary relocations when @a dll_name is first loaded and 00076 * <RTLD_GLOBAL>, which makes symbols available for relocation 00077 * processing of any other DLLs. Returns -1 on failure and 0 on 00078 * success. 00079 */ 00080 int open (const ACE_TCHAR *dll_name, 00081 int open_mode, 00082 ACE_SHLIB_HANDLE handle); 00083 00084 /// Call to close the DLL object. If unload = 0, it only decrements 00085 /// the refcount, but if unload = 1, then it will actually unload 00086 /// the library when the refcount == 0; 00087 int close (int unload = 0); 00088 00089 /// Return the current refcount. 00090 sig_atomic_t refcount (void) const; 00091 00092 /// If @a symbol_name is in the symbol table of the DLL a pointer to 00093 /// the @a symbol_name is returned. Otherwise, returns 0. Set the 00094 /// ignore_errors flag to supress logging errors if symbol_name isn't 00095 /// found. This is nice if you just want to probe a dll to see what's 00096 /// available, since missing functions in that case aren't really errors. 00097 void *symbol (const ACE_TCHAR *symbol_name, int ignore_errors = 0); 00098 00099 /** 00100 * Return the handle to the caller. If @a become_owner is non-0 then 00101 * caller assumes ownership of the handle so we decrement the retcount. 00102 */ 00103 ACE_SHLIB_HANDLE get_handle (int become_owner = 0); 00104 00105 private: 00106 00107 /// Returns a pointer to a string explaining why <symbol> or <open> 00108 /// failed. This is used internal to print out the error to the log, 00109 /// but since this object is shared, we can't store or return the error 00110 /// to the caller. 00111 auto_ptr <ACE_TString> error (void); 00112 00113 // Builds array of DLL names to try to dlopen, based on platform 00114 // and configured DLL prefixes/suffixes. 00115 // Returns the array of names to try in try_names. 00116 void get_dll_names (const ACE_TCHAR *dll_name, 00117 ACE_Array<ACE_TString> &try_names); 00118 00119 // Disallow copying and assignment since we don't handle them. 00120 ACE_DLL_Handle (const ACE_DLL_Handle &); 00121 void operator= (const ACE_DLL_Handle &); 00122 00123 private: 00124 00125 // Keep track of how many ACE_DLL objects have a reference to this 00126 // dll. 00127 sig_atomic_t refcount_; 00128 00129 /// Name of the shared library. 00130 ACE_TCHAR *dll_name_; 00131 00132 /// Handle to the actual library loaded by the OS. 00133 ACE_SHLIB_HANDLE handle_; 00134 00135 /// Keeps track of whether or not open() has ever been called. This 00136 /// helps get around problem on Linux, and perhaps other OS's, that 00137 /// seg-fault if dlerror() is called before the ld library has been 00138 /// initialized by a call to dlopen(). 00139 static sig_atomic_t open_called_; 00140 00141 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) 00142 /// Synchronization variable for the MT_SAFE Repository 00143 ACE_Thread_Mutex lock_; 00144 #endif /* ACE_MT_SAFE */ 00145 }; 00146 00147 class ACE_Framework_Repository; 00148 00149 /** 00150 * @class ACE_DLL_Manager 00151 * 00152 * @brief This class is a singleton and serves as a factory and 00153 * repository for instances of ACE_DLL_Handle. 00154 * 00155 * This class is a singleton whose lifetime is managed by the 00156 * ACE_Framework_Repository. Although it is normally meant to be 00157 * used directly only by ACE_DLL, applications can call the unload_policy() 00158 * methods in order get/set the the dll unload policy. Unload policies include 00159 * per_process/per-dll and eager/lazy. Dlls can export set their own policy 00160 * by using the ACE_DLL_UNLOAD_POLICY macro found in config-all.h. If a dll 00161 * choses to set an unload policy, it will be used when the per-dll policy 00162 * (the default) is in effect. If the per-dll policy is in effect and a dll 00163 * has not chosen to set a policy, the current per-process policy will be 00164 * used. 00165 * 00166 * The following policy macros are provided in config-all.h: 00167 * 00168 * ACE_DLL_UNLOAD_POLICY_PER_PROCESS - Per-process policy that unloads dlls 00169 * eagerly. 00170 * 00171 * ACE_DLL_UNLOAD_POLICY_PER_DLL - Apply policy on a per-dll basis. If the 00172 * dll doesn't use one of the macros below, the current per-process policy 00173 * will be used. 00174 * 00175 * ACE_DLL_UNLOAD_POLICY_LAZY - Don't unload dll when refcount reaches 00176 * zero, i.e., wait for either an explicit unload request or program exit. 00177 * 00178 * ACE_DLL_UNLOAD_POLICY_DEFAULT - Default policy allows dlls to control 00179 * their own destinies, but will unload those that don't make a choice eagerly. 00180 * 00181 */ 00182 class ACE_Export ACE_DLL_Manager 00183 { 00184 public: 00185 friend class ACE_Framework_Repository; 00186 friend class ACE_Object_Manager; 00187 00188 enum 00189 { 00190 DEFAULT_SIZE = ACE_DEFAULT_DLL_MANAGER_SIZE 00191 }; 00192 00193 /// Return a unique instance 00194 static ACE_DLL_Manager *instance (int size = ACE_DLL_Manager::DEFAULT_SIZE); 00195 00196 /// Factory for ACE_DLL_Handle objects. If one already exits, 00197 /// its refcount is incremented. 00198 ACE_DLL_Handle *open_dll (const ACE_TCHAR *dll_name, 00199 int openmode, 00200 ACE_SHLIB_HANDLE handle); 00201 00202 /// Close the underlying dll. Decrements the refcount. 00203 int close_dll (const ACE_TCHAR *dll_name); 00204 00205 /// Returns the current per-process UNLOAD_POLICY. 00206 u_long unload_policy (void) const; 00207 00208 /// Set the per-process UNLOAD_POLICY. If the policy is changed from 00209 /// LAZY to EAGER, then it will also unload any dlls with zero 00210 /// refcounts. 00211 void unload_policy (u_long unload_policy); 00212 00213 protected: 00214 00215 /// Default constructor. 00216 ACE_DLL_Manager (int size = ACE_DLL_Manager::DEFAULT_SIZE); 00217 00218 /// Destructor. 00219 ~ACE_DLL_Manager (void); 00220 00221 // Allocate handle_vector_. 00222 int open (int size); 00223 00224 // Close all open dlls and deallocate memory. 00225 int close (void); 00226 00227 // Find dll in handle_vector_. 00228 ACE_DLL_Handle *find_dll (const ACE_TCHAR *dll_name) const; 00229 00230 // Applies strategy for unloading dll. 00231 int unload_dll (ACE_DLL_Handle *dll_handle, int force_unload = 0); 00232 00233 private: 00234 00235 /// Close the singleton instance. 00236 static void close_singleton (void); 00237 00238 // Disallow copying and assignment since we don't handle these. 00239 ACE_DLL_Manager (const ACE_DLL_Manager &); 00240 void operator= (const ACE_DLL_Manager &); 00241 00242 private: 00243 00244 /// Vector containing all loaded handle objects. 00245 ACE_DLL_Handle **handle_vector_; 00246 00247 /// Current number of handles. 00248 int current_size_; 00249 00250 /// Maximum number of handles. 00251 int total_size_; 00252 00253 /// Unload strategy. 00254 u_long unload_policy_; 00255 00256 /// Pointer to a process-wide ACE_DLL_Manager. 00257 static ACE_DLL_Manager *instance_; 00258 00259 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) 00260 /// Synchronization variable for the MT_SAFE Repository 00261 ACE_Thread_Mutex lock_; 00262 #endif /* ACE_MT_SAFE */ 00263 00264 }; 00265 00266 ACE_END_VERSIONED_NAMESPACE_DECL 00267 00268 #include /**/ "ace/post.h" 00269 #endif /* ACE_DLL_MANAGER_H */