Я довольно новичок в использовании фьютексов, но вот решение, которое, я думаю, должно работать.Только предупреждаю, что я вообще не проверял это, и его можно было бы сделать быстрее с помощью нескольких дополнительных настроек.
void waitUntilNotEqual(volatile int* addr, int value) {
while (*addr == value) {
futex(addr, FUTEX_WAIT, value, 0, 0, 0);
}
}
void changeValue (volatile int* addr, int newValue) {
int oldValue = *addr;
if (oldValue != newValue) {
*addr = newValue;
futex(addr, FUTEX_WAKE, INT_MAX, 0, 0, 0);
}
}
Для того, чтобы это работало должным образом, все изменения адреса были переданы * 1004.* должно быть сделано через changeValue
.Значение INT_MAX
в вызове FUTEX_WAKE
указывает, что он должен разбудить все потоки, ожидающие этого фьютекса.Оператор if в функции changeValue
- это оптимизация, позволяющая избежать бессмысленных пробуждений.Наконец, вызов FUTEX_WAIT
необходимо держать в цикле, потому что он мог бы ложно возвращаться из сигналов.
Я также должен отметить, что вы не предоставили подробных сведений о проблеме, которую пытаетесь решитьЭто означает, что этот фрагмент кода, вероятно, подходит только для самых простых случаев использования.Если вам нужно что-то лучше адаптированное к вашей текущей проблеме, тогда мне нужно больше деталей (количество потоков, контекст, в котором вызываются waitUntilNotEqual
и changeValue
, количество возможных одновременных потоков в waitUntilNotEqual
или changeValue
и т. Д.)
Если вы хотите узнать больше о том, как правильно использовать фьютексы, я рекомендую бумагу Futexes Are Tricky .