home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* SWAP.PAS *)
- (* Das Modul erlaubt das Auslagern von dynamischen *)
- (* Variablen in eine Disketten-/Plattendatei. *)
- (* (c) 1991 Ralf Homburg & TOOLBOX *) }
- (* ------------------------------------------------------ *)
- {$I-}
- UNIT Swap;
-
- INTERFACE
-
- CONST
- SwapFile = 'SwapFile'; { Name der Swapdatei. Kann be- }
- { liebig gewählt werden. }
- SwapSign = -123454321; { Kennung zur Unterscheidung von }
- { geswapten und nicht geswapten }
- { Zeigern. }
-
- FUNCTION SwappedOut(VAR Ptr) : BOOLEAN;
- { "Ptr" ist ein beliebiger Zeiger. SwappedOut gibt TRUE }
- { zurück, wenn der Inhalt des Zeigers mit SwapOut ausge- }
- { lagert wurde. Die Funktion kann z.B. dazu genutzt wer- }
- { den, um festzustellen, ob SwapIn bzw. SwapOut erfolg- }
- { reich waren. }
-
- PROCEDURE SwapOut(VAR Ptr; Size : WORD);
- { "Ptr" ist ein beliebiger Zeiger, der auf einen mit New }
- { bzw. GETMEM zugewiesenen Speicherbereich von "Size" }
- { Bytes zeigt. SwapOut sichert den Inhalt des Zeigers in }
- { die mit "SwapFile" festgelegte Swap-Datei. Der von }
- { "Ptr" belegte Heap wird freigegeben, sofern kein Da- }
- { teifehler beim Speichern aufgetreten ist, und der Zei- }
- { ger "Ptr" wird auf eine zum Zurückladen des alten In- }
- { halts erforderliche Struktur verbogen. }
- { Achtung! Der Zeiger darf bis zum Aufruf von SwapIn }
- { nicht mehr manipuliert werden! }
-
- PROCEDURE SwapIn(VAR Ptr);
- { "Ptr" ist ein mit SwapOut geswappter Zeiger. SwapIn re- }
- { stauriert die in der Swapdatei gespeicherten Daten des }
- { Zeigers. Dazu muß allerdings ausreichend Platz auf dem }
- { Heap vorhanden sein. Ansonsten wird der Aufruf von }
- { SwapIn ignoriert. }
-
-
- IMPLEMENTATION
-
- TYPE
- BlockPtr = ^Block;
- Block = RECORD
- Sign,
- FirstRec,
- LastRec : LONGINT;
- Prev,
- Next : BlockPtr;
- END;
- VAR
- OldExitProc : Pointer;
- FirstFree,
- LastFree,
- FirstUsed,
- LastUsed : BlockPtr;
- SFile : FILE;
-
- PROCEDURE InsertBlock(VAR First, Last, Block : BlockPtr);
- BEGIN
- Block^.Next := NIL;
- Block^.Prev := Last;
- IF Last <> NIL THEN
- Last^.Next := Block;
- Last := Block;
- IF First = NIL THEN
- First := Block;
- END;
-
- PROCEDURE RemoveBlock(VAR First, Last, Block : BlockPtr);
- BEGIN
- IF Block^.Prev <> NIL THEN
- Block^.Prev^.Next := Block^.Next
- ELSE
- First := Block^.Next;
- IF Block^.Next <> NIL THEN
- Block^.Next^.Prev := Block^.Prev
- ELSE
- Last := Block^.Prev;
- END;
-
- FUNCTION SwappedOut(VAR Ptr) : BOOLEAN;
- VAR
- Block : BlockPtr ABSOLUTE Ptr;
- BEGIN
- SwappedOut := (Block^.Sign = SwapSign);
- END;
-
- FUNCTION GetFreeBlock(Size : WORD) : BlockPtr;
- VAR
- Block : BlockPtr;
- BEGIN
- Block := FirstFree;
- WHILE (Block <> NIL) AND
- (Block^.LastRec - Block^.FirstRec + 1 < Size) DO
- Block := Block^.Next;
- IF Block = NIL THEN BEGIN
- New(Block);
- Block^.FirstRec := FileSize(SFile);
- Block^.LastRec := Block^.FirstRec + Size - 1;
- InsertBlock(FirstFree, LastFree, Block);
- END;
- GetFreeBlock := Block;
- END;
-
- PROCEDURE SetBlockFree(VAR Block : BlockPtr);
- VAR
- Search : BlockPtr;
- Found : BOOLEAN;
- BEGIN
- InsertBlock(FirstFree, LastFree, Block);
- Search := FirstFree;
- Found := FALSE;
- WHILE (Search <> NIL) AND NOT(Found) DO BEGIN
- IF Search^.FirstRec - 1 = Block^.LastRec THEN BEGIN
- Search^.FirstRec := Block^.FirstRec;
- RemoveBlock(FirstFree, LastFree, Block);
- Dispose(Block);
- Block := Search;
- Found := TRUE;
- END;
- Search := Search^.Next;
- END;
- Search := FirstFree;
- Found := FALSE;
- WHILE (Search <> NIL) AND NOT(Found) DO BEGIN
- IF Search^.LastRec + 1 = Block^.FirstRec THEN BEGIN
- Search^.LastRec := Block^.LastRec;
- RemoveBlock(FirstFree, LastFree, Block);
- Dispose(Block);
- Found := TRUE;
- END;
- Search := Search^.Next;
- END;
- END;
-
- PROCEDURE SwapOut(VAR Ptr; Size : WORD);
- VAR
- Data : Pointer ABSOLUTE Ptr;
- Block,
- Free : BlockPtr;
- Result : WORD;
- BEGIN
- IF (Data <> NIL) AND NOT SwappedOut(Ptr) THEN BEGIN
- Free := GetFreeBlock(Size);
- Seek(SFile, Free^.FirstRec);
- BlockWrite(SFile, Data^, Size, Result);
- IF (IOResult = 0) AND (Result = Size) THEN BEGIN
- New(Block);
- Block^.Sign := SwapSign;
- Block^.FirstRec := Free^.FirstRec;
- Block^.LastRec := Block^.FirstRec + Size - 1;
- InsertBlock(FirstUsed, LastUsed, Block);
- FreeMem(Data, Size);
- Data := Block;
- IF Free^.LastRec > Block^.LastRec THEN
- Free^.FirstRec := Block^.LastRec + 1
- ELSE BEGIN
- RemoveBlock(FirstFree, LastFree, Free);
- Dispose(Free);
- END;
- END;
- END;
- END;
-
- PROCEDURE SwapIn(VAR Ptr);
- VAR
- Data : Pointer;
- Block : BlockPtr ABSOLUTE Ptr;
- Size,
- Result : WORD;
- BEGIN
- Size := Block^.LastRec - Block^.FirstRec + 1;
- IF (Block <> NIL) AND (SwappedOut(Ptr)) AND
- (MaxAvail >= Size) THEN BEGIN
- GetMem(Data, Size);
- Seek(SFile, Block^.FirstRec);
- BlockRead(SFile, Data^, Size, Result);
- IF (IOResult = 0) AND (Result = Size) THEN BEGIN
- RemoveBlock(FirstUsed, LastUsed, Block);
- SetBlockFree(Block);
- Pointer(Ptr) := Data;
- END ELSE
- FreeMem(Data, Size);
- END;
- END;
-
- {$F+}
- PROCEDURE NewExitProc;
- BEGIN
- ExitProc := OldExitProc;
- Close(SFile);
- Erase(SFile);
- END;
- {$F-}
-
- BEGIN
- FirstFree := NIL;
- LastFree := NIL;
- FirstUsed := NIL;
- LastUsed := NIL;
- OldExitProc := ExitProc;
- ExitProc := @NewExitProc;
- Assign(SFile, SwapFile);
- Rewrite(SFile, 1);
- IF IOResult <> 0 THEN Halt;
- END.
- (* ------------------------------------------------------ *)
- (* Ende von SWAP.PAS *)
-
-
-