У мене є список, з якого я хочу захоплювати елементи з різних потоків. Щоб уникнути блокування файлу 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.