Я думаю, что эта статья основана на фундаментальном недопонимании того, для чего нужен CSingleLock и как его использовать.
Вы не можете заблокировать один и тот же CSingleLock несколько раз, но вы не должны это делать. CSingleLock, как следует из его названия, предназначен для блокировки чего-то ОДНАЖДЫ.
Каждый CSingleLock просто управляет одной блокировкой на каком-либо другом объекте (например, CCriticalSection, который вы передаете его во время построения), с целью автоматического снятия этой блокировки, когда CSingleLock выходит из области видимости.
Если вы хотите заблокировать базовый объект несколько раз, вы должны использовать несколько CSingleLocks; Вы не будете использовать один CSingleLock и пытаться заблокировать его несколько раз.
Неверно (его пример):
CCriticalSection crit;
CSingleLock lock(&crit);
lock.Lock();
lock.Lock();
lock.Unlock();
lock.Unlock();
Справа:
CCriticalSection crit;
CSingleLock lock1(&crit);
CSingleLock lock2(&crit);
lock1.Lock();
lock2.Lock();
lock2.Unlock();
lock1.Unlock();
Еще лучше (так что вы получите RAII):
CCriticalSection crit;
// Scope the objects
{
CSingleLock lock1(&crit, TRUE); // TRUE means it (tries to) locks immediately.
// Do stuff which needs the lock (if IsLocked returns success)
CSingleLock lock2(&crit, TRUE);
// Do stuff which needs the lock (if IsLocked returns success)
}
// crit is unlocked now.
(Конечно, вы никогда не получите намеренно две блокировки одной и той же критической секции в одном блоке, подобном этому. Обычно это происходит только в результате вызова функций, которые получают блокировку, находясь внутри чего-то другого, уже имеющего свой собственный замок.)
(Кроме того, вы должны проверить CSingleLock.IsLocked, чтобы увидеть, была ли блокировка успешной. Я оставил эти проверки для краткости и потому, что они были исключены из исходного примера.)
Если сам CCriticalSection страдает от той же проблемы, то это, безусловно, проблема, но он не представил никаких доказательств того, что я вижу. (Возможно, я что-то пропустил. Я не могу найти источник CCriticalSection в моей установке MFC, чтобы также проверить это.)