'Why does this two static constexpr int variable behave "differently"?

English is not my first language.Please forgive my syntax mistake.

I am new to mutiThread programming, and I am doing a mutiThread Lab about spinLock. A couple of constexpr type variable's behaviour really occur my concerning. Here is the code.

(P.S. The WriteUp of the Lab provides a Lock Class and it work fine, everything is good.)

class spin_lock
{
    static constexpr int UNLOCKED = 1;

    static constexpr int LOCKED = 0;

    std::atomic<int> m_value{1};

public:
    void lock()
    {
        while (true)
        {
            int expected = UNLOCKED;
            if (m_value.compare_exchange_strong(expected, LOCKED)) // watch out for this line
                break;
        }
    }

there are two Thread son and dad, son is consumer and dad is producer:

#include <thread>
#include <mutex>
#include <iostream>
#include <atomic>

static std::atomic<int> orangeNum(0);
static std::atomic<int> appleNum(0);
static constexpr int FULL = 1;
static constexpr int EMPTY = 0;

void * son(void * arg) {
    while(true){
        myLock.lock();
        std::cout<<"plant locked by son"<<std::endl;
        if(orangeNum.compare_exchange_strong(FULL,EMPTY) && appleNum.compare_exchange_strong(EMPTY,EMPTY)){
            std::cout<<"son take out orange."<<std::endl;
            myLock.unlock();
            std::cout<<"plant unlocked by son"<<std::endl;
            continue;
        } else {
            std::cout << "son cannot take out orange." << std::endl;
            myLock.unlock();
            std::cout << "plant unlocked by son" << std::endl;
            continue;
        }
    }
}

I am using Clion on Arch linux with g++ (GCC) 11.2.0

IDE mark red underline looked like this(with error notice, error:No matching member function for call to 'compare_exchange_strong'). enter image description here

if I delete constexpr in declaration of static constexpr int FULL = 1; static constexpr int EMPTY = 0;.Every thing goes fine. enter image description here

while the spin_lock class work fine with constexpr: enter image description here

the whoal code file is looked like this.

#include <thread>
#include <mutex>
#include <iostream>
#include <atomic>


static std::atomic<int> orangeNum(0);
static std::atomic<int> appleNum(0);

static constexpr int FULL = 1;//error
static constexpr int EMPTY = 0;//error

//static int FULL = 1;//good
//static int EMPTY = 0;//good

class spin_lock
{
    static constexpr int UNLOCKED = 1;

    static constexpr int LOCKED = 0;

    std::atomic<int> m_value{1};

public:
    void lock()
    {
        while (true)
        {
            int expected = UNLOCKED;
            if (m_value.compare_exchange_strong(expected, LOCKED))
                break;
        }
    }

    void unlock()
    {
        m_value.store(UNLOCKED);
    }
};
static spin_lock myLock;
void * son(void * arg) {
    while(true){
        myLock.lock();
        std::cout<<"plant locked by son"<<std::endl;
        if(orangeNum.compare_exchange_strong(FULL,EMPTY) && appleNum.compare_exchange_strong(EMPTY,EMPTY)){
            std::cout<<"son take out orange."<<std::endl;
            myLock.unlock();
            std::cout<<"plant unlocked by son"<<std::endl;
            continue;
        } else {
            std::cout << "son cannot take out orange." << std::endl;
            myLock.unlock();
            std::cout << "plant unlocked by son" << std::endl;
            continue;
        }
    }
}

void * dad(void * arg){
//quite similar to son.
}

int main(){
    pthread_t dadThread, sonThread;
    int ret;

    ret=pthread_create(&dadThread,nullptr, dad,0);
    ret=pthread_create(&sonThread,nullptr, son,0);




    pthread_join(dadThread,NULL);
    pthread_join(sonThread,NULL);


}

why these constexpr type behave differently?

c++


Solution 1:[1]

I'm the original poster.

I have checked the solutions and tips in comment and now I have learnt what is wrong I've done.

first of all, I just copy the lock class and didn't notice that this line

int expected = UNLOCKED;

the expected is int not const int

Secondly, the type of the first arg of compare_exchange_strong() is lvalue reference.So it can't bind to a non-modified-able lvalue which is a const static lvalue in this case.

Thirdly, the mannual book I refered is too old, thanks you guys for introducing std::jthread for mehere is some doc about it.

Thanks very much~!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1