C++ CSinglock 实现

问题描述 投票:0回答:1

我想在基于遗留参考代码的 C++ 程序中为正在运行的线程实现单锁。

void AutoThread::CreateEvent()
{
    AutoRunning = new CRtEvent(FALSE, TRUE,"AutoRunning");
    AutoHoming  = new CRtEvent(FALSE, TRUE,"AutoHoming");
    AutoPicking = new CRtEvent(FALSE, TRUE,"AutoPicking");
    AutoMoving  = new CRtEvent(FALSE, TRUE,"AutoMoving");
}

int AutoThread :: Run()
{
    while (1) {
            CRtSingleLock sSingleLock132(AutoRunning, FALSE);
            CRtSingleLock sSingleLock134(AutoPicking, FALSE);
            CRtSingleLock sSingleLock144(AutoHoming, FALSE);        
            CRtSingleLock sSingleLock154(AutoMoving, FALSE);
            
            if(sSingleLock132.Lock(0) || ( sSingleLock134.Lock(0)) || 
                ( sSingleLock144.Lock(0)) || sSingleLock154.Lock(0)) {...}
                
    }
}

`

但是,由于我使用的是主要支持标准C++ API的专有软件,单锁机制不可用。我已经了解了一些可用的同步函数,例如临界区、互斥量和信号量,但我仍然对使用什么来替代单锁感到困惑。

欢迎对我的问题提出任何意见和建议;因为我是多线程概念和线程之间的资源共享的新手。

  1. 单锁实现方案示例
  2. 正确的实施方法
  3. 替代解决方案的建议。
c++ multithreading concurrency mfc semaphore
1个回答
0
投票

使用一个条件变量等待状态变化而不是有 4 个单独事件的示例。

在线演示:https://onlinegdb.com/J8nrlkIo3x

如果有任何问题,请告诉我

// state_synchronization header
#include <mutex>
#include <condition_variable>
#include <chrono>

// class to synchronize states between threads
// using condition variables.

template<typename type_t>
class state_synchronization_t final
{
public:
    explicit state_synchronization_t(const type_t& state) :
        m_state{ state },
        m_cancelled{ false }
    {
    }

    ~state_synchronization_t()
    {
        // be nice at shutdown
        cancel_waits();
    }

    //non copyable/non movable
    state_synchronization_t(const state_synchronization_t&) = delete;
    state_synchronization_t& operator=(state_synchronization_t&) = delete;
    state_synchronization_t(state_synchronization_t&&) = delete;
    state_synchronization_t& operator=(state_synchronization_t&&) = delete;

    // at shutdown of the system any pending waits must be aborted
    // so that waiting threads get unblocked.
    void cancel_waits()
    {
        std::unique_lock<std::mutex> lock(m_state_mutex);
        m_cancelled = true;
        m_state_changed.notify_all();
    }

    void set(const type_t& state)
    {
        std::unique_lock<std::mutex> lock(m_state_mutex);
        m_state = state;
        m_state_changed.notify_all();
    }

    // wait for a state change or cancelled
    bool wait_for(const type_t& state, const std::chrono::steady_clock::duration& duration)
    {
        std::unique_lock<std::mutex> lock(m_state_mutex);
        auto retval = m_state_changed.wait_for(lock, duration, [&] { return (m_state == state) || m_cancelled; });
        if (m_cancelled) throw std::runtime_error("cancelled");
        return retval;
    }

private:
    std::mutex               m_state_mutex;
    std::condition_variable  m_state_changed;
    std::atomic<type_t>      m_state;
    bool                     m_cancelled;
};

// main cpp file
#include <future>
#include <iostream>

using namespace std::chrono_literals;

// use 1 enum instead of 4 synchronization primitives to model states
enum class motion_state_v
{
    unknown,
    running,
    homing,
    picking,
    moving
};

int main()
{
    // initialize state
    state_synchronization_t<motion_state_v> state{ motion_state_v::unknown };

    [[maybe_unused]] auto future = std::async(std::launch::async,[&]
    {
        std::cout << "background thread : homing\n";
        state.set(motion_state_v::homing);
        std::this_thread::sleep_for(250ms);
        std::cout << "background thread : running\n";
        state.set(motion_state_v::running);
    });

    std::cout << "main thread : wait for homing\n";
    state.wait_for(motion_state_v::homing, 30s);  // first wait for background process to start homing
    std::cout << "main thread : wait for running\n";
    state.wait_for(motion_state_v::running, 30s); // then wait for homed
    std::cout << "main thread : done\n";

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.