Используйте атомную операцию сравнения и замены. В псевдокоде:
do {
unsigned int n = load(freeBytes);
if (n < bytesNeeded) { return NOT_ENOUGH_MEMORY; }
unsigned int new_n = n - bytesNeeded;
} while (!compare_and_swap(&freeBytes, n, new_n));
С реальным C++ <atomic>
переменных фактическое может будет выглядеть очень похоже:
#include <atomic>
// Global counter for the amount of available bytes
std::atomic<unsigned int> freeBytes; // global
// attempt to decrement the counter by bytesNeeded; returns whether
// decrementing succeeded.
bool allocate(unsigned int bytesNeeded)
{
for (unsigned int n = freeBytes.load(); ;)
{
if (n < bytesNeeded) { return false; }
unsigned int new_n = n - bytesNeeded;
if (freeBytes.compare_exchange_weak(n, new_n)) { return true; }
}
}
(Обратите внимание, что окончательное compare_exchange_weak
принимает первый аргумент по ссылке и обновления его с текущее значение атомной переменной в случае сбоя обмена.)
В отличие от этого, приращение значения («deallocate?») может быть выполнено с помощью простого a tomic add (если вы не хотите проверять переполнение). Это в какой-то степени симптоматично для контейнеров без блокировки: создание чего-то относительно легко, предполагая бесконечные ресурсы, но удаление требует попыток в цикле.
и поддержка
спасибо!. Моя проблема заключалась в том, что между загрузкой и обменом значение freeBytes могло измениться, поэтому я не могу доверять этому, я не понял, что я могу подготовить результат в соответствии с этим значением и перепроверять, если он изменился, прежде чем обменять значения ! – user3723779
@ user3723779: Точно :-) –
Итак, это решение, учитывая статус технологии. Но процессор может обеспечить такую атомную операцию одним выстрелом !!! – user3723779