代码之家  ›  专栏  ›  技术社区  ›  canellas

qmutex:销毁锁定的互斥锁

  •  0
  • canellas  · 技术社区  · 7 年前

    给定以下代码:

    #include <chrono>
    #include <ctime>
    #include <functional>
    #include <iostream>
    #include <thread>
    #include <utility>
    
    #include <QFuture>
    #include <QMutex>
    #include <QWaitCondition>
    #include <QtConcurrent>
    
    class Async
    {
    public:
        Async() = default;
        Async(const Async&) = delete;
        Async(Async&&) = delete;
    
        ~Async() = default; //{ m_mutex.unlock(); }
    
        Async& operator=(const Async&) = delete;
        Async& operator=(Async&&) = delete;
    
        template<typename t_result>
        QFuture<bool> operator()(
              std::function<t_result()>&& p_function,
              std::chrono::milliseconds p_timeout,
              t_result* p_result)
        {
            QtConcurrent::run([this, p_function, p_result]() {
                *p_result = p_function();
                std::cout << time(nullptr) << " waking" << std::endl;
                m_cond.wakeAll();
        });
    
        return QtConcurrent::run([this, p_timeout]() {
               std::cout << time(nullptr) << " starting to wait for "
                         << p_timeout.count() << " ms" << std::endl;
               m_mutex.lock();
               bool wait =
                   m_cond.wait(&m_mutex, 
                               static_cast<unsigned 
                                           long>(p_timeout.count()));
               std::cout << time(nullptr)
                         << ", finished waiting = " 
                         << (wait ? "T" : "F") 
                         << std::endl;
               if (wait) {
                   return false;
               }
               return true;
        });
      }
    
    private:
        QMutex m_mutex;
        QWaitCondition m_cond;
    };
    
    int main()
    {
      Async async;
    
      char letter = 'z';
    
      std::function<char()> f1 = []() -> char {
          std::this_thread::sleep_for(std::chrono::seconds(4));
          return 'a';
      };
    
      std::cout << "1: " << time(nullptr) << std::endl;
      QFuture<bool> result =
        async(std::move(f1), std::chrono::milliseconds(3999), 
              &letter);
    
      std::cout << "2: " << time(nullptr) << std::endl;
    
      std::this_thread::sleep_for(std::chrono::seconds(8));
    
      std::cout << "3: " << time(nullptr) << std::endl;
    
      if (result.result()) {
        std::cout << "timeout, letter = " << letter;
      } else {
        std::cout << "NO timeout, letter = " << letter;
      }
      std::cout << std::endl;
    
      return 0;
    }
    

    终于 …8),当我运行它时, cout 按预期打印,但我得到一个 QMutex: destroying locked mutex 在行刑结束时。因为我收到消息了 finished waiting , the m_cond.wait 所以被处决了(我想) m_mutex 将被解锁。但似乎并非如此。

    如果我用 ~Async() { m_mutex.unlock(); } ,我没有收到消息,但我认为不应该这样做。

    有人能解释一下为什么没有释放互斥锁吗?

    谢谢!

    0 回复  |  直到 7 年前
        1
  •  1
  •   UmNyobe    7 年前

    当使用互斥互斥锁对条件变量执行可运行的等待时,当等待结束(是否超时)时,它将保持互斥锁。

    这意味着您必须显式地解除互斥锁

    bool wait = m_cond.wait(&m_mutex,static_cast<unsigned long>(p_timeout.count()));
    m_mutex.unlock();
    if (wait) {
        return false;
    }
    return true;
    
        2
  •  0
  •   mzimmers    7 年前

    从qt qmutex页面:

    警告:销毁锁定的互斥锁可能导致未定义的行为。

    很抱歉,我在电话里打字