У мене є список, з якого я хочу захоплювати елементи з різних потоків. Щоб уникнути блокування файлу mutex, який захищає список, коли він порожній, я перевіряю empty()
перед блокуванням.
Це добре, якщо дзвінок на list::empty()
неправильний 100% часу. Я хочу лише уникнути збоїв або зривів одночасних list::push()
та list::pop()
викликів.
Чи можу я припустити, що VC ++ та Gnu GCC лише іноді empty()
помиляться і нічого гіршого?
if(list.empty() == false){ // unprotected by mutex, okay if incorrect sometimes
mutex.lock();
if(list.empty() == false){ // check again while locked to be certain
element = list.back();
list.pop_back();
}
mutex.unlock();
}
std::list::size
має гарантовану постійну часову складність, що в основному означає, що розмір (кількість вузлів) потрібно зберігати в окремій змінній; давайте назвемо це size_
. std::list::empty
то, ймовірно, повертає щось на зразок size_ == 0
, і одночасне читання і запис size_
викликає перегони даних, отже, UB.