deal with static constructor problem

This commit is contained in:
Craig Dowell
2007-10-12 13:41:24 -07:00
parent 73e9110b64
commit 9a7694f32a
2 changed files with 66 additions and 18 deletions

View File

@@ -48,10 +48,44 @@ void
LogComponentEnableEnvVar (void)
{
static bool isFirstLog = true;
#if 0
//
// Interesting static constructor bug:
//
// The RandomDirection2dMobilityModel declares a RandomVariableDefaultValue
// g_speedVariable. This variable is initialized in the
// static_initialization_and_destruction_0 function as expected. This causes
// RandomVariableDefaultValue::Parse () to be called which calls NS_LOG_X
// functions. The macro calls LogComponent::IsEnabled () which calls
// LogComponentEnableEnvVar (). The following variable called isFirstLog
// is set after the first call to prevent the environment variable from
// actually being parsed on every log call.
//
// When the RandomDirection2dMobilityModel static constructor is run, other
// log components may not have had their static constructors run yet. It is
// in those other static constructors that their log components are added to
// the list of log components.
//
// The end result is that if any code calls an NS_LOG_X function during its
// static constructor, the environment variable check is "locked out" for
// any log component declarations (in different compilation units) that have
// not yet been executed.
//
// So, the choice seems to be to either 1) parse the environment variables
// at every log call; or 2) make LogComponentEnableEnvVar explicitly called
// after all other static constructors are called. This means in main ().
// The former choice seems the only reasonable way out if we care remotely
// about performance in logging.
//
// I made LogComponentEnableEnvVar a public API that you need to call in
// main () if you want to use environment variables to drive the log output.
//
if (!isFirstLog)
{
return;
}
#endif // 0
#ifdef HAVE_GETENV
char *envVar = getenv("NS_LOG");
if (envVar == 0)
@@ -142,6 +176,10 @@ LogComponentEnableEnvVar (void)
{
level |= LOG_ALL;
}
else if (lev == "prefix")
{
level |= LOG_PREFIX_ALL;
}
else if (lev == "level_error")
{
level |= LOG_LEVEL_ERROR;
@@ -236,7 +274,7 @@ LogComponent::LogComponent (char const * name)
bool
LogComponent::IsEnabled (enum LogLevel level) const
{
LogComponentEnableEnvVar ();
// LogComponentEnableEnvVar ();
return (level & m_levels) ? 1 : 0;
}

View File

@@ -32,22 +32,8 @@
* send information out on screen. All logging messages
* are disabled by default. To enable selected logging
* messages, use the ns3::LogComponentEnable
* function.
*
* Alternatively, you can use the NS_LOG
* environment variable to define a ';'-separated list of
* logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
* would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
*
* For each component, the "debug" log level is enabled by default
* but more components can be enabled selectively with the following
* syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
* This example would enable the 'func', 'param', and 'warn' log
* levels for 'Component1' and the 'error' and 'debug' log levels
* for 'Component2'.
*
* The list of available log components can be printed on stdout
* with the NS_LOG=print-list syntax.
* function or use the NS_LOG environment variable and
* ns3::LogComponentEnableEnvVar
*/
/**
@@ -187,12 +173,34 @@ enum LogLevel {
LOG_ALL = 0x7fffffff, // print everything
LOG_LEVEL_ALL = LOG_ALL,
LOG_PREFIX_ALL = 0x80000000
LOG_PREFIX_ALL = 0x80000000 // prefix all trace prints with function
};
#endif
#ifdef NS3_LOG_ENABLE
/**
* \brief Enable the logging output based on an environment variable.
*
* Use the environment variable NS_LOG to define a ';'-separated list of
* logging components to enable. For example, NS_LOG=a;b;c;DAFD;GH
* would enable the components 'a', 'b', 'c', 'DAFD', and, 'GH'.
* NS_LOG=* will enable all available log components.
*
* For each component, the "debug" log level is enabled by default
* but more components can be enabled selectively with the following
* syntax: NS_LOG='Component1=func|param|warn;Component2=error|debug'
* This example would enable the 'func', 'param', and 'warn' log
* levels for 'Component1' and the 'error' and 'debug' log levels
* for 'Component2'. The wildcard can be used here as well. For example
* NS_LOG='*=level_all|prefix' would enable all log levels and prefix all
* prints with the component and function names.
*
* The list of available log components can be printed on stdout
* with the NS_LOG=print-list syntax.
*/
void LogComponentEnableEnvVar (void);
/**
* \param name a log component name
* \param level a logging level
@@ -204,6 +212,7 @@ enum LogLevel {
* to ns3::LogComponentDisable.
*/
void LogComponentEnable (char const *name, enum LogLevel level);
/**
* \param level a logging level
* \param decorate whether or not to add function names to all logs
@@ -213,6 +222,7 @@ enum LogLevel {
*/
void LogComponentEnableAll (enum LogLevel level);
#else
#define LogComponentEnableEnvVar()
#define LogComponentEnable(a,b)
#define LogComponentEnableAll(a)
#endif