使用 boost 轮询状态更改时如何同步线程

发布于 2024-07-14 23:20:43 字数 2113 浏览 3 评论 0原文

在我的应用程序中,我希望通过事件通知另一个应用程序已启动或停止。 我有一个正在运行的应用程序的现有 API无法更改来容纳通知,这将是显而易见的解决方案。

我拥有的是 API 中的函数调用(isRunning),因此我决定创建一个轮询线程,通过 API 轮询状态并通知我的应用程序。

我现在的问题是,轮询线程中的 API 调用使用的对象也在我自己的应用程序的主线程中使用,我想知道如何确保我做得正确:)。

我的想法是用互斥锁包装对 API 对象的每次调用(通过适配器,例如,参见第二个代码块),因此我确信我的线程不会多次调用该 API。

这是正确的方法吗?

我正在使用 boost 进行线程/同步(参见代码)。

这是轮询线程:

void EventCreator::start()
{
    stop();
    m_bShouldRun = true;    
    m_spThread = BoostThreadPtr(new thread(bind(&EventCreator::run,this)));
}

void EventCreator::stop()
{
    {
        lock_guard<mutex> lock(m_mutex);
        m_bShouldRun = false;
        m_condition.notify_one();
    }

    if (m_spThread)
    {
        m_spThread->join();
        m_spThread.reset();
    }    
}

void EventCreator::run()
{
    bool isRTAppRunning = m_pDevice->isApplicationRunning();
    while (m_bShouldRun)
    {
        boost::unique_lock<mutex> lock(m_mutex);
        // 
        if(!m_condition.timed_wait(lock,boost::system_time(boost::get_system_time() + boost::posix_time::milliseconds(25))))
        {
            // here because of time out, so no sleep necessary
            bool isStillRunning = m_pDevice->isApplicationRunning();
            if (isRTAppRunning != isStillRunning)
            {   

                if (isStillRunning)
                {
                    // Using SendMessage to main thread => no problem here
                    notifyAppStarted();
                }
                else
                {   
                    notifyAppStopped(); 
                }
                isRTAppRunning = isStillRunning;
            }
            // in addition to wait above
            m_spThread->yield();
        }
    }
}

这些是来自主线程的一些 API 调用:

void Device::getData(Int32 byteCnt)
{
    mutex::scoped_lock lock(m_monitor);
    m_pApi->fetchBytes(&m_buf,byteCnt);
}

bool Device::isApplicationRunning()
{
    mutex::scoped_lock lock(m_monitor);
    return m_pApi->getState() == DV_RUNNING;
}

In my application I want to be informed by events, that another application has been started or stopped. I have an existing API to the running application which cannot be changed to accomodate notification which would be the obvious solution.

What I have is a function call in the API (isRunning), so I decided to make a polling thread which polls the state through the API and informs my app.

My problem is now, the API call in the polling thread uses an object which is also used in my own application's main thread and I'd like to know how to be sure that I make it right :).

My idea would be to wrap each call to the API object (through an adapter e.g., see the second code block) with a mutex lock, so I'm sure the API is not called by my threads more than once.

Is this the right approach?

I'm using boost for threading/syncing (see code).

This is the polling thread:

void EventCreator::start()
{
    stop();
    m_bShouldRun = true;    
    m_spThread = BoostThreadPtr(new thread(bind(&EventCreator::run,this)));
}

void EventCreator::stop()
{
    {
        lock_guard<mutex> lock(m_mutex);
        m_bShouldRun = false;
        m_condition.notify_one();
    }

    if (m_spThread)
    {
        m_spThread->join();
        m_spThread.reset();
    }    
}

void EventCreator::run()
{
    bool isRTAppRunning = m_pDevice->isApplicationRunning();
    while (m_bShouldRun)
    {
        boost::unique_lock<mutex> lock(m_mutex);
        // 
        if(!m_condition.timed_wait(lock,boost::system_time(boost::get_system_time() + boost::posix_time::milliseconds(25))))
        {
            // here because of time out, so no sleep necessary
            bool isStillRunning = m_pDevice->isApplicationRunning();
            if (isRTAppRunning != isStillRunning)
            {   

                if (isStillRunning)
                {
                    // Using SendMessage to main thread => no problem here
                    notifyAppStarted();
                }
                else
                {   
                    notifyAppStopped(); 
                }
                isRTAppRunning = isStillRunning;
            }
            // in addition to wait above
            m_spThread->yield();
        }
    }
}

These are some API calls from the main thread:

void Device::getData(Int32 byteCnt)
{
    mutex::scoped_lock lock(m_monitor);
    m_pApi->fetchBytes(&m_buf,byteCnt);
}

bool Device::isApplicationRunning()
{
    mutex::scoped_lock lock(m_monitor);
    return m_pApi->getState() == DV_RUNNING;
}

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

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

发布评论

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

评论(1

滴情不沾 2024-07-21 23:20:44

这听起来是个好方法。

一般来说,在无争用的情况下,锁的获取速度应该非常快。 您的轮询线程应该不频繁地轮询,即最多每隔几秒轮询一次,因此锁的争用应该非常小。

如果您的两个线程不断争夺锁,您将需要重新考虑您的设计。

This sounds like a good approach.

In general, locks should be very fast to acquire when uncontended. Your polling thread should be polling infrequently, i.e., at most once every few seconds, so contention on the lock should be very small.

If your two threads are constantly battling over the lock, you'll need to rethink your design.

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