summaryrefslogtreecommitdiff
path: root/ace/Service_Config.h
diff options
context:
space:
mode:
Diffstat (limited to 'ace/Service_Config.h')
-rw-r--r--ace/Service_Config.h237
1 files changed, 166 insertions, 71 deletions
diff --git a/ace/Service_Config.h b/ace/Service_Config.h
index 6fafb50408b..82b988d69d6 100644
--- a/ace/Service_Config.h
+++ b/ace/Service_Config.h
@@ -17,13 +17,12 @@
#include "ace/config-all.h"
#include "ace/Default_Constants.h"
+#include "ace/Service_Gestalt.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
-#include "ace/Unbounded_Queue.h"
-#include "ace/Unbounded_Set.h"
#include "ace/SString.h"
#include "ace/OS_NS_signal.h"
@@ -134,20 +133,8 @@ public:
bool operator!= (ACE_Static_Svc_Descriptor &) const;
};
-// Maintain a set of the statically linked service descriptors.
-typedef ACE_Unbounded_Set<ACE_Static_Svc_Descriptor *>
- ACE_STATIC_SVCS;
-typedef ACE_Unbounded_Set_Iterator<ACE_Static_Svc_Descriptor *>
- ACE_STATIC_SVCS_ITERATOR;
-
-// Maintain a queue of services to be configured from the
-// command-line.
-typedef ACE_Unbounded_Queue<ACE_TString>
- ACE_SVC_QUEUE;
-typedef ACE_Unbounded_Queue_Iterator<ACE_TString>
- ACE_SVC_QUEUE_ITERATOR;
-
#define ACE_Component_Config ACE_Service_Config
+
/**
* @class ACE_Service_Config
*
@@ -155,7 +142,22 @@ typedef ACE_Unbounded_Queue_Iterator<ACE_TString>
* configuration of services.
*
* The ACE_Service_Config uses the Monostate pattern. Therefore,
- * you can only have one of these instantiated per-process.
+ * you can only have one of these instantiated per-process. It
+ * represents the process-wide collection of services, which is
+ * typicaly shared among all other configurable entities. The only
+ * ACE_Service_Config instance is registered with and owned by the
+ * ACE_Object_Manager.
+ *
+ * By contrast, the ACE_Service_Gestalt represents the collection
+ * of services, pertaining to a configurable entity. Typicaly, a
+ * "configurable entity" is an instance, which owns an instance of
+ * ACE_Service_Gestalt in order to ensure full controll over the
+ * services it needs.
+ *
+ * Another facet of ACE_Service_Config is that for a given thread,
+ * it provides access to its current, process-global
+ * ACE_Service_Gestalt instance through its curent() method.
+ *
* @note The signal_handler_ static member is allocated by the
* ACE_Object_Manager. The ACE_Service_Config constructor
* uses signal_handler_. Therefore, if the program has any
@@ -164,13 +166,9 @@ typedef ACE_Unbounded_Queue_Iterator<ACE_TString>
* not eliminated, by _not_ #defining
* ACE_HAS_NONSTATIC_OBJECT_MANAGER.
*/
-class ACE_Export ACE_Service_Config
+class ACE_Export ACE_Service_Config: public ACE_Service_Gestalt
{
public:
- enum
- {
- MAX_SERVICES = ACE_DEFAULT_SERVICE_REPOSITORY_SIZE
- };
// = Initialization and termination methods.
@@ -180,7 +178,7 @@ public:
* registered when the repository is opened.
*/
ACE_Service_Config (int ignore_static_svcs = 1,
- size_t size = ACE_Service_Config::MAX_SERVICES,
+ size_t size = ACE_Service_Gestalt::MAX_SERVICES,
int signum = SIGHUP);
/**
@@ -191,9 +189,19 @@ public:
ACE_Service_Config (const ACE_TCHAR program_name[],
const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY);
+ /// Perform user-specified close activities and remove dynamic
+ /// memory.
+ virtual ~ACE_Service_Config (void);
+
+
+protected:
+
/**
- * Performs an open without parsing command-line arguments. The
- * @a logger_key indicates where to write the logging output, which
+ * Performs an open without parsing command-line arguments.
+ * Implements whats different in the opening sequence
+ * for this class, as opposed to the base class.
+ *
+ * The @a logger_key indicates where to write the logging output, which
* is typically either a STREAM pipe or a socket address. If
* @a ignore_default_svc_conf_file is non-0 then the "svc.conf" file
* will be ignored. If @a ignore_debug_flag is non-0 then the
@@ -201,12 +209,56 @@ public:
* @c ACE_Log_Msg::priority_mask() appropriately. Returns number of
* errors that occurred on failure and 0 otherwise.
*/
- static int open_i (const ACE_TCHAR program_name[],
- const ACE_TCHAR *logger_key = ACE_DEFAULT_LOGGER_KEY,
- int ignore_default_svc_conf_file = 0,
- int ignore_debug_flag = 0);
+ virtual int open_i (const ACE_TCHAR program_name[],
+ const ACE_TCHAR *logger_key,
+ bool ignore_static_svcs,
+ bool ignore_default_svc_conf_file,
+ bool ignore_debug_flag);
/**
+ * Implements whats different in the command line parameter processing
+ * for this class, as opposed to the base class.
+ */
+ virtual int parse_args_i (int argc, ACE_TCHAR *argv[]);
+
+
+
+ /// = Static interfaces
+
+
+
+protected:
+
+ /// Mutator to set the (TSS) global instance. Intended for use by helper
+ /// classes, like ACE_Service_Config_Guard which when instantiated on the
+ /// stack, can temporarily change which gestalt instance is viewed as
+ /// global from the point of view of the static initializers in DLLs.
+ static int current (ACE_Service_Gestalt*);
+
+
+public:
+
+ /// If not yet initialized, creates a process-wide instance
+ /// global instance, which is registered with the ACE_Object_Manager,
+ /// via ACE_Singleton. Note that this is allways the same instance,
+ /// in contrast with current (), which may be different instance at
+ /// different times, dependent on the context.
+ static ACE_Service_Gestalt* global (void);
+
+
+ /// Accessor for the "current" service repository through a pointer
+ /// held in TSS.
+ static ACE_Service_Gestalt* current (void);
+
+ /// This is what the static service initializators are hard-wired
+ /// to use, so in order to keep interface changes to a minimum this
+ /// method merely forwards to current(). Thus it is possible to
+ /// temporarily replace what those initializers think is the global
+ /// service repository, for instance when dynamically loading a
+ /// service from a DLL, which in turn, contains its own static services.
+ static ACE_Service_Gestalt* instance (void);
+
+ /**
* Performs an open without parsing command-line arguments. The
* @a logger_key indicates where to write the logging output, which
* is typically either a STREAM pipe or a socket address. If
@@ -283,10 +335,6 @@ public:
int ignore_default_svc_conf_file = 0,
int ignore_debug_flag = 0);
- /// Perform user-specified close activities and remove dynamic
- /// memory.
- virtual ~ACE_Service_Config (void);
-
/// Tidy up and perform last rites when ACE_Service_Config is shut
/// down. This method calls <close_svcs>. Returns 0.
static int close (void);
@@ -315,11 +363,31 @@ public:
// semantics for the Reactor, Service_Repository, Thread_Manager,
// and Acceptor/Connector Strategy factory. Other portions of the
// system may need to access them at some point or another...
+
+ // = This is not strictly needed, anymore since the service configurator
+ // has been refactored to allow multiple service configuration
+ // instances (called gestalts). The interfaces, however were retained in for
+ // the sake of maintaining source-code compatibility.
+
// = Accessors and mutators for process-wide Singletons.
/// Returns a pointer to the list of statically linked services.
- static ACE_STATIC_SVCS *static_svcs (void);
+ ///
+ /// @deprecated - Same as instance(), but still useful in legacy code,
+ /// (notably, one that can not be easily modified) which uses the following
+ /// idiom for registering static services:
+ ///
+ /// ACE_Service_Config::static_svcs ()->insert (...);
+ static ACE_Service_Gestalt *static_svcs (void);
+
+ /// Insert a static service descriptor for processing on open_i(). The
+ /// corresponding ACE_STATIC_SVC_* macros were chaged to use this method
+ /// instead of obtaining a ptr to a container. See the note on static_svcs().
+ /// Added to prevent exposing the internal storage representation of the
+ /// services repository and provide a better way of debugging service
+ /// loading and registration problems.
+ static int insert (ACE_Static_Svc_Descriptor *svc);
// = Utility methods.
/// Dynamically link the shared object file and retrieve a pointer to
@@ -352,11 +420,11 @@ public:
#if defined (ACE_HAS_WINCE) && defined (ACE_USES_WCHAR)
// We must provide these function to bridge the Svc_Conf parser
// with ACE.
- static int initialize (const ACE_Service_Type *, char parameters[]);
- static int initialize (const char svc_name[], char parameters[]);
- static int resume (const char svc_name[]);
- static int suspend (const char svc_name[]);
- static int remove (const char svc_name[]);
+ static int initialize (const ACE_Service_Type *, ACE_ANTI_TCHAR []);
+ static int initialize (const char svc_name[], ACE_ANTI_TCHAR parameters[]);
+ static int resume (const ACE_ANTI_TCHAR svc_name[]);
+ static int suspend (const ACE_ANTI_TCHAR svc_name[]);
+ static int remove (const ACE_ANTI_TCHAR svc_name[]);
#endif /* ACE_HAS_WINCE */
/// Dump the state of an object.
@@ -426,12 +494,15 @@ public:
int active);
#endif /* ACE_USES_CLASSIC_SVC_CONF == 0 */
- static ACE_Service_Type_Impl *create_service_type_impl (const ACE_TCHAR *name,
- int type,
- void *symbol,
- u_int flags,
- ACE_Service_Object_Exterminator gobbler);
+ static ACE_Service_Type_Impl *
+ create_service_type_impl (const ACE_TCHAR *name,
+ int type,
+ void *symbol,
+ u_int flags,
+ ACE_Service_Object_Exterminator gobbler);
+
protected:
+
/// Process service configuration requests that were provided on the
/// command-line. Returns the number of errors that occurred.
static int process_commandline_directives (void);
@@ -442,7 +513,8 @@ protected:
/// that occurred.
static int process_directives_i (ACE_Svc_Conf_Param *param);
#else
- /// Helper function to dynamically link in the XML Service Configurator parser.
+ /// Helper function to dynamically link in the XML Service Configurator
+ /// parser.
static ACE_XML_Svc_Conf *get_xml_svc_conf (ACE_DLL &d);
#endif /* ACE_USES_CLASSIC_SVC_CONF == 1 */
@@ -453,23 +525,8 @@ protected:
/// ACE_Service_Repository.
static int load_static_svcs (void);
+
private:
- /// Indicates where to write the logging output. This is typically
- /// either a STREAM pipe or a socket address.
- static const ACE_TCHAR *logger_key_;
-
- /// Singleton repository of statically linked services.
- static ACE_STATIC_SVCS *static_svcs_;
-
- /// Queue of services specified on the command-line.
- static ACE_SVC_QUEUE *svc_queue_;
-
- /// Queue of svc.conf files specified on the command-line.
- /// @@ This should probably be made to handle unicode filenames...
- static ACE_SVC_QUEUE *svc_conf_file_queue_;
-
- /// Initialize the <svc_conf_file_queue_> if necessary.
- static int init_svc_conf_file_queue (void);
/// True if reconfiguration occurred.
static sig_atomic_t reconfig_occurred_;
@@ -481,25 +538,63 @@ private:
/// Pathname of file to write process id.
static ACE_TCHAR *pid_file_name_;
- /// Should we avoid loading the static services?
- static int no_static_svcs_;
-
/// Number of the signal used to trigger reconfiguration.
static int signum_;
/// Handles the reconfiguration signals.
static ACE_Sig_Adapter *signal_handler_;
- /**
- * Keep track of whether the ACE_Service_Config is already
- * initialized. If so, we can't allow <yyparse> to be called since
- * it's not reentrant. This variable is incremented by the
- * <ACE_Service_Config::open> method and decremented by the
- * <ACE_Service_Config::close> method.
- */
- static int is_initialized_;
+ /// Pointer to the Singleton (ACE_Cleanup) Gestalt instance.
+ /// There is thread-specific global instance pointer, which is used to
+ /// temporarily change which Gestalt instance is used for static service
+ /// registrations.
+ ///
+ /// A specific use case is a thread, which loads a _dynamic_ service from
+ /// a DLL. If the said DLL also contains additional _static_ services,
+ /// those *must* be registered with the same configuration repository as
+ /// the dynamic service. Otherwise, the DLL's static services would be
+ /// registered with the global Gestalt and may outlive the DLL that
+ /// contains their code and perhaps the memory in which they are in.
+ /// This is a problem because if the DLL gets unloaded (as it will, if
+ /// it was loaded in an instance of Gestalt), the DLL's memory will be
+ /// deallocated, but the global service repository will still "think"
+ /// it must finalize the (DLL's) static services - with disastrous
+ /// consequences, occurring in the post-main code (at_exit()).
+ static ACE_TSS< ACE_TSS_Type_Adapter <ACE_Service_Gestalt*> > current_;
+
+ /// This class needs the intimate access to be able to swap the
+ /// current TSS pointer for the global Gestalt.
+ friend class ACE_Service_Config_Guard;
+
+};
+
+/**
+ * @class ACE_Service_Config_Guard
+ *
+ * @brief A guard class, designed to be instantiated on the stack.
+ *
+ * Instantiating it with a specific configuration ensures any references to
+ * ACE_Service_Config::instance(), even when occuring in static constructors,
+ * will allways access the designated configuration instance.
+ * This comes very handy when a dynamic service also registers any static
+ * services of its own and their static factories.
+ */
+class ACE_Export ACE_Service_Config_Guard
+{
+public:
+ ACE_Service_Config_Guard (ACE_Service_Gestalt * psg);
+ ~ACE_Service_Config_Guard (void);
+
+private:
+ // Private AND not implemented to disable copying
+ ACE_Service_Config_Guard(const ACE_Service_Config_Guard&);
+ ACE_Service_Config_Guard& operator= (const ACE_Service_Config_Guard&);
+
+private:
+ ACE_Service_Gestalt* saved_;
};
+
ACE_END_VERSIONED_NAMESPACE_DECL
#if defined (__ACE_INLINE__)