Блокировка нескольких частей массива — многопоточность

Я пытаюсь реализовать потокобезопасный механизм блокировки для массива со следующим предполагаемым вариантом использования:

  1. Запросите индексы, которые вы хотите заблокировать, и попытайтесь получить их. Если вам не удалось получить ЛЮБОЙ индекс, выручите и попробуйте снова (по сути, вращение).
  2. После получения необходимых блокировок выполните обработку этих индексов.
  3. Отпусти приобретенные замки!

Я использую приведенный ниже код для проверки блокировки — он просто увеличивает количество тестов, при этом для каждой итерации указываются одни и те же индексы (поэтому он заставляет доступ быть последовательным). Единственная проблема в том, что это не работает, и я как бы озадачен …

У меня такое ощущение, что мне не хватает какого-то ключевого состояния гонки, но я пока не могу его идентифицировать 🙁

#pragma omp parallel for
for (int i = 0; i < activeItems; i++)
{
std::vector<int> lockedBucketIndexes = {0, 1, 2, 3};
//try and get a lock on the buckets we want, otherwise keep trying
while (!spatialHash->TryAcquireBucketLocks(lockedBucketIndexes))
{
//TODO - do some fancy backoff here
}

testCount++;

spatialHash->DropBucketLocks(lockedBucketIndexes);
}

Класс / методы, которые делают блокировку:

std::vector<int> _bucketLocks;
SpinLock _bucketLockLock;

bool SpatialHash::TryAcquireBucketLocks(std::vector<int> bucketIndexes)
{
bool success = true;
//try and get a lock to set our bucket locks... lockception
_bucketLockLock.lock();

//quickly check that the buckets we want are free
for each (int bucketIndex in bucketIndexes)
{
if (_bucketLocks[bucketIndex] > 0)
{
success = false;
break;
}
}

//if all the buckets are free, set them to occupied
if (success)
{
for each (int bucketIndex in bucketIndexes)
{
_bucketLocks[bucketIndex] = 1;
}
}

//let go of the lock
_bucketLockLock.unlock();

return success;
}

void DropBucketLocks(std::vector<int> bucketIndexes)
{
//I have no idea why these locks are required
//It seems to almost work with them though...
_bucketLockLock.lock();

for each (int bucketIndex in bucketIndexes)
{
_bucketLocks[bucketIndex] = 0;
}

_bucketLockLock.unlock();

return true;
}

Класс спинлок:

class SpinLock {
std::atomic_flag locked = ATOMIC_FLAG_INIT;
public:
void lock() {
while (locked.test_and_set(std::memory_order_acquire)) { ; }
}
void unlock() {
locked.clear(std::memory_order_release);
}
};

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]