00001 // -*- C++ -*- 00002 00003 //==================================================================== 00004 /** 00005 * @file Service_Config.h 00006 * 00007 * Service_Config.h,v 4.109 2006/06/20 12:40:38 jwillemsen Exp 00008 * 00009 * @author Douglas C. Schmidt <schmidt@cs.wustl.edu> 00010 */ 00011 //==================================================================== 00012 00013 #ifndef ACE_SERVICE_CONFIG_H 00014 #define ACE_SERVICE_CONFIG_H 00015 00016 #include /**/ "ace/pre.h" 00017 00018 #include "ace/config-all.h" 00019 #include "ace/Default_Constants.h" 00020 #include "ace/Service_Gestalt.h" 00021 00022 #if !defined (ACE_LACKS_PRAGMA_ONCE) 00023 # pragma once 00024 #endif /* ACE_LACKS_PRAGMA_ONCE */ 00025 00026 #include "ace/SString.h" 00027 #include "ace/OS_NS_signal.h" 00028 00029 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00030 00031 // Forward decl. 00032 class ACE_Service_Object; 00033 class ACE_Service_Type; 00034 class ACE_Service_Type_Impl; 00035 class ACE_Service_Repository; 00036 class ACE_Sig_Adapter; 00037 class ACE_Allocator; 00038 class ACE_Reactor; 00039 class ACE_Thread_Manager; 00040 class ACE_DLL; 00041 00042 #if (ACE_USES_CLASSIC_SVC_CONF == 1) 00043 #define ACE_DYNAMIC_SERVICE_DIRECTIVE(ident, libpathname, objectclass, parameters) \ 00044 ACE_LIB_TEXT ("dynamic ") \ 00045 ACE_LIB_TEXT (ident) \ 00046 ACE_LIB_TEXT (" Service_Object * ") \ 00047 ACE_LIB_TEXT (libpathname) \ 00048 ACE_LIB_TEXT (":") \ 00049 ACE_LIB_TEXT (objectclass) \ 00050 ACE_LIB_TEXT ("() \"") \ 00051 ACE_LIB_TEXT (parameters) \ 00052 ACE_LIB_TEXT ("\"") 00053 #define ACE_REMOVE_SERVICE_DIRECTIVE(ident) \ 00054 ACE_LIB_TEXT ("remove ") \ 00055 ACE_LIB_TEXT (ident) 00056 class ACE_Svc_Conf_Param; 00057 #else 00058 #define ACE_DYNAMIC_SERVICE_DIRECTIVE(ident, libpathname, objectclass, parameters) \ 00059 ACE_LIB_TEXT ("<ACE_Svc_Conf><dynamic id=\"") \ 00060 ACE_LIB_TEXT (ident) \ 00061 ACE_LIB_TEXT ("\" type=\"Service_Object\">") \ 00062 ACE_LIB_TEXT ("<initializer path=\"") \ 00063 ACE_LIB_TEXT (libpathname) \ 00064 ACE_LIB_TEXT ("\" init=\"") \ 00065 ACE_LIB_TEXT (objectclass) \ 00066 ACE_LIB_TEXT ("\"") \ 00067 ACE_LIB_TEXT (" params=\"") \ 00068 ACE_LIB_TEXT (parameters) \ 00069 ACE_LIB_TEXT ("\"/></dynamic></ACE_Svc_Conf>") 00070 #define ACE_REMOVE_SERVICE_DIRECTIVE(ident) \ 00071 ACE_LIB_TEXT ("<ACE_Svc_Conf><remove id=\"") \ 00072 ACE_LIB_TEXT (ident) \ 00073 ACE_LIB_TEXT ("\"></remove></ACE_Svc_Conf>") 00074 class ACE_XML_Svc_Conf; 00075 #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */ 00076 00077 ACE_END_VERSIONED_NAMESPACE_DECL 00078 00079 extern "C" 00080 { 00081 typedef ACE_Service_Object *(*ACE_SERVICE_ALLOCATOR) (ACE_Service_Object_Exterminator *); 00082 } 00083 00084 ACE_BEGIN_VERSIONED_NAMESPACE_DECL 00085 00086 /** 00087 * @class ACE_Static_Svc_Descriptor 00088 * 00089 * @brief Holds the information necessary to describe a statically linked 00090 * Svc. 00091 */ 00092 class ACE_Static_Svc_Descriptor 00093 { 00094 public: 00095 /// Name of the service. 00096 const ACE_TCHAR *name_; 00097 00098 /// Type of service. 00099 int type_; 00100 00101 /// Factory function that allocates the service. 00102 ACE_SERVICE_ALLOCATOR alloc_; 00103 00104 /// Bitmask flags indicating how the framework should delete memory. 00105 u_int flags_; 00106 00107 /// Flag indicating whether the service starts out active. 00108 int active_; 00109 00110 /// Dump the state of an object. 00111 void dump (void) const; 00112 00113 /// Declare the dynamic allocation hooks. 00114 ACE_ALLOC_HOOK_DECLARE; 00115 00116 public: 00117 /// Compare two service descriptors for equality. 00118 bool operator== (ACE_Static_Svc_Descriptor &) const; 00119 00120 /// Compare two service descriptors for inequality. 00121 bool operator!= (ACE_Static_Svc_Descriptor &) const; 00122 }; 00123 00124 #if defined (ACE_OPENVMS) 00125 /** 00126 * @class ACE_Static_Svc_Registrar 00127 * 00128 * @brief Used to register Service allocator function by its full name. 00129 */ 00130 class ACE_Static_Svc_Registrar 00131 { 00132 public: 00133 ACE_Static_Svc_Registrar (const ACE_TCHAR* alloc_name, 00134 ACE_SERVICE_ALLOCATOR alloc); 00135 }; 00136 #endif 00137 00138 #define ACE_Component_Config ACE_Service_Config 00139 00140 /** 00141 * @class ACE_Service_Config 00142 * 00143 * @brief Supplies common server operations for dynamic and static 00144 * configuration of services. 00145 * 00146 * The ACE_Service_Config uses the Monostate pattern. Therefore, 00147 * you can only have one of these instantiated per-process. It 00148 * represents the process-wide collection of services, which is 00149 * typicaly shared among all other configurable entities. The only 00150 * ACE_Service_Config instance is registered with and owned by the 00151 * ACE_Object_Manager. 00152 * 00153 * By contrast, the ACE_Service_Gestalt represents the collection 00154 * of services, pertaining to a configurable entity. Typicaly, a 00155 * "configurable entity" is an instance, which owns an instance of 00156 * ACE_Service_Gestalt in order to ensure full controll over the 00157 * services it needs. 00158 * 00159 * Another facet of ACE_Service_Config is that for a given thread, 00160 * it provides access to its current, process-global 00161 * ACE_Service_Gestalt instance through its curent() method. 00162 * 00163 * @note The signal_handler_ static member is allocated by the 00164 * ACE_Object_Manager. The ACE_Service_Config constructor 00165 * uses signal_handler_. Therefore, if the program has any 00166 * static ACE_Service_Config objects, there might be 00167 * initialization order problems. They can be minimized, but 00168 * not eliminated, by _not_ #defining 00169 * ACE_HAS_NONSTATIC_OBJECT_MANAGER. 00170 */ 00171 class ACE_Export ACE_Service_Config: public ACE_Service_Gestalt 00172 { 00173 00174 public: 00175 00176 // = Initialization and termination methods. 00177 00178 /** 00179 * Initialize the Service Repository. Note that initialising @a 00180 * signum to a negative number will prevent a signal handler being 00181 * registered when the repository is opened. 00182 */ 00183 ACE_Service_Config (int ignore_static_svcs = 1, 00184 size_t size = ACE_Service_Gestalt::MAX_SERVICES, 00185 int signum = SIGHUP); 00186 00187 /** 00188 * Performs an open without parsing command-line arguments. The 00189 * @a logger_key indicates where to write the logging output, which 00190 * is typically either a STREAM pipe or a socket address. 00191 */ 00192 ACE_Service_Config (const ACE_TCHAR program_name[], 00193 const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY); 00194 00195 /// Perform user-specified close activities and remove dynamic 00196 /// memory. 00197 virtual ~ACE_Service_Config (void); 00198 00199 00200 protected: 00201 00202 /** 00203 * Performs an open without parsing command-line arguments. 00204 * Implements whats different in the opening sequence 00205 * for this class, as opposed to the base class. 00206 * 00207 * The @a logger_key indicates where to write the logging output, which 00208 * is typically either a STREAM pipe or a socket address. If 00209 * @a ignore_default_svc_conf_file is non-0 then the "svc.conf" file 00210 * will be ignored. If @a ignore_debug_flag is non-0 then the 00211 * application is responsible for setting the 00212 * @c ACE_Log_Msg::priority_mask() appropriately. Returns number of 00213 * errors that occurred on failure and 0 otherwise. 00214 */ 00215 virtual int open_i (const ACE_TCHAR program_name[], 00216 const ACE_TCHAR *logger_key, 00217 bool ignore_static_svcs, 00218 bool ignore_default_svc_conf_file, 00219 bool ignore_debug_flag); 00220 00221 /** 00222 * Implements whats different in the command line parameter processing 00223 * for this class, as opposed to the base class. 00224 */ 00225 virtual int parse_args_i (int argc, ACE_TCHAR *argv[]); 00226 00227 00228 00229 /// = Static interfaces 00230 00231 private: 00232 00233 /// A private, non-locking mutator to set the "current" (TSS) gestalt instance. 00234 /// Make sure to call with the proper locks held! 00235 static ACE_Service_Gestalt* current_i (ACE_Service_Gestalt *newcurrent); 00236 00237 /// A Wrapper for the TSS-stored pointer. 00238 struct TSS_Resources { 00239 TSS_Resources (void) : ptr_ (0) {}; 00240 ACE_Service_Gestalt *ptr_; 00241 }; 00242 00243 /// A type for the TSS-stored resources. The typedef helps to 00244 /// abstract from the particularities of single-threaded vs 00245 /// multi-threaded environments. 00246 typedef ACE_TSS_TYPE (ACE_Service_Config::TSS_Resources) TSS_Service_Gestalt_Ptr; 00247 00248 /// Provides access to the static ptr, containing the TSS 00249 /// accessor. Ensures the desired order of initialization, even when 00250 /// other static initializers need the value. 00251 static TSS_Service_Gestalt_Ptr * & impl_ (void); 00252 00253 protected: 00254 00255 /// Mutator to set the (TSS) global instance. Intended for use by helper 00256 /// classes, like ACE_Service_Config_Guard which when instantiated on the 00257 /// stack, can temporarily change which gestalt instance is viewed as 00258 /// global from the point of view of the static initializers in DLLs. 00259 static ACE_Service_Gestalt* current (ACE_Service_Gestalt*); 00260 00261 00262 public: 00263 00264 /// If not yet initialized, creates a process-wide instance 00265 /// global instance, which is registered with the ACE_Object_Manager, 00266 /// via ACE_Singleton. Note that this is allways the same instance, 00267 /// in contrast with current (), which may be different instance at 00268 /// different times, dependent on the context. 00269 static ACE_Service_Gestalt* global (void); 00270 00271 00272 /// Accessor for the "current" service repository through a pointer 00273 /// held in TSS. 00274 static ACE_Service_Gestalt* current (void); 00275 00276 /// This is what the static service initializators are hard-wired 00277 /// to use, so in order to keep interface changes to a minimum this 00278 /// method merely forwards to current(). Thus it is possible to 00279 /// temporarily replace what those initializers think is the global 00280 /// service repository, for instance when dynamically loading a 00281 /// service from a DLL, which in turn, contains its own static services. 00282 static ACE_Service_Gestalt* instance (void); 00283 00284 /** 00285 * Performs an open without parsing command-line arguments. The 00286 * @a logger_key indicates where to write the logging output, which 00287 * is typically either a STREAM pipe or a socket address. If 00288 * @a ignore_static_svcs is 1 then static services are not loaded, 00289 * otherwise, they are loaded. If @a ignore_default_svc_conf_file is 00290 * non-0 then the <svc.conf> configuration file will be ignored. 00291 * Returns zero upon success, -1 if the file is not found or cannot 00292 * be opened (errno is set accordingly), otherwise returns the 00293 * number of errors encountered loading the services in the 00294 * specified svc.conf configuration file. If @a ignore_debug_flag is 00295 * non-0 then the application is responsible for setting the 00296 * @c ACE_Log_Msg::priority_mask appropriately. 00297 */ 00298 static int open (const ACE_TCHAR program_name[], 00299 const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY, 00300 int ignore_static_svcs = 1, 00301 int ignore_default_svc_conf_file = 0, 00302 int ignore_debug_flag = 0); 00303 00304 /** 00305 * This is the primary entry point into the ACE_Service_Config (the 00306 * constructor just handles simple initializations). It parses 00307 * arguments passed in from @a argc and @a argv parameters. The 00308 * arguments that are valid in a call to this method include: 00309 * 00310 * - '-b' Option to indicate that we should be a daemon. Note that when 00311 * this option is used, the process will be daemonized before the 00312 * service configuration file(s) are read. During daemonization, 00313 * (on POSIX systems) the current directory will be changed to "/" 00314 * so the caller should either fully specify the file names, or 00315 * execute a @c chroot() to the appropriate directory. 00316 * @sa ACE::daemonize(). 00317 * - '-d' Turn on debugging mode 00318 * - '-f' Specifies a configuration file name other than the default 00319 * svc.conf. Can be specified multiple times to use multiple files. 00320 * - '-k' Specifies the rendezvous point to use for the ACE distributed 00321 * logger. 00322 * - '-y' Explicitly enables the use of static services. This flag 00323 * overrides the @a ignore_static_svcs parameter value. 00324 * - '-n' Explicitly disables the use of static services. This flag 00325 * overrides the @a ignore_static_svcs parameter value. 00326 * - '-p' Specifies a pathname which is used to store the process id. 00327 * - '-s' Specifies a signal number other than SIGHUP to trigger reprocessing 00328 * of the configuration file(s). Ignored for platforms that do not 00329 * have POSIX signals, such as Windows. 00330 * - '-S' Specifies a service directive string. Enclose the string in quotes 00331 * and escape any embedded quotes with a backslash. This option 00332 * specifies service directives without the need for a configuration 00333 * file. 00334 * 00335 * @param argc The number of commandline arguments. 00336 * @param argv The array with commandline arguments 00337 * @param logger_key Indicates where to write the logging output, 00338 * which is typically either a STREAM pipe or a 00339 * socket address. 00340 * @param ignore_static_svcs If 1 then static services are not loaded, 00341 * otherwise, they are loaded. 00342 * @param ignore_default_svc_conf_file If non-0 then the @c svc.conf 00343 * configuration file will be ignored. 00344 * @param ignore_debug_flag If non-0 then the application is responsible 00345 * for setting the @c ACE_Log_Msg::priority_mask 00346 * appropriately. 00347 * 00348 * @retval -1 The configuration file is not found or cannot 00349 * be opened (errno is set accordingly). 00350 * @retval 0 Success. 00351 * @retval >0 The number of errors encountered while processing 00352 * the service configuration file(s). 00353 */ 00354 static int open (int argc, 00355 ACE_TCHAR *argv[], 00356 const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY, 00357 int ignore_static_svcs = 1, 00358 int ignore_default_svc_conf_file = 0, 00359 int ignore_debug_flag = 0); 00360 00361 /// Tidy up and perform last rites when ACE_Service_Config is shut 00362 /// down. This method calls <close_svcs>. Returns 0. 00363 static int close (void); 00364 00365 /// Perform user-specified close hooks and possibly delete all of the 00366 /// configured services in the <Service_Repository>. 00367 static int fini_svcs (void); 00368 00369 /** 00370 * Perform user-specified close hooks on all of the configured 00371 * services in the Service_Repository, then delete the 00372 * Service_Repository itself. Returns 0. 00373 */ 00374 static int close_svcs (void); 00375 00376 /// True if reconfiguration occurred. 00377 static int reconfig_occurred (void); 00378 00379 /// Indicate that reconfiguration occurred. 00380 static void reconfig_occurred (int); 00381 00382 /// Perform the reconfiguration process. 00383 static void reconfigure (void); 00384 00385 // = The following methods are static in order to enforce Singleton 00386 // semantics for the Reactor, Service_Repository, Thread_Manager, 00387 // and Acceptor/Connector Strategy factory. Other portions of the 00388 // system may need to access them at some point or another... 00389 00390 // = This is not strictly needed, anymore since the service configurator 00391 // has been refactored to allow multiple service configuration 00392 // instances (called gestalts). The interfaces, however were retained in for 00393 // the sake of maintaining source-code compatibility. 00394 00395 00396 // = Accessors and mutators for process-wide Singletons. 00397 00398 /// Returns a pointer to the list of statically linked services. 00399 /// 00400 /// @deprecated - Same as instance(), but still useful in legacy code, 00401 /// (notably, one that can not be easily modified) which uses the following 00402 /// idiom for registering static services: 00403 /// 00404 /// ACE_Service_Config::static_svcs ()->insert (...); 00405 static ACE_Service_Gestalt *static_svcs (void); 00406 00407 /// Insert a static service descriptor for processing on open_i(). The 00408 /// corresponding ACE_STATIC_SVC_* macros were chaged to use this method 00409 /// instead of obtaining a ptr to a container. See the note on static_svcs(). 00410 /// Added to prevent exposing the internal storage representation of the 00411 /// services repository and provide a better way of debugging service 00412 /// loading and registration problems. 00413 static int insert (ACE_Static_Svc_Descriptor *svc); 00414 00415 // = Utility methods. 00416 /// Dynamically link the shared object file and retrieve a pointer to 00417 /// the designated shared object in this file. 00418 static int initialize (const ACE_Service_Type *, 00419 const ACE_TCHAR *parameters); 00420 00421 /// Initialize and activate a statically @a svc_name service. 00422 static int initialize (const ACE_TCHAR *svc_name, 00423 const ACE_TCHAR *parameters); 00424 00425 /// Resume a @a svc_name that was previously suspended or has not yet 00426 /// been resumed (e.g., a static service). 00427 static int resume (const ACE_TCHAR svc_name[]); 00428 00429 /** 00430 * Suspend @a svc_name. Note that this will not unlink the service 00431 * from the daemon if it was dynamically linked, it will mark it as 00432 * being suspended in the Service Repository and call the <suspend> 00433 * member function on the appropriate ACE_Service_Object. A 00434 * service can be resumed later on by calling the <RESUME> member 00435 * function... 00436 */ 00437 static int suspend (const ACE_TCHAR svc_name[]); 00438 00439 /// Totally remove @a svc_name from the daemon by removing it 00440 /// from the ACE_Reactor, and unlinking it if necessary. 00441 static int remove (const ACE_TCHAR svc_name[]); 00442 00443 #if defined (ACE_HAS_WINCE) && defined (ACE_USES_WCHAR) 00444 // We must provide these function to bridge the Svc_Conf parser 00445 // with ACE. 00446 static int initialize (const ACE_Service_Type *, ACE_ANTI_TCHAR []); 00447 static int initialize (const char svc_name[], ACE_ANTI_TCHAR parameters[]); 00448 static int resume (const ACE_ANTI_TCHAR svc_name[]); 00449 static int suspend (const ACE_ANTI_TCHAR svc_name[]); 00450 static int remove (const ACE_ANTI_TCHAR svc_name[]); 00451 #endif /* ACE_HAS_WINCE */ 00452 00453 /// Dump the state of an object. 00454 void dump (void) const; 00455 00456 /// Set the signal_handler;for internal use by ACE_Object_Manager only. 00457 static ACE_INLINE void signal_handler (ACE_Sig_Adapter *); 00458 00459 /// Declare the dynamic allocation hooks. 00460 ACE_ALLOC_HOOK_DECLARE; 00461 00462 /// Process a file containing a list of service configuration 00463 /// directives. 00464 static int process_file (const ACE_TCHAR file[]); 00465 00466 /// Process one service configuration @a directive, which is passed as 00467 /// a string. Returns the number of errors that occurred. 00468 static int process_directive (const ACE_TCHAR directive[]); 00469 00470 /// Process one static service definition. 00471 /** 00472 * Load a new static service into the ACE_Service_Repository. 00473 * 00474 * @param ssd Service descriptor, see the document of 00475 * ACE_Static_Svc_Descriptor for more details. 00476 * 00477 * @param force_replace If set the new service descriptor replaces 00478 * any previous instance in the ACE_Service_Repository. 00479 * 00480 * @return Returns -1 if the service cannot be 'loaded'. 00481 */ 00482 static int process_directive (const ACE_Static_Svc_Descriptor &ssd, 00483 int force_replace = 0); 00484 00485 /** 00486 * Process (or re-process) service configuration requests that are 00487 * provided in the svc.conf file(s). Returns the number of errors 00488 * that occurred. 00489 */ 00490 static int process_directives (void); 00491 00492 /// Handles signals to trigger reconfigurations. 00493 static void handle_signal (int sig, siginfo_t *, ucontext_t *); 00494 00495 /** 00496 * Handle the command-line options intended for the 00497 * ACE_Service_Config. Note that @c argv[0] is assumed to be the 00498 * program name. 00499 * The arguments that are valid in a call to this method are 00500 * - '-b' Option to indicate that we should be a daemon 00501 * - '-d' Turn on debugging mode 00502 * - '-f' Option to read in the list of svc.conf file names 00503 * - '-k' Option to read a wide string where in the logger output can 00504 * be written 00505 * - '-y' Turn on the flag for a repository of statically 00506 * linked services 00507 * - '-n' Need not have a repository of statically linked services 00508 * - '-S' Option to read in the list of services on the command-line 00509 * Please observe the difference between options '-f' that looks 00510 * for a list of files and here a list of services. 00511 */ 00512 static int parse_args (int, ACE_TCHAR *argv[]); 00513 #if (ACE_USES_CLASSIC_SVC_CONF == 0) 00514 static ACE_Service_Type *create_service_type (const ACE_TCHAR *n, 00515 ACE_Service_Type_Impl *o, 00516 ACE_DLL &dll, 00517 int active); 00518 #endif /* ACE_USES_CLASSIC_SVC_CONF == 0 */ 00519 00520 static ACE_Service_Type_Impl * 00521 create_service_type_impl (const ACE_TCHAR *name, 00522 int type, 00523 void *symbol, 00524 u_int flags, 00525 ACE_Service_Object_Exterminator gobbler); 00526 00527 protected: 00528 00529 /// Process service configuration requests that were provided on the 00530 /// command-line. Returns the number of errors that occurred. 00531 static int process_commandline_directives (void); 00532 00533 #if (ACE_USES_CLASSIC_SVC_CONF == 1) 00534 /// This is the implementation function that process_directives() 00535 /// and process_directive() both call. Returns the number of errors 00536 /// that occurred. 00537 static int process_directives_i (ACE_Svc_Conf_Param *param); 00538 #else 00539 /// Helper function to dynamically link in the XML Service Configurator 00540 /// parser. 00541 static ACE_XML_Svc_Conf *get_xml_svc_conf (ACE_DLL &d); 00542 #endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */ 00543 00544 /// Become a daemon. 00545 static int start_daemon (void); 00546 00547 /// Add the default statically-linked services to the 00548 /// ACE_Service_Repository. 00549 static int load_static_svcs (void); 00550 00551 00552 private: 00553 00554 /// True if reconfiguration occurred. 00555 static sig_atomic_t reconfig_occurred_; 00556 00557 // = Set by command-line options. 00558 /// Shall we become a daemon process? 00559 static int be_a_daemon_; 00560 00561 /// Pathname of file to write process id. 00562 static ACE_TCHAR *pid_file_name_; 00563 00564 /// Number of the signal used to trigger reconfiguration. 00565 static int signum_; 00566 00567 /// Handles the reconfiguration signals. 00568 static ACE_Sig_Adapter *signal_handler_; 00569 00570 /// Pointer to the Singleton (ACE_Cleanup) Gestalt instance. 00571 /// There is thread-specific global instance pointer, which is used to 00572 /// temporarily change which Gestalt instance is used for static service 00573 /// registrations. 00574 /// 00575 /// A specific use case is a thread, which loads a _dynamic_ service from 00576 /// a DLL. If the said DLL also contains additional _static_ services, 00577 /// those *must* be registered with the same configuration repository as 00578 /// the dynamic service. Otherwise, the DLL's static services would be 00579 /// registered with the global Gestalt and may outlive the DLL that 00580 /// contains their code and perhaps the memory in which they are in. 00581 /// This is a problem because if the DLL gets unloaded (as it will, if 00582 /// it was loaded in an instance of Gestalt), the DLL's memory will be 00583 /// deallocated, but the global service repository will still "think" 00584 /// it must finalize the (DLL's) static services - with disastrous 00585 /// consequences, occurring in the post-main code (at_exit()). 00586 00587 /// This class needs the intimate access to be able to swap the 00588 /// current TSS pointer for the global Gestalt. 00589 friend class ACE_Service_Config_Guard; 00590 }; 00591 00592 /** 00593 * @class ACE_Service_Config_Guard 00594 * 00595 * @brief A guard class, designed to be instantiated on the stack. 00596 * 00597 * Instantiating it with a specific configuration ensures any references to 00598 * ACE_Service_Config::instance(), even when occuring in static constructors, 00599 * will allways access the designated configuration instance. 00600 * This comes very handy when a dynamic service also registers any static 00601 * services of its own and their static factories. 00602 */ 00603 class ACE_Export ACE_Service_Config_Guard 00604 { 00605 public: 00606 ACE_Service_Config_Guard (ACE_Service_Gestalt * psg); 00607 ~ACE_Service_Config_Guard (void); 00608 00609 private: 00610 // Private AND not implemented to disable copying 00611 ACE_Service_Config_Guard(const ACE_Service_Config_Guard&); 00612 ACE_Service_Config_Guard& operator= (const ACE_Service_Config_Guard&); 00613 00614 private: 00615 ACE_Service_Gestalt* saved_; 00616 }; 00617 00618 00619 ACE_END_VERSIONED_NAMESPACE_DECL 00620 00621 #if defined (__ACE_INLINE__) 00622 #include "ace/Service_Config.inl" 00623 #endif /* __ACE_INLINE__ */ 00624 00625 00626 #include /**/ "ace/post.h" 00627 00628 #endif /* ACE_SERVICE_CONFIG_H */