Reputation: 193
I have a Logger
singleton class that its purpose is to print messages to log file / screen.
This Logger has some configurations that he wants to read from configuration file. Here is the constructor of Logger:
Logger::Logger(const std::string& confFilePath) {
m_logConf = new LogConfig(confFilePath);
...
}
Class LogConfig
uses Configuration Object that knows how to parse a configuration file. Here is the class Ctor
:
LogConfig::LogConfig(const std::string& confFilePath) {
m_config = new Configuration(confFilePath);
...
m_config->ParseConfFile();
}
The problem is that in ParseConfFile
method - Configuration object may want to write to the log and use Logger singleton class. But, when it tries to do it - he will enter again to Logger constructor, and then to LogConfig Ctor and there is an infinite cycle.
I don't want to forbid Configuration class to write to the log (LogConfig
is not the only class that uses it).
How can I solve this cycle problem?
Upvotes: 1
Views: 147
Reputation: 691
Since Logger
is a singleton, supposedly all classes (including Configuration
) access it through a static method(say getInctance()
), and Logger
's constructor is private. The right approach would be to simplify Logger's construction to bare minimum and move the setup/configuration logic from the constructor to getInstance()
.
Something like:
static Logger* Logger::getInstance() {
if (m_logger == nullptr) {
m_logger = new Logger(); // remove configuration path passing from the constructor
m_logger->setConfigPath(const std::string& confFilePath); // ok trying to write to Logger, at least from the perspective of not being stuck in construction loop
}
return m_logger;
}
Although the behavior in this situation still needs to be defined, since the Logger is not fully initialized when Configuration tries wryting to it.
One approach would be to throw an exception or write an error message to the standard output when someone wants to use Logger
before it's fully initialized.
Upvotes: 2
Reputation: 11968
Initialize the logger with a bare minimum so you don't need the configuration at all. Then when you have the configuration replace the logger.
If the config reader needs to log anything it will go to the bare minimum logger so you should at least dump it to stderr.
Also if you are in a multi-threaded environment make sure you use a shared_ptr and do an atomic swap to replace it with the propper one (in case some other module is logging when you need to swap).
Upvotes: 3