UNIT-UL OVERLAY
La programe foarte mari - formate dintr-un program principal si un mare numar de unit-uri proprii - exista situatii cand memoria disponibila este insuficienta pentru incarcarea simultana a tuturor unit-urilor. Compilatorul Turbo Pascal pune la dispozitia utilizatorului un numar de proceduri si functii standard - depuse in unit-ui Overlay - care implementeaza o tehnica de acoperire. Aceasta tehnica permite ca unele unit-uri, desemnate de utilizator prin directiva de compilare sa fie incarcate in memorie odata cu programul care le utilizeaza. 444g68e Un unit astfel desemnat va fi incarcat in memorie - intr-o zona denumita tampon de acoperire numai atunci cand o procedura sau functie definita in unit-ul respectiv este efectiv apelata.
Tamponul de acoperire (a carui lungime este initializata de compilator), in functie de lungimea tamponului poate sa contina in principiu mai multe unit-uri.
Un unit care a fost introdus in tamponul de acoperire va ramane in memorie pana cand este apelat un unit care nu se gaseste in tamponul plin, in acest moment unit-ul introdus prima data in tampon va fi inlocuit (reacoperit) de unit-ul recent apelat. Deci tamponul de acoperire, in momente diferite, va contine unit-uri distincte.
Unit-urile care sunt desemnate de
programul principal prin directivele
trebuie compilate cu optiunile si , plasate inaintea
declaratiei de antet unit nume.
Activitatea de initiere a folosirii tehnicii
de acoperire este realizata de procedura Ovrinit.
Aceasta procedura deschide un fisier pe disc in care introduce toate acele
unit-uri, care au fost selectate cu directivele de compilare
. Incarcarea unit-urilor in tamponul de acoperire va fi realizata
din fisierul astfel desemnat. Apelul acestei proceduri trebuie realizat in
programul principal inaintea apelului oricarei alte proceduri si functii care
gestioneaza tehnica de acoperire.
Procedura Ovrinit se defineste astfel:
procedure Ovrinit (FileName:string);
unde FileName este numele fisierului fizic care contine toate unit-urile implicate in activitatea de acoperire. Fisierul desemnat are extensia implicita .OVR.
Functia OvrGetBuf returneaza (in numar de octeti) dimensiunea initiala sau actuala a tamponului de acoperire.
Functia se defineste astfel:
function OvrGetBuf: Longint;
Modificarea dimensiunii tamponului de acoperire poate fi realizata cu procedura OvrSetBuf, care se defineste astfel:
procedure OvrSetBuf (BufSize: Longint);
unde BufSize precizeaza noua dimensiune a tamponului. Aceasta valoare trebuie sa fie mai mare decat dimensiunea originala a tamponului, dar mai mica decat dimensiunea originala majorata a valorii returnate de functia MemAvail.
Stergerea continutului tamponului de acoperire poate fi realizata cu procedura OvrClearBuf, care se defineste astfel:
procedare OvrClearBuf;
Mentionam ca daca aceasta procedura este apelata dintr-un unit participant la activitatea de acoperire, unit-ul respectiv va fi sters din tampon si imediat reincarcat.
Pentru ridicarea performantelor operatiilor de incarcare din fisierul desemnat de Ovrinit in tamponul de acoperire s-a preconizat utilizarea memoriei EMS (Expanded Memory System).
Procedura Ovrinit EMS definita prin:
procedure OvrinitEMS:
incarca fisierul desemnat de procedura Ovrinit in memoria EMS (daca aceasta are capacitate suficienta). Orice incarcare in tamponul de acoperire se va face din aceasta memorie rapida si nu din unitatea de disc. Dupa terminarea programului memoria EMS este automat eliberata.
In sectiunea de interfata a unit-uiui Overlay este definita o variabila de tip integer, numita OvrResult care contine codul de eroare rezultat in urma unui apel de procedura sau functie referitoare la gestiunea tehnicii de acoperire. Daca variabila OvrResult este incarcata cu valoarea zero, inseamna ca procedura sau functia apelata anterior s-a terminat cu succes, sau o valoare negativa inseamna esec.
Valorile predefinite ale acestei variabile sunt:
const
OvrOK := 0;
OvrError := -1;
OvrNotFound := -2;
OvrNoMemory = -3;
OvrlOError := -4;
OvrNoEMSDriver = -5,
QvrNoEMSMemory := -6,
Compilatorul Turbo Pascal a pus la dispozitia utilizatorului cateva facilitati destinate ridicarii performantelor sistemului de gestiune al acoperirilor.
S-a vazut ca atunci cand tamponul de acoperire este ocupat in asa fel incat nu mai este spatiu suficient incarcarii unui nou unit apelat, tamponul este golit, fiind indepartat unit-ul cel mai vechi introdus. Astfel exista pericolul sa fie indepartat din tampon un unit frecvent apelat: dupa indepartarea unitatii, unit-ul respectiv va fi imediat reincarcat. Aceasta indepartare - reincareare se datoreste faptului ca sistemul de gestiune al acoperirilor nu cunoaste nimic despre frecventa apelurilor subprogramelor unit-ului. In noua versiune s-a introdus o schema de incercare/amanare in mecanismul de gestiune, o zona din tamponul de acoperire este rezervata memorarii unit-ului pentru care exista pericolul de a fi eliminat ia urmatoarea intentie de introducere in tampon. Se intercepteaza numarul acceselor la subprogramele care apartin unit-ului in 'pericol'. Daca pana la intentia de eliminare s-a interceptat un apel, unit-ul respectiv va fi pastrat in tamponul de acoperire, urmand sa fie eliminat un alt unit. Daca nu s-a interceptat nici un apel, unit-ul analizat va fi eliminat din tampon.
Procedura OvrSctRetry definita prin:
procedura OvrSetRetry(dim: longint);
stabileste prin valoarea din dim dimensiunea zonei de 'incercari/amanari'. Nu exista formula empirica pentru determinarea dimensiunii optime a acestei zone. Experientele au aratat ca cele mai bune rezultate se obtin atunci cand aceasta valoare este 30-50% din dimensiunea tamponului de acoperire. lata un exemplu de utilizare:
Ovrlnit('TEST.OVR'); OvrSetBuf(DimBuf); OvrSetRetry (DimBuf div 3);
Functia OvrGetRetry definita prin:
function OvrGetRetry:Longint;
returneaza dimensiunea actuala a zonei de 'incercari/amanari', adica dimensiunea fixata de apelul cel mai recent al procedurii OvrSetRetry.
Din motive de compatibilitate cu versiunile mai vechi ale sistemului de gestiune al acoperirii, dimensiunea implicita a zonei de 'incercari/amanari' este initializata cu zero, fapt ce dezactiveaza mecanismul de mentinere in memorie a unit-urilor frecvent folosite
In exemplul urmator sunt create doua unit-uri (cu numele Ovr1 respectiv Ovr2), care sunt compilate pe disc, rezultatele celor doua compilari vor fi doua fisiere cu numele Ovr1.tpl si Ovr2.tpl. Ambele unit-uri contin optiunile de compilare si .
Programul principal testovr va utiliza unit-urile Ovrl si Ovr2 ca unitati de acoperire, fapt desemnat prin plasarea dupa clauza uses a directivelor si . Programul este compilat cu optiunea si . Numele fisierului disc care contine unit-urile ele acoperire este testovr.ovr.
program testovr;
uses Overlay, Crt, Ovrl, Ovr2;
{$O Ovr2)
begin
TextAttr:=white;
ClrScr;
Ovrinit ('testovr.ovr');
if OvrResult <> 0 then
writeln ('Eroare Overlay:', OvrResult); halt(1);
end.
repeat
scr1;
scr2;
until keypressed;
unit Ovr1;
inrerface scr1;
procedure scr1;
implementation
procedure scr1;
begin
writeln ('Unii ');
end;
end.
interface
procedure scr2;
implementation
procedure scr2;
begin
writeln ('Doi'),
end;
end.
|