당신이 필요로하고 구현하고 싶은 것을 Run-Down Protection이라고합니다. 불행히도 커널 모드에서만 지원되지만 사용자 모드에서도 직접 구현하지는 않습니다.
HANDLE ghStopEvent;
LONG gLockCount = 1;
BOOLEAN bStop = FALSE;
void unlock()
{
if (!InterlockedDecrement(&gLockCount)) SetEvent(ghStopEvent);
}
BOOL lock()
{
LONG Value = gLockCount, NewValue;
for (; !bStop && Value; Value = NewValue)
{
NewValue = InterlockedCompareExchange(&gLockCount, Value + 1, Value);
if (NewValue == Value) return TRUE;
}
return FALSE;
}
void funcA();
void UseA()
{
if (lock())
{
funcA();
unlock();
}
}
하고 런 다운을 시작하고자 할 때 - 당신이 있지만 경우에만 1 lock
기능이 연동되어 증가 gLockCount
을 볼 수있는 방법을 한 번
bStop = TRUE; unlock();
전화 :
간단한 구현 옆에 0이 아닙니다.
커널 모드에서는를 대신 호출 할 수 있습니다.
EX_RUNDOWN_REF gRunRef;
void UseA()
{
if (ExAcquireRundownProtection(&gRunRef))
{
funcA();
ExReleaseRundownProtection(&gRunRef)
}
}
최종 장소에unlock
-ExWaitForRundownProtectionRelease
은
런 다운 보호의 좀 더 복잡하고 확장 성 구현 :
#define RUNDOWN_INIT_VALUE 0x80000000
#define RUNDOWN_COMPLETE_VALUE 0
class __declspec(novtable) RUNDOWN_REF
{
LONG _LockCount;
protected:
virtual void RundownCompleted() = 0;
public:
BOOL IsRundownBegin()
{
return 0 <= _LockCount;
}
void Reinit()
{
if (InterlockedCompareExchange(&_LockCount, RUNDOWN_INIT_VALUE, RUNDOWN_COMPLETE_VALUE) != RUNDOWN_COMPLETE_VALUE)
{
__debugbreak();
}
}
RUNDOWN_REF()
{
_LockCount = RUNDOWN_INIT_VALUE;
}
BOOL AcquireRundownProtection()
{
LONG Value = _LockCount, NewValue;
for (; Value < 0; Value = NewValue)
{
NewValue = InterlockedCompareExchange(&_LockCount, Value + 1, Value);
if (NewValue == Value) return TRUE;
}
return FALSE;
}
void ReleaseRundownProtection()
{
if (RUNDOWN_COMPLETE_VALUE == InterlockedDecrement(&_LockCount))
{
RundownCompleted();
}
}
void BeginRundown()
{
if (AcquireRundownProtection())
{
_interlockedbittestandreset(&_LockCount, 31);
ReleaseRundownProtection();
}
}
};
및 사용은 좋아 :
class MY_RUNDOWN_REF : public RUNDOWN_REF
{
HANDLE _hEvent;
virtual void RundownCompleted()
{
SetEvent(_hEvent);
}
// ...
} gRunRef;
void UseA()
{
if (gRunRef.AcquireRundownProtection())
{
funcA();
gRunRef.ReleaseRundownProtection();
}
}
,403,210 및 중지 할 때 : 커널에서 다른 하나의 존재
gRunRef.BeginRundown();// can be safe called multiple times
// wait on gRunRef._hEvent here
재미있는 것을 (더 오래된 - XP에서 보호를 소진 된 WIN2000에서) API를 Remove Locks. 그것은 거의 동일합니다. 내부 구현 및 사용법 만 다릅니다.
IO_REMOVE_LOCK gLock;
void UseA()
{
if (0 <= IoAcquireRemoveLock(&gLock, 0))
{
funcA();
IoReleaseRemoveLock(&gLock, 0);
}
}
을 우리가 정지 할 때 - 가까운 잠금 구현, 두 번째 근처 개요 보호 구현을 제거 구현
IoAcquireRemoveLock(&gLock, 0);
IoReleaseRemoveLockAndWait(&gLock, 0);
내 첫 번째 코드 스피 넷 전화 : 제거 잠금 코드와 함께 같이 표시됩니다. 그러나 감각으로도 모두 똑같습니다.
[인라인 함수] (https://docs.microsoft.com/en-us/cpp/cpp/inline-functions-cpp) : * "'__forceinline' 키워드는 비용을 무시합니다/benefit 분석을 수행하고 대신 프로그래머의 판단에 의존합니다. [...] '__forceinline'을 무차별 적으로 사용하면 한계 성능 향상만으로 더 큰 코드가 생성되거나 경우에 따라 성능 손실이 발생할 수 있습니다. 예를 들어 더 큰 실행 파일). "* – IInspectable
@IInspectable - 좋아, 필자는 여기서 프로그래머의 판단을 선택한다. 하지만 어쨌든 인라인을 사용하거나 사용하지 않으면 여기에서 내 구현의 논리를 변경하지 마세요. – RbMm
프로그래머의 판단이 잘못되었습니다. 멤버 함수는 이미 암시 적으로 인라인되어 있습니다. 이것은 * 무차별 적으로 사용하기 때문에 시각적 인 혼란을 야기하며 런타임 성능은'__forceinline'이없는 코드보다 좋거나 나쁘다. – IInspectable