Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Быстрые списки

Автор: Vitaly Sergienko
WEB-сайт: http://delphibase.endimus.com

{ **** UBPFD *********** by delphibase.endimus.com ****
>> Быстрые списки.

Цепочка - односвязный список записей (record) фиксированной длины.
Пул цепочек позволяет быстро манипулировать с множеством цепочек.
Общая для всех цепочек конкретного пула память выделяется по мере
необходимости страницами через VirtualAlloc, т.е. без обращения к
менеджеру памяти (GetMem/FreeMem). Соответственно, освобождается
память сразу всего пула. Удобно использовать цепочки в качестве
рабочей памяти, когда нужно раскидать множество элементов по кучкам,
а также при реализации графов ( списки соседей узла ), деревьев
(списки детей узла). Большинство методов и функций написано на basm.

Зависимости: System
Автор:       Alex Konshin, akonshin@earthlink.net, Boston, USA
Copyright:   http://home.earthlink.net/~akonshin/index.htm
Дата:        30 декабря 2002 г.
***************************************************** }

// (c) Alex Konshin mailto:alexk@mtgroup.ru 08 Feb 1999

// 21 jun 2000 - bugfix PutValue
// all "uses" are removed

unit ChainPools;

interface

//uses

type

  PChainLink = ^TChainLink;
  PPChainLink = ^PChainLink;
  TChainLink = packed record
    FNext: PChainLink;
    FValue: LongInt;
  end;

  PPoolBuffer = ^TPoolBuffer;
  PPPoolBuffer = ^PPoolBuffer;
  TPoolBuffer = record
    FNextBuf: PPoolBuffer;
  end;

  TChainLinkCallBack = function(const Value: LongInt; const ALink: PChainLink;
    AParm: Pointer): Boolean;
  TScanChainCallBack = function(ALink: PChainLink; AParm: Pointer): Boolean of
    object;

  TChainPool = class
  protected
    FFirstBuffer: PPoolBuffer;
    FPLastBuffer: PPPoolBuffer;
    FRest: LongWord;
    FTop: PChar;
    FItemSize: Integer;
    function Allocate(const ASize: LongWord): Pointer;
  public
    FFreeChain: PChainLink;
    constructor Create(AItemSize: Integer = SizeOf(TChainLink));
    destructor Destroy; override;
    procedure FreeBuffers;
    // извлекаем из цепочки первый элемент (освобождается)
    function GetValue(var AAnchor: PChainLink): LongInt; virtual;
    // извлекаем из цепочки первый элемент (отсоединяется от цепочки)
    function GetFirstLink(var AAnchor: PChainLink): PChainLink; virtual;
    // извлекаем из цепочки последний элемент (освобождается)
    function GetLastValue(var AAnchor: PChainLink): LongInt; virtual;
    // извлекаем из цепочки последний элемент (отсоединяется от цепочки)
    function GetLastLink(var AAnchor: PChainLink): PChainLink; virtual;
    // вставка в начало без проверки на уникальность
    procedure PutValue(const Value: LongInt; var AAnchor: PChainLink); virtual;
    // вставка в конец с проверкой, False - значение уже существует
    function AddValue(const Value: LongInt; var AAnchor: PChainLink): Boolean;
      virtual;
    // вставка перед звеном, на которое ACallBackFunc выдаст True
    function InsertValue(const Value: LongInt; var AAnchor: PChainLink;
      ACallBackFunc: TChainLinkCallBack; AParm: Pointer = nil): PChainLink;
      virtual;
    // вставка в цепочку в порядке возврастания Value
    function InsertSorted(const Value: LongInt; var AAnchor: PChainLink):
      PChainLink; virtual;
    // удаление указанного значения //
    function RemoveValue(const Value: LongInt; var AAnchor: PChainLink): Boolean;
      virtual;
    // удаление указанного звена
    function RemoveLink(const ALink: PChainLink; var AAnchor: PChainLink):
      Boolean; virtual;
    // создает новый элемент, непривязанный к какой-либо цепочке
    function NewLink: PChainLink; // virtual;
    // освобождение элемента - перенос в список FFreeChain (элемент не должен принадлежать какой-либо цепочке)
    procedure FreeLink(const ALink: PChainLink); virtual;
    // освобождение цепочки
    procedure FreeChain(var AAnchor: PChainLink); virtual;
  end; { TChainPool }

  // вставка элемента в начало цепочки(элемент не должен принадлежать какой-либо цепочке)
procedure LinkTo(const ALink: PChainLink; var AAnchor: PChainLink);
// вставка элемента в конец цепочки(элемент не должен принадлежать какой-либо цепочке)
procedure Append(const ALink: PChainLink; var AAnchor: PChainLink);
function MoveFirstToChain(var AFrom, ATo: PChainLink): PChainLink;
function MoveChainLink(const Value: LongInt; var AAnchor, ATo: PChainLink):
  Boolean;
function AppendChainLink(const Value: LongInt; var AFromChain, AToChain:
  PChainLink): Boolean;
function LastChainLink(const AAnchor: PChainLink): PChainLink;
// проверяем наличие указанного значения в цепочке
function IsValueInChain(const Value: LongInt; AAnchor: PChainLink): Boolean;
// ищем элемент (остается в цепочке)
function FindValue(const Value: LongInt; AAnchor: PChainLink): PChainLink;
function FindAndUnlink(var AAnchor: PChainLink; ACallBackFunc:
  TScanChainCallBack; AParm: Pointer = nil): PChainLink;
function IndexOfValue(const Value: LongInt; AAnchor: PChainLink): LongInt;
// ищем ChainLink, на который AScanChainFunc выдаст True
function ScanChain(const AAnchor: PChainLink; AScanChainFunc:
  TScanChainCallBack; AParm: Pointer): PChainLink;
function ChainLinkByIndex(AAnchor: PChainLink; AIndex: Integer): PChainLink;
function ChainLinkCount(AAnchor: PChainLink): Integer;
// сравнение цепочек, результат =0, <0, >0, abs(result) = индекс несовпавшего элемента
function CompareChains(AFromChain, AToChain: PChainLink): LongInt;

//=============================================================
implementation

const
  MEM_COMMIT = $1000;
  MEM_DECOMMIT = $4000;
  MEM_RELEASE = $8000;
  PAGE_READWRITE = 4;

  kernel = 'kernel32.dll';

type
  DWORD = LongInt;
  BOOL = LongBool;

function VirtualAlloc(lpAddress: Pointer; dwSize, flAllocationType, flProtect:
  DWORD): Pointer; stdcall; external kernel name 'VirtualAlloc';

function VirtualFree(lpAddress: Pointer; dwSize, dwFreeType: DWORD): BOOL;
  stdcall; external kernel name 'VirtualFree';

//-------------------------------------------------------------
// вставка элемента (элемент не должен принадлежать какой-либо цепочке)

procedure LinkTo(const ALink: PChainLink; var AAnchor: PChainLink);
begin
  ALink^.FNext := AAnchor;
  AAnchor := ALink;
end;
//-------------------------------------------------------------
// вставка элемента в конец (элемент не должен принадлежать какой-либо цепочке)

procedure Append(const ALink: PChainLink; var AAnchor: PChainLink); assembler;
asm
@@FindLast:
  mov ecx,edx
  mov edx,[edx]
  test edx,edx
  jnz @@FindLast
  mov [eax],edx
  mov [ecx],eax
end;
//-------------------------------------------------------------
// перенос первого элемента в другую цепочку

function MoveFirstToChain(var AFrom, ATo: PChainLink): PChainLink; assembler;
asm
  mov ecx,[eax]
  test ecx,ecx
  jz @@Exit
  push edx
  mov edx,[ecx]
  mov [eax],edx
  pop edx
  mov eax,[edx]
  mov [ecx],eax
  mov [edx],ecx
@@Exit:
  mov eax,ecx
end;
//-------------------------------------------------------------

function MoveChainLink(const Value: LongInt; var AAnchor, ATo: PChainLink):
  Boolean; assembler;
asm
  push edi
  mov edi,eax
  jmp @@Start
@@Next:
  mov edx,eax
@@Start:
  mov eax,[edx]
  test eax,eax
  jz @@Done
  cmp edi,[eax].TChainLink.FValue
  jne @@Next
  mov edi,[eax]
  mov [edx],edi
  mov edi,[ecx]
  mov [eax],edi
  mov [ecx],eax
  mov eax,1
@@Done:
  pop edi
@@Exit:
end;
//-------------------------------------------------------------

function AppendChainLink(const Value: LongInt; var AFromChain, AToChain:
  PChainLink): Boolean; assembler;
asm
  push edi
  mov edi,eax
  jmp @@Start
@@Next:
  mov edx,eax
@@Start:
  mov eax,[edx]
  test eax,eax
  jz @@Done
  cmp edi,[eax].TChainLink.FValue
  jne @@Next
  mov edi,[eax]
  mov [edx],edi

@@FindLast:
  mov edx,ecx
  mov ecx,[ecx]
  test ecx,ecx
  jnz @@FindLast

  mov edi,[edx]
  mov [eax],edi
  mov [edx],eax
  mov eax,1
@@Done:
  pop edi
@@Exit:
end;
//-------------------------------------------------------------

function LastChainLink(const AAnchor: PChainLink): PChainLink; assembler;
asm
  mov edx,eax
  jmp @@Start
@@Next:
  mov eax,edx
  mov edx,[edx]
@@Start:
  test edx,edx
  jnz @@Next
@@Exit:
end;
//-------------------------------------------------------------

function ScanChain(const AAnchor: PChainLink; AScanChainFunc:
  TScanChainCallBack; AParm: Pointer): PChainLink;
var
  pNext: PChainLink;
begin
  pNext := AAnchor;
  while pNext <> nil do
  begin
    Result := pNext;
    pNext := pNext^.FNext;
    if AScanChainFunc(Result, AParm) then
      Exit;
  end;
  Result := nil;
end;
//-------------------------------------------------------------
// сравнение цепочек, результат =0, <0, >0, abs(result) = индекс несовпавшего элемента

function CompareChains(AFromChain, AToChain: PChainLink): LongInt; assembler;
asm
    mov ecx,1
    push esi
    mov esi,eax
@@loop:
    inc ecx
    test esi,esi
    jz @@1
    test edx,edx
    jz @@gt
    mov eax,[esi]
    sub eax,[edx]
    jz @@loop
    jc @@lt
    jmp @@gt

@@1:
    test edx,edx
    jz @@exit
@@lt:
    neg ecx
@@gt:
    mov eax,ecx
@@exit:
    pop esi
end;
//-------------------------------------------------------------

function IsValueInChain(const Value: LongInt; AAnchor: PChainLink): Boolean;
  assembler; // проверяем наличие указанного значения в цепочке
{
  while AAnchor<>nil do
  begin
    if AAnchor^.FValue=Value then
    begin
      Result := True;
      Exit;
    end;
    AAnchor := AAnchor^.FNext;
  end;
  Result := False;
}
asm
  test edx,edx
  jz @False
@loop:
  cmp eax,TChainLink[edx].FValue
  je @True
  mov edx,[edx]
  test edx,edx
  jnz @loop
@False:
  mov eax,0
  jmp @Exit
@True:
  mov eax,1
@Exit:
end;
//-------------------------------------------------------------

function FindValue(const Value: LongInt; AAnchor: PChainLink): PChainLink;
  assembler;
{ Result := AAnchor;
  while (Result<>nil)and(Result^.FValue<>Value) do Result := Result^.FNext;
}
asm
  xchg eax,edx
  test eax,eax
  jz @Exit
@loop:
  cmp edx,TChainLink[eax].FValue
  je @Exit
  mov eax,[eax]
  test eax,eax
  jnz @loop
@Exit:
end;
//-------------------------------------------------------------

function IndexOfValue(const Value: LongInt; AAnchor: PChainLink): LongInt;
asm
  test edx,edx
  jz @NotFound
  mov ecx,eax
  xor eax,eax
@loop:
  cmp ecx,TChainLink[edx].FValue
  je @Exit
  inc eax
  mov edx,[edx]
  test edx,edx
  jnz @loop
@NotFound:
  mov eax,-1
@Exit:
end;
//-------------------------------------------------------------
// Извлечение первого звена, для которого ACallBackFunc выдаст True
// Внимание! Найденный элемент отсоединяется от цепочки. Для присоединения к другой цепочке используйте LinkTo, для освобождения памяти - TChainPool.FreeLink

function FindAndUnlink(var AAnchor: PChainLink; ACallBackFunc:
  TScanChainCallBack; AParm: Pointer = nil): PChainLink; assembler;
var
  pParm: Pointer;
asm
  push edi
  push esi
  mov esi,eax // esi <= AAnchor
  mov eax,AParm
  mov pParm,eax
  mov edi,edx // edi <= ACallBackFunc
@NextLink:
  mov eax,[esi]
  mov edx,pParm
  call edi
  test eax,eax
  jnz @Unlink
  mov esi,[esi]
  test esi,esi
  jnz @NextLink
  xor eax,eax // для всех получили отказ
  jmp @Exit

@Unlink:
  mov eax,[esi]
  mov edx,[eax]
  mov [esi],edx
  mov dword ptr [eax],0
@Exit:
  pop esi
  pop edi
end;
//-------------------------------------------------------------

function ChainLinkByIndex(AAnchor: PChainLink; AIndex: Integer): PChainLink;
  assembler;
asm
  test eax,eax
  jz @Exit
  test edx,edx
  jz @Exit
@Next:
  mov eax,[eax]
  test eax,eax
  jz @Exit
  dec edx
  jnz @Next
@Exit:
end;
//-------------------------------------------------------------

function ChainLinkCount(AAnchor: PChainLink): Integer;
asm
  test eax,eax
  jz @Exit
  xor edx,edx
@Next:
  mov eax,[eax]
  inc edx
  test eax,eax
  jnz @Next
  mov eax,edx
@Exit:
end;

//==TChainPool===========================================================

constructor TChainPool.Create(AItemSize: Integer = SizeOf(TChainLink));
begin
  inherited Create;
  FPLastBuffer := @FFirstBuffer;
  FItemSize := AItemSize;
end;
//-------------------------------------------------------------

destructor TChainPool.Destroy;
begin
  FreeBuffers;
  inherited Destroy;
end;
//-------------------------------------------------------------

procedure TChainPool.FreeBuffers;
var
  pBuf: PPoolBuffer;
begin
  while FFirstBuffer <> nil do
  begin
    pBuf := FFirstBuffer;
    FFirstBuffer := FFirstBuffer^.FNextBuf;
    VirtualFree(pBuf, 0, MEM_RELEASE);
  end;
  FPLastBuffer := @FFirstBuffer;
  FFreeChain := nil;
  FRest := 0;
  FTop := nil;
end;
//-------------------------------------------------------------

function TChainPool.Allocate(const ASize: LongWord): Pointer;
var
  nSize: LongInt;
  pBuf: PPoolBuffer;
begin
  if FRest < ASize then
  begin
    nSize := (4095 + ASize + SizeOf(TPoolBuffer)) and (-4096);
    pBuf := PPoolBuffer(VirtualAlloc(nil, nSize, MEM_COMMIT, PAGE_READWRITE));
    if pBuf = nil then
      GetMem(pBuf, not 0);
        // raise Exception.Create('ChainPools: Out of memory'); - SysUtils required
    FPLastBuffer^ := pBuf;
    FPLastBuffer := @(pBuf^.FNextBuf);
    FTop := PChar(pBuf) + SizeOf(TPoolBuffer);
    FRest := nSize - SizeOf(TPoolBuffer);
  end;
  Dec(FRest, ASize);
  Result := FTop;
  Inc(FTop, ASize);
end;
//-------------------------------------------------------------

function TChainPool.AddValue(const Value: LongInt; var AAnchor: PChainLink):
  Boolean; assembler;
asm
  push edi
  push esi
  xor esi,esi
  mov edi,eax
  mov eax,[ecx]
  test eax,eax
  jz @@New
@@Compare:
  cmp edx,[eax].TChainLink.FValue
  je @@Done
  mov ecx,eax
  mov eax,[ecx]
  test eax,eax
  jnz @@Compare
@@New:
  inc esi
  push edx
  mov eax,edi
  mov edi,ecx
  call TChainPool.NewLink
  mov ecx,edi
@@Link:
  pop edx
  mov [eax].TChainLink.FValue,edx
  mov dword ptr [eax],0
  mov [ecx],eax
@@Done:
  mov eax,esi
  pop esi
  pop edi
end; {TChainPool.AddValue}
//-------------------------------------------------------------

procedure TChainPool.PutValue(const Value: LongInt; var AAnchor: PChainLink);
  assembler;
asm
  push edi
  mov edi,eax
  push edx
  push ecx
  call TChainPool.NewLink
  pop ecx
  pop edx
  mov TChainLink[eax].FValue,edx
  mov edx,[ecx]
  mov [eax],edx
  mov [ecx],eax
@@Done:
  pop edi
end; {TChainPool.PutValue}
//-------------------------------------------------------------
// Вставка перед звеном, на которое ACallBackFunc выдаст True
// Будет предложено также вставить в конец - будет вызов ACallBackFunc с ALink=nil
// TChainLinkCallBack = function ( const Value : LongInt; const ALink : PChainLink; AParm : Pointer ) : Boolean;

function TChainPool.InsertValue(const Value: LongInt; var AAnchor: PChainLink;
  ACallBackFunc: TChainLinkCallBack; AParm: Pointer = nil): PChainLink; assembler;
var
  pSelf: LongInt;
asm
  push edi
  push esi
  mov pSelf,eax
  mov edi,edx // edi <= Value
  mov esi,ecx // esi <= AAnchor
@NextLink:
  mov eax,edi // AValue
  mov edx,[esi]
  mov ecx,AParm
  call [ACallBackFunc]
  test eax,eax
  jnz @Insert
  mov esi,[esi]
  test esi,esi
  jnz @NextLink
  xor eax,eax // для всех получили отказ
  jmp @Exit

@Insert:
  mov eax,pSelf
  call TChainPool.NewLink
  mov TChainLink[eax].FValue,edi
  mov edx,[esi]
  mov [eax],edx
  mov [esi],eax
@Exit:
  pop esi
  pop edi
end; {TChainPool.InsertValue}
//-------------------------------------------------------------
// CallBack для InsertSorted

function ChainLinkAscending(const Value: LongInt; const ALink: PChainLink;
  AParm: Pointer): Boolean;
begin
  Result := (Value < ALink.FValue);
end;
// вставка в цепочку в порядке возврастания Value

function TChainPool.InsertSorted(const Value: LongInt; var AAnchor: PChainLink):
  PChainLink;
begin
  Result := InsertValue(Value, AAnchor, ChainLinkAscending);
end;
//-------------------------------------------------------------
// освобождение элемента - перенос в список FFreeChain (элемент не должен принадлежать какой-либо цепочке)

procedure TChainPool.FreeLink(const ALink: PChainLink);
begin
  ALink^.FNext := FFreeChain;
  FFreeChain := ALink;
end;
//-------------------------------------------------------------
// создает новый элемент, непривязанный к какой-либо цепочке

function TChainPool.NewLink: PChainLink;
asm
  mov ecx,TChainPool[eax].FFreeChain
  test ecx,ecx
  jz @Allocate
  mov edx,[ecx]
  mov TChainPool[eax].FFreeChain,edx
  push ecx
  mov edx,TChainPool[eax].FItemSize
  mov eax,ecx
  mov ecx,0
  call System.@FillChar
  pop eax
  jmp @Exit
@Allocate:
  mov edx,TChainPool[eax].FItemSize
  call TChainPool.Allocate
@Exit:
end;
//-------------------------------------------------------------

function TChainPool.GetValue(var AAnchor: PChainLink): LongInt; assembler;
asm
  mov ecx,[edx]
  test ecx,ecx
  jnz @@1
  xor eax,eax
  jmp @@Exit

@@1:
  push edi
  mov edi,[ecx]
  mov [edx],edi
  mov edi,[eax].TChainPool.FFreeChain
  mov [ecx],edi
  mov [eax].TChainPool.FFreeChain,ecx
  pop edi
  mov eax,[ecx].TChainLink.FValue
@@Exit:
end;
//-------------------------------------------------------------

function TChainPool.GetFirstLink(var AAnchor: PChainLink): PChainLink;
  assembler;
asm
  mov eax,[edx]
  test eax,eax
  jz @Empty
  mov ecx,[eax]
  mov [edx],ecx
  mov dword ptr[eax],0
@Empty:
end;
//-------------------------------------------------------------

function TChainPool.RemoveValue(const Value: LongInt; var AAnchor: PChainLink):
  Boolean; assembler;
asm
  test eax,eax
  jz @@Exit
  push edi
  mov edi,eax
  jmp @@Start
@@Next:
  mov ecx,eax
@@Start:
  mov eax,[ecx]
  test eax,eax
  jz @@Done
  cmp edx,TChainLink[eax].FValue
  jne @@Next
  mov edx,[eax] // FNext
  mov [ecx],edx
  mov edx,TChainPool[edi].FFreeChain
  mov [eax],edx
  mov TChainPool[edi].FFreeChain,eax
  mov eax,1
@@Done:
  pop edi
@@Exit:
end;
//-------------------------------------------------------------

function TChainPool.RemoveLink(const ALink: PChainLink; var AAnchor:
  PChainLink): Boolean; assembler;
asm
  test eax,eax
  jz @@Exit
  push edi
  mov edi,eax
  test edx,edx
  jz @@False
  test ecx,ecx
  jnz @@Start
@@False:
  xor eax,eax
  jmp @@Done

@@Next:
  mov ecx,eax
@@Start:
  mov eax,[ecx]
  test eax,eax
  jz @@Done
  cmp edx,eax
  jne @@Next
  mov eax,[edx]
  mov [ecx],eax
  mov eax,[edi].TChainPool.FFreeChain
  mov [edx],eax
  mov [edi].TChainPool.FFreeChain,edx
  mov eax,1
@@Done:
  pop edi
@@Exit:
end;
//-------------------------------------------------------------

function TChainPool.GetLastValue(var AAnchor: PChainLink): LongInt; assembler;
asm
  mov ecx,[edx]
  test ecx,ecx
  jnz @@Start
  xor eax,eax
  jmp @@Exit

@@Next:
  mov edx,ecx
  mov ecx,[edx]
@@Start:
  cmp dword ptr [ecx],0
  jnz @@Next
  mov dword ptr [edx],0
  mov edx,[eax].TChainPool.FFreeChain
  mov [ecx],edx
  mov [eax].TChainPool.FFreeChain,ecx
  mov eax,[ecx].TChainLink.FValue
@@Exit:
end;
//-------------------------------------------------------------

function TChainPool.GetLastLink(var AAnchor: PChainLink): PChainLink; assembler;
asm
  mov eax,[edx]
  test eax,eax
  jz @Empty
  mov ecx,[eax]
  test ecx,ecx
  jz @Finish
@@Next:
  mov edx,eax
  mov eax,ecx
  mov ecx,[eax]
  test ecx,ecx
  jnz @@Next
@Finish:
  mov dword ptr [edx],0
@Empty:
end;
//-------------------------------------------------------------

procedure TChainPool.FreeChain(var AAnchor: PChainLink); assembler;
asm
  test eax,eax
  jz @@Exit
  test edx,edx
  jz @@Exit
  add eax,offset(TChainPool.FFreeChain)
  mov ecx,[edx]
  xchg ecx,[eax]
  mov eax,[edx]
  mov dword ptr[edx],0
  test eax,eax
  jz @@Done
@@Next:
  mov edx,eax
  mov eax,[edx]
  test eax,eax
  jnz @@Next
@@Done:
  mov [edx],ecx
@@Exit:
end;

end.

Пример использования:

program Test;

{$APPTYPE CONSOLE}
uses
  ChainPools;

type
  PItem = ^TItem;
  TItem = packed record
    FNext: PItem;
    FValue: LongInt;
    FValue2: LongInt;
  end;

  // It is just a holder of method.
  // In real life use forms or other objects.
  TSomeClass = class
    function FindValue2(ALink: PChainLink; AParm: Pointer): Boolean;
  end;

function TSomeClass.FindValue2(ALink: PChainLink; AParm: Pointer): Boolean;
begin
  Result := PLongInt(AParm)^ = PItem(ALink)^.FValue2;
end;

var
  oChainPool: TChainPool;
  pFirst1: PItem; // pointer to the first item in chain 1
  pFirst2: PItem; // pointer to the first item in chain 2
  ptr: PItem;
  nValue: LongInt;
  i: Integer;
  oSomeObject: TSomeClass;
begin

  oSomeObject := TSomeClass.Create;

  pFirst1 := nil;
  pFirst2 := nil;
  oChainPool := TChainPool.Create(SizeOf(TItem));

  // Put some values in chain 1
  for i := 0 to 99 do
    oChainPool.AddValue(i, PChainLink(pFirst1));

  // Put some values in chain 2
  for i := 0 to 99 do
  begin
    ptr := PItem(oChainPool.NewLink);
    with ptr^ do
    begin
      // put here the code that fills in new item's fields.
      FValue := i;
      FValue2 := 100 - i;
    end;
    ChainPools.LinkTo(PChainLink(ptr), PChainLink(pFirst2));
  end;

  // Example for scanning chain.
  nValue := 30;
  ptr := PItem(ChainPools.ScanChain(PChainLink(pFirst2), oSomeObject.FindValue2,
    @nValue));
  if ptr = nil then
    WriteLn('Item is not found')
  else
    WriteLn('FValue = ', ptr^.FValue);

  // Scan chain
  ptr := pFirst2;
  while ptr <> nil do
  begin
    if ptr^.FValue2 = 30 then
    begin
      WriteLn('FValue = ', ptr^.FValue);
      Break;
    end;
    ptr := ptr^.FNext;
  end;

  // Destroy pool
  oChainPool.Free;

end.
Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay