Reputation: 75
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').
if I delete constexpr
in declaration of static constexpr int FULL = 1; static constexpr int EMPTY = 0;
.Every thing goes fine.
while the spin_lock class work fine with constexpr
:
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?
Upvotes: 0
Views: 104
Reputation: 75
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 of type 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 manual book I referred to is too old, thanks you guys for introducing std::jthread
for mehere is some doc about it.
Thanks very much~!
Upvotes: 1