Создание std::mutex
ярмарки будет стоить. А в C ++ вы не платите за то, что не просите.
Вы могли бы написать блокирующий объект, где сторона, снимающая блокировку, не может быть следующей, чтобы получить ее. Более продвинутый, вы можете написать один, где это происходит, только если кто-то еще ждет.
Вот быстрый, непроверенный удар по справедливому мьютексу:
struct fair_mutex {
void lock() {
auto l = internal_lock();
lock(l);
}
void unlock() {
auto l = internal_lock();
in_use = false;
if (waiting != 0) {
loser=std::this_thread::get_id();
} else {
loser = {};
}
cv.notify_one();
}
bool try_lock() {
auto l = internal_lock();
if (in_use) return false;
lock(l);
return true;
}
private:
void lock(std::unique_lock<std::mutex>&l) {
++waiting;
cv.wait( l, [&]{ return !in_use && std::this_thread::get_id() != loser; } );
in_use = true;
--waiting;
}
std::unique_lock<std::mutex> internal_lock() const {
return std::unique_lock<std::mutex>(m);
}
mutable std::mutex m;
std::condition_variable cv;
std::thread::id loser;
bool in_use = false;
std::size_t waiting = 0;
};
это "справедливо", если у вас есть два потока, конкурирующих за ресурс, они будут по очереди. Если кто-то ждет блокировки, тот, кто отказывается от блокировки, больше не захватит ее.
Это, однако, многопоточный код. Так что я мог бы перечитать это, но я бы не стал доверять своей первой попытке что-либо написать.
Вы могли бы расширить это (при увеличении стоимости), чтобы оно было справедливым в n-смысле (или даже омега-справедливым), где, если ожидается до N элементов, они все получат свой ход, прежде чем освобождающий поток получит еще один шанс.