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