条件变量自定义等待函数

Condition variable custom wait function

我创建了自定义自旋锁 class

我想在条件变量中使用这个class,但是有一个错误

error: no matching function for call to ‘std::condition_variable::wait(std::unique_lock<Spinlock>&)’
                 cv_.wait(lk);

我在第 cv_.wait(lk);

行有错误

如何支持条件变量的自旋锁?

我要声明我自己的函数等待void wait(unique_lock<SpinLock>& __lock, _Predicate __p)签名。

#include <atomic>
#include <iostream>
#include <string>
#include <cstdlib> // atoi
#include <thread> // thread
#include <mutex> // mutex
#include <condition_variable>
#include <vector>

using namespace std;


class Spinlock {
private:
    std::atomic_flag lock_ = ATOMIC_FLAG_INIT;
public:
    void lock()
    {
        while (lock_.test_and_set(std::memory_order_acquire)) continue;
    }
    void unlock()
    {
        lock_.clear(std::memory_order_release);
    }
};


class PrintOrder final {
public:
    PrintOrder(int n, int threadNum)
        : maxNum_(n)
        , curNum_(0)
    {
        startTime_ = chrono::steady_clock::now();
        
        threads_.reserve(threadNum);
        unique_lock<Spinlock> lk(spinLock_);
        for(int x = 0; x < threadNum; ++x)
        {
            threads_.emplace_back(&PrintOrder::background, this, x);
        }
    }

    ~PrintOrder() {
        for(auto&& th : threads_)
        {
            th.join();
        }

        auto endTime = chrono::steady_clock::now();
        auto diff = endTime - startTime_;
        cout << chrono::duration <double, milli> (diff).count() << " ms" << endl;
    }

    void background(int x) {
        while(true) {
            unique_lock<Spinlock> lk(spinLock_);
            // wait until it's this thread's turn or curNum_ > maxNum_
            while((curNum_ % threads_.size()) != x and curNum_ <= maxNum_)
            {
                cv_.wait(lk);
            }
            if(curNum_ > maxNum_)
            {
                break;
            }

            cout << curNum_ << endl;
            ++curNum_;
            cv_.notify_all();
        }
    }

private:
    int maxNum_;
    int curNum_;
    Spinlock spinLock_;
    condition_variable cv_;
    vector<thread> threads_;

    chrono::time_point<chrono::steady_clock> startTime_;
};

int main(int argc, char **argv) {
    if (argc == 3)
    {
        int maxNum = atoi(argv[1]);
        int threadsNum = atoi(argv[2]);
        PrintOrder printOrder(maxNum, threadsNum);
    } else {
        cout << "ERROR: expected console input: <maxNum> <threadsNum>" << endl;
    }
    return 0;
}

std::condition_variable only supports std::unique_lock<std::mutex>. Use std::condition_variable_any 代替。

The condition_variable_any class is a generalization of std::condition_variable. Whereas std::condition_variable works only on std::unique_lock<std::mutex>, condition_variable_any can operate on any lock that meets the BasicLockable requirements.