binyamina
binyamina

Reputation: 193

Constructors infinite cycle in cpp

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

Answers (2)

nVxx
nVxx

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

Sorin
Sorin

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

Related Questions