Класс логгера с использованием потоков [многопоточный] - PullRequest
1 голос
/ 09 апреля 2020

У меня есть класс регистрации в C ++. Это синглтон с поддержкой многопоточности.

То, чего я хотел достичь (и в основном достиг):

  • имеет универсальный c класс регистратора
  • синглтон
  • используйте его с оператором вставки потока, а не как вызов функции

Класс записывает в std :: stringstream, а в std :: endl сбрасывает содержимое std :: stringstream в файл. Большим недостатком является то, что std :: endl требуется один раз и только один раз за вызов, чтобы все работало правильно в многопоточном приложении. не уверен, что это хороший подход, но пока это нормально, и в моем случае я могу go с этим недостатком

Моя проблема в том, что вызов std :: setfill () при входе в систему тупик. Похоже, этот вызов не отправляется моему классу Logger и выполняется за пределами его критической секции.

Можно ли этого добиться? Класс логгера с полной поддержкой manips?

Журнал вызовов

LOGI << "Some message " << aVariable << std::endl;                // OK
LOGI << std::setw(20) << var << std::endl                         // OK
LOGI << std::setfill('-') << std::setw(50) << var << std::endl;   // NOT OK because of setfill() call !!!!

Пример кода класса

#define LOGFATAL Logger::GetLogger(LOGLEVEL_FATAL,      __FUNCTION__)
#define LOGE     Logger::GetLogger(LOGLEVEL_ERROR,      __FUNCTION__)
#define LOGW     Logger::GetLogger(LOGLEVEL_WARN,       __FUNCTION__)
#define LOGI     Logger::GetLogger(LOGLEVEL_INFO,       __FUNCTION__)
#define LOGD     Logger::GetLogger(LOGLEVEL_DEBUG,      __FUNCTION__)
#define LOGV     Logger::GetLogger(LOGLEVEL_VERBOSE,    __FUNCTION__)

class Logger
{
public:
    static void Initialize(const std::string& _logFile, const std::string& _logLevel)
    {
        isInitialized = true;
        logFileName = _logFile;
        logLevel = GetLogLevel(_logLevel);
    }
    static Logger& GetLogger(LogLevel l, const std::string& funcName)
    {
        if(isInitialized)
            csFile->lock();

        msgLogLevel = l;
        functionName = funcName;
        return GetLogger();
    }

    typedef std::ostream&  (*ManipFn)(std::ostream&);
    typedef std::ios_base& (*FlagsFn)(std::ios_base&);

    template<class T>
    Logger& operator<<(const T& output)
    {
        if (!isInitialized)
            return *this;

        m_stream << output;
        return *this;
    }

    Logger& operator<<(const ManipFn manip)
    {
        if (!isInitialized)
            return *this;

        manip(m_stream);

        if (manip == static_cast<ManipFn>(std::flush) ||
            manip == static_cast<ManipFn>(std::endl))
        {
            // flush the stream and unlock the mutex
            this->flush();
            csFile->unlock();
        }
        return *this;
    }

    Logger& operator<<(const FlagsFn manip) /// setiosflags, resetiosflags
    {
        manip(m_stream);
        return *this;
    }
...
    static Logger& GetLogger()
    {
        static Logger instance;
        return instance;
    }


Дайте мне знать, если потребуется дополнительная информация

1 Ответ

0 голосов
/ 09 апреля 2020

Я пропустил свои собственные слова, свои проблемы с кодом и ограничения (о которых я знал, когда отправлял вопрос). Моя ошибка не состояла в том, чтобы опубликовать исходный код, который заблокировал мой процесс. Вот код:

LOGV << std::setfill('-') << std::setw(206) << '-' << std::endl;
LOGV << std::setfill(' ');

Процитирую себя: «Большой недостаток в том, что std :: endl требуется один раз и только один раз за вызов, чтобы все работало правильно в многопоточном приложении».

Итак, исправление для моей проблемы: LOGV << std::setfill('-') << std::setw(206) << '-' << std::setfill(' ') << std::endl;

Извините, что больше не регистрируюсь и тратить время впустую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...