需要知道如何检查输入的字符串是否已在 C++ 中的线程安全记录器内终止;

发布于 2024-09-16 04:16:14 字数 571 浏览 3 评论 0原文

我对此很陌生,如果我的问题不清楚,我深表歉意。

我用 C++ 创建了一个线程安全记录器。该记录器将在大型程序中使用将从多个地方调用。我使用的是单例,因此只有一个记录器实例。该记录器输出到文件&到控制台。它的行为类似于 cout;它从另一个文件中获取一个字符串(如果需要,将其连接起来),将这些片段存储在缓冲区中,直到字符串完成,然后使用 cout 输出。该字符串被存储为 const char*。现在,互斥锁被锁定在一个函数中,并在另一个函数中解锁(这是我的问题),这会重载 endl 运算符。

我的问题是,只有当用户在调用记录器的其他文件中写入 endl 时,此函数(互斥锁被解锁)才有效。我需要它成为一个多功能实用程序,它不会依赖于用户编写的内容,因为用户可能不使用 endl 或者可能使用它太频繁。我现在需要一些方法让我的记录器识别字符串(来自其他文件)何时完成,以便它可以清空缓冲区。目前 endl 就像一个关键字 &我需要一些方法让它在没有任何关键词的情况下工作。

我最初认为我可以找到一些方法来检查字符串中的“\0”终止字符,然后使用该检查来知道字符串是否已完成,然后清空缓冲区。但是,当我这样做时,我遇到了越界错误。

谢谢您的宝贵时间

I am very new at this and apologise if my question is not clear.

I have created a thread safe logger in C++. This logger will be used in a large program & will be called from multiple places. I am using a singleton so there is only one instance of the logger. This logger outputs to a file & to the console. It behaves similar to cout; it takes in a string from another file, ( concatenates it if necessary), stores the peices in a buffer until the string is done then outputs using cout. The string is being stored as a const char*. Right now the mutexes are being locked in one function and unlocked in another function ( this is were my problem is) which overloads the endl operator.

My problem is that this function (where the mutexes are unlocked )only works if the user writes endl in the other files where the logger is being called. I need this to be a versatile utility which will NOT rely on what the user writes since a user may not use endl or may use it too often. I now need some means for my logger to identify when the string ( from the other file) is done so that it can empty out the buffer. Currently endl is like a keyword & i need some means to make it work without any key words.

I was initially thinking i could find some means to check for the "\0" terminating character in the string then using that check to know that the string is done and then emptying out the buffer. However, i get out of bounds errors when i do this.

Thank you for your time

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

谈场末日恋爱 2024-09-23 04:16:14

我不太确定我明白这种情况,但听起来你想要一个代理:

class LogSingleton
{
public:
    LogSingleton& instance() { /* ... */ }

    void lock(); // lock mutex
    void unlock(); // unlock mutex

    template <typename T>
    friend LogSingleton& operator<<(LogSingleton& pLog, const T& pX)
    {
        // needs to be locked first
        assert(is_locked()); 

        /* output pX however */

        return pLog;
    }
};

class LogProxy
{
public:
    LogProxy()
    {
        // manage lock in proxy
        LogSingleton::instance().lock();            
    }

    ~LogProxy()
    {
        LogSingleton::instance().unlock();            
    }
};

// forward input into the proxy to the log, knowing it's locked
template <typename T>
LogProxy& operator<<(LogProxy& pProxy, const T& pX)
{
    LogSingleton::instance() << pX;

    return pProxy;
}

// now expose proxy
typedef LogProxy log;

你会这样做:

log() << "its locked now" << "and the temporary will die" << "here ->";

锁定在构造函数和析构函数中完成,并在最后调用析构函数。


正如托尼正确指出的那样,这不必要地延长了锁的时间。仅当“最终”输出到 LogSingleton 时才需要锁定。想象一下:

log() << "this next function takes 5 minutes"
        << my_utterly_crappy_function() << "ouch";

没有记录任何内容,但互斥锁已锁定很长时间。更好的方法是缓冲输出,然后立即输出:

class LogProxy
{
public:
    ~LogProxy()
    {
        // manage lock in proxy
        LogSingleton::instance().lock();

        // no-throw, or wrap mutex use in a scoped-lock
        LogSingleton::instance() << mBuffer.rdbuf();

        LogSingleton::instance().unlock();            
    }

    // buffer output
    template <typename T>
    friend LogProxy& operator<<(LogProxy& pProxy, const T& pX)
    {
        mBuffer << pX;

        return pProxy;
    }

private:
    std::ostringstream mBuffer;
};

现在,在缓冲区准备好输出之前不会获取锁。

I'm not quite sure I get the situation, but it sounds like you want a proxy:

class LogSingleton
{
public:
    LogSingleton& instance() { /* ... */ }

    void lock(); // lock mutex
    void unlock(); // unlock mutex

    template <typename T>
    friend LogSingleton& operator<<(LogSingleton& pLog, const T& pX)
    {
        // needs to be locked first
        assert(is_locked()); 

        /* output pX however */

        return pLog;
    }
};

class LogProxy
{
public:
    LogProxy()
    {
        // manage lock in proxy
        LogSingleton::instance().lock();            
    }

    ~LogProxy()
    {
        LogSingleton::instance().unlock();            
    }
};

// forward input into the proxy to the log, knowing it's locked
template <typename T>
LogProxy& operator<<(LogProxy& pProxy, const T& pX)
{
    LogSingleton::instance() << pX;

    return pProxy;
}

// now expose proxy
typedef LogProxy log;

And you'd do this:

log() << "its locked now" << "and the temporary will die" << "here ->";

The locking is done in the constructor and destructor, and the destructor is called at the end.


As Tony correctly points out, this holds the lock unnecessarily long. The lock is only needed for the "final" output to the LogSingleton. Imagine this:

log() << "this next function takes 5 minutes"
        << my_utterly_crappy_function() << "ouch";

Nothings getting logged yet the mutex is locked for a long time. Better would be to buffer-up output then output it all at once:

class LogProxy
{
public:
    ~LogProxy()
    {
        // manage lock in proxy
        LogSingleton::instance().lock();

        // no-throw, or wrap mutex use in a scoped-lock
        LogSingleton::instance() << mBuffer.rdbuf();

        LogSingleton::instance().unlock();            
    }

    // buffer output
    template <typename T>
    friend LogProxy& operator<<(LogProxy& pProxy, const T& pX)
    {
        mBuffer << pX;

        return pProxy;
    }

private:
    std::ostringstream mBuffer;
};

Now no locks are acquired until the buffer is ready to be outputted.

野侃 2024-09-23 04:16:14

通常,在一个函数中锁定互斥体并在另一个函数中解锁是一个坏主意。应在同一功能中锁定和解锁。

我创建了类似的东西,通常我创建了一个名为 Error 的 C++ 类。

这样,用户创建一个 Error 对象,并且该错误对象处理所有终止内容。然后错误对象被发送到 ErrorLogger 的队列,并且当 ErrorLogger 队列为空时错误记录器终止。那么你就不必担心互斥体,因为ErrorLogger有时间处理队列外的事情。

Typically it's a bad idea to have mutex lock in one function and unlock in another. It should be locked and unlocked in the same function.

I created something similar, and typically I made a C++ class called Error.

That way the user creates an Error object, and that error object handles all the termination stuff. Then the error object gets sent to the ErrorLogger's Queue, and the error logger terminates when the ErrorLogger Queue is empty. Then you don't have to worry about mutexes, because the ErrorLogger has time to process out of the queue.

零時差 2024-09-23 04:16:14

查看
https:// web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-5072104.html

这个想法是创建线程本地“代理”,它将调用实际的线程-安全记录功能。

Check
https://web.archive.org/web/1/http://articles.techrepublic%2ecom%2ecom/5100-10878_11-5072104.html

The idea is to create thread-local "proxies" which will call actual thread-safe logging function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文