DIOCP 소스 오픈 프로젝트 - Delphi 고성능 잠금 해제 대기열 (lock-free)
8649 단어 Delphi
[대기열]
먼저 하나의 대기열이다. 간단한 대기열은 생산자가 데이터를 대기열(push)에 넣고 소비자가 대기열을 통해 데이터를 출력하여 처리하는 것이다.
간단한 대기열은 Push와 Pop 함수를 제공하는 것입니다.
우리는 체인 테이블로 데이터를 저장한다.Head ->data01->data02...data_n->Tail, 각 블록의 구조는 다음과 같습니다.
type
PVarQueueBlock = ^TVarQueueBlock;
TVarQueueBlock = packed record
value:Variant;
next:PVarQueueBlock;
end;
1. Push 데이터 압입 시 압입 Tail.next는 새로 눌린 블록을 가리키고 새로운 블록으로 Tail을 만듭니다
procedure TSimpleQueue.pushQueue(pvData: PVarQueueBlock);
begin
if FHead = nil then
begin
FHead = pvData;
FTail := FHead;
end else
begin
FTail.next := pvData;
FTail := pvData;
end;
Inc(FCount);
end;
2. Pop 데이터를 진행할 때 Head 블록을 꺼내고 Head 블록으로 가리키는 다음 블록을 Head로 한다.
function TSimpleQueue.popQueue: PVarQueueBlock;
var
lvTemp, lvRet:PVarQueueBlock;
begin
lvTemp := FHead;
if (lvTemp = nil) then
begin // Pop
Result := nil;
exit;
end;
//
FHead := FHead.next;
Dec(FCount);
Result :=lvTemp;
end;
위에는 간단한 대열입니다.
[잠금 큐 없음]
위에서 실현된 대열은 다선정 상황에서 안전하지 않다.많은 대기열에서 자물쇠를 추가하려면push와 pop에서 자물쇠를 추가하는 것도 방법이다.임계를 바로 쓰면 되지만 우리가 해야 할 일은 자물쇠가 없는 대열이다
우선 다중 병렬 설계 규칙을 기억해라: 어떤 코드가 연속적으로 실행될 것이라고 가정해서는 안 된다
위의push 조작
FTail.next := pvData;
FTail := pvData;
아마도 FTAil을 실행했을 거예요.xt:=pvData 후 다른 라인에 뺏기고 FTAil에서 새로운 값을 부여합니다. 이렇게 FTAil:=pvData를 진행합니다.이렇게 하면 전체 데이터 체인이 파괴될 것이다.
만약 이 두 줄을 우리가 한 번에 완성할 수 있다면, 이렇게 하면 자물쇠가 없는 조작을 실현할 수 있을 것이다. 이렇게 하면 우리는 원자 조작을 도입해야 한다.Interlocked의 함수입니다.
자물쇠가 없다고 하는 것은 사실 그다지 확실하지 않다. 단지 자물쇠의 입도가 작을 뿐이다.우리는api의InterlockedCompareExchange 함수를 사용하여 실현하였다.
MSDN 찾아보세요.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms683560(v=vs.85).aspx
LONG __cdecl InterlockedCompareExchange(
_Inout_ LONG volatile *Destination,
_In_ LONG Exchange,
_In_ LONG Comparand
);
Parameters
Destination [in, out]
A pointer to the destination value.
Exchange [in]
The exchange value.
Comparand [in]
The value to compare to Destination.
Return value
The function returns the initial value of the Destination parameter.
대충 해명하다.이 함수는 비교한 후에 교환한다.첫 번째 파라미터는 목적의 데이터를 저장하는 것이고, 두 번째 파라미터는 교환 데이터이며, 세 번째 파라미터는 비교 데이터(첫 번째 파라미터와 비교)이다. 만약에 교환이 되돌아오는 데이터가 세 번째 파라미터와 같다면.
이렇게 하면 push와 pop에서 한꺼번에 완성할 수 있다.
여기에 push의 팝 동작을 붙여주세요.
procedure TVarQueue.pushQueue(pvData: PVarQueueBlock);
var
lvTemp:PVarQueueBlock;
lvPointer:Pointer;
begin
while True do
begin
lvTemp := FTail;
while lvTemp.next <> nil do lvTemp := lvTemp.next;
if InterlockedCompareExchangePointer(Pointer(lvTemp.next), Pointer(pvData), nil) = nil then
begin
break;
end;
end;
FTail := pvData;
Inc(FCount);
end;
function TVarQueue.popQueue: PVarQueueBlock;
var
lvTemp, lvRet:PVarQueueBlock;
lvPointer:Pointer;
begin
/// FHead
/// FHead
///
while True do
begin
lvTemp := FHead;
if (lvTemp = nil) or (lvTemp.next = nil) then
begin // Pop
Result := nil;
exit;
end;
if InterlockedCompareExchangePointer(Pointer(FHead), lvTemp.next, lvTemp) = lvTemp then
begin
break;
end;
end;
Dec(FCount);
lvRet := lvTemp.next;
Result := lvRet;
lvTemp.next := nil;
Dispose(lvTemp);
// head.next
end;
나중에 DIOCP 프로젝트에 전체 코드를 업로드합니다.
만약 빈틈이 있으면 지적해 주십시오.환영합니다. 만약에 DIOCP 그룹 토론이
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[Delphi] TStringBuilder그리고 꼭 사용해야만 할까? 그림처럼 Heap 영역에 "Hello" 공간을 생성하고 포인팅을 한다. "Hello World" 공간을 새로 생성한 후 포인팅을 하게 된다. 결국 "Hello" 라는 String 객체가 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.