18.04.2013 Views

Tehnici de implementare a concurentei în analiza si proiectarea ...

Tehnici de implementare a concurentei în analiza si proiectarea ...

Tehnici de implementare a concurentei în analiza si proiectarea ...

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

UNIVERSITATEA "BABES - BOLYAI" CLUJ-NAPOCA<br />

FACULTATEA DE MATEMATICA SI INFORMATICA<br />

<strong>Tehnici</strong> <strong>de</strong> <strong>implementare</strong> a <strong>concurentei</strong><br />

<strong>în</strong> <strong>analiza</strong> <strong>si</strong> <strong>proiectarea</strong> orientata pe obiecte<br />

TEZA DE DOCTORAT<br />

CONDUCATOR STIINTIFIC: DOCTORAND:<br />

prof. dr. Grigor MOLDOVAN Dan Mircea SUCIU<br />

2001


Prefata<br />

Automatizarea etapelor ciclului <strong>de</strong> <strong>de</strong>zvoltare a aplicatiilor constituie un<br />

subiect fierbinte <strong>în</strong> comunitatea informatica. Lucrarea <strong>de</strong> fata î<strong>si</strong> propune sa aduca o<br />

contributie <strong>în</strong> aceasta directie, <strong>în</strong> special <strong>în</strong> cazul aplicatiilor orientate-obiect<br />

concurente.<br />

Doresc sa aduc multumiri <strong>si</strong>ncere domnului profesor univer<strong>si</strong>tar doctor Grigor<br />

Moldovan pentru <strong>în</strong>telegerea, rabdarea <strong>si</strong> tactul pedagogic pe care le-a dovedit fata <strong>de</strong><br />

mine. Consultarile <strong>si</strong> dicutiile care au <strong>în</strong>sotit activitatea comuna <strong>de</strong> cercetare au<br />

influentat <strong>în</strong> mod hotarâtor calitatea <strong>si</strong> <strong>de</strong>finitivarea lucrarii <strong>de</strong> fata.<br />

Domnului lector doctor Dan Chiorean îi multumesc pentru <strong>în</strong>treg sprijinul,<br />

solicitudinea <strong>si</strong> <strong>în</strong>curajarile oferite <strong>în</strong> diverse împrejurari. Domnia sa a fost primul<br />

meu <strong>în</strong>drumator stiintific <strong>si</strong> cel care m-a <strong>de</strong>terminat sa iau <strong>de</strong>cizii corecte <strong>în</strong> momente<br />

importante ale vietii mele. Faptul ca lucrarea <strong>de</strong> fata exista i se datoreaza <strong>în</strong>tr-o<br />

covâr<strong>si</strong>toare masura dânsului.<br />

Colegilor <strong>si</strong> prietenilor mei Dorel Bozga, Ileana Ober, Iulian Ober <strong>si</strong> Marian<br />

Scuturici le multumesc pentru lungile discutii avute împreuna, discutii care au avut un<br />

rol <strong>de</strong>terminant <strong>în</strong> <strong>de</strong>finitivarea tezei <strong>în</strong> forma actuala. De asemenea, multumesc<br />

tuturor colegilor din cadrul Laboratorului <strong>de</strong> Cercetare <strong>în</strong> Informatica alaturi <strong>de</strong> care<br />

am petrecut momente <strong>de</strong> neuitat.<br />

Multumesc colegilor din Departamentul <strong>de</strong> Informatica pentru suportul,<br />

dicutiile <strong>si</strong> sugestiile utile care au condus la o mai buna structurare a continutului<br />

lucrarii.<br />

1<br />

Cluj-Napoca, mai 2001


Cuprins<br />

1. Introducere ...............................................................................................................4<br />

1.1. Contextul programarii orientate-obiect concurente............................................4<br />

1.2. Meto<strong>de</strong> <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare a aplicatiilor ....................................................7<br />

1.3. Contributiile originale ale tezei...........................................................................8<br />

1.4. Structura tezei....................................................................................................10<br />

2. Specificarea <strong>si</strong> coordonarea <strong>concurentei</strong> <strong>în</strong> programarea orientata-obiect<br />

concurenta ..............................................................................................................12<br />

2.1. Introducere ........................................................................................................12<br />

2.2. Principii <strong>de</strong> proiectare a limbajelor <strong>de</strong> programare orientate-obiect conc......13<br />

2.3. Mecanisme <strong>de</strong> specificare a <strong>concurentei</strong>...........................................................20<br />

2.4. Mecanisme <strong>de</strong> interactiune <strong>si</strong> <strong>si</strong>ncronizare a obiectelor concurente................24<br />

2.2.1. Mecanisme <strong>de</strong> interactiune orientate pe operatii ................................................ 27<br />

2.2.2. Mecanisme <strong>de</strong> interactiune concurenta bazate pe <strong>în</strong>capsulare............................. 32<br />

2.5. Concluzii ............................................................................................................53<br />

3. Anomalii <strong>de</strong> mostenire ...........................................................................................55<br />

3.1. Introducere ........................................................................................................55<br />

3.2. Cla<strong>si</strong>ficari ale anomaliilor <strong>de</strong> mostenire...........................................................57<br />

3.2.1. Cla<strong>si</strong>ficarea Matsuoka-Yonezawa.................................................................... 58<br />

3.2.2. Cla<strong>si</strong>ficarea Zeng-Schach................................................................................ 63<br />

3.2.3. Anomalii <strong>de</strong> reutilizare.................................................................................... 64<br />

3.3. Formalizarea anomaliilor <strong>de</strong> mostenire............................................................67<br />

3.4. Mo<strong>de</strong>larea principiilor <strong>de</strong> proiectare ale limbajelor orientate-obiect conc .....82<br />

3.5. Concluzii ............................................................................................................86<br />

4. Mo<strong>de</strong>larea comportamentului obiectelor active .................................................89<br />

2


4.1. Introducere ........................................................................................................89<br />

4.2. Sisteme reactive.................................................................................................90<br />

4.3. Harti <strong>de</strong> stari......................................................................................................93<br />

4.3.1. Structura hartilor <strong>de</strong> stari................................................................................. 93<br />

4.3.2. Timp <strong>de</strong> executie ............................................................................................ 97<br />

4.3.3. Pseudostari..................................................................................................... 99<br />

4.4. Utilizarea hartilor <strong>de</strong> stari <strong>în</strong> mo<strong>de</strong>larea obiectelor active.............................100<br />

4.5. Harti <strong>de</strong> stari scalabile ....................................................................................109<br />

4.5.1. Mo<strong>de</strong>lul obiect ..............................................................................................109<br />

4.5.2. Definirea hartilor <strong>de</strong> stari scalabile ..................................................................111<br />

4.5.3. Executabilitatea hartilor <strong>de</strong> stari scalabile ........................................................125<br />

4.6. Concluzii ..........................................................................................................128<br />

5. ActiveCASE - instrument <strong>de</strong> mo<strong>de</strong>lare <strong>si</strong> <strong>si</strong>mulare a comportamentului<br />

obiectelor active ...................................................................................................130<br />

5.1. Introducere ......................................................................................................130<br />

5.2. Meta-mo<strong>de</strong>lul hartilor <strong>de</strong> stari scalabile.........................................................132<br />

5.2.1. Mo<strong>de</strong>larea hartilor <strong>de</strong> stari <strong>în</strong> UML.................................................................132<br />

5.2.2. Mo<strong>de</strong>larea hartilor <strong>de</strong> stari scalabile <strong>în</strong> ActiveCASE ........................................134<br />

5.3. Descrierea aplicatiei ActiveCASE...................................................................139<br />

5.3. Mo<strong>de</strong>larea <strong>si</strong> testarea unei aplicatii <strong>de</strong> <strong>si</strong>mulare a traficului <strong>de</strong> ma<strong>si</strong>ni.........143<br />

5.4. Concluzii ..........................................................................................................148<br />

6. Concluzii ...............................................................................................................151<br />

6.1. Rezultate obtinute ............................................................................................151<br />

6.2. Perspective.......................................................................................................152<br />

6.2.1. Anomalii <strong>de</strong> reutilizare...................................................................................152<br />

6.2.2. Mo<strong>de</strong>larea <strong>si</strong> <strong>si</strong>mularea aplicatiilor orientate-obiect concurente.........................153<br />

Bibliografie ...............................................................................................................155<br />

Anexa A. Notatii matematice ..................................................................................164<br />

A.1. Multimi ............................................................................................................164<br />

A.2. Relatii binare...................................................................................................164<br />

A.3. Functii .............................................................................................................165<br />

Anexa B. Notatii UML.............................................................................................166<br />

B.1. Diagrame <strong>de</strong> clase...........................................................................................167<br />

B.2. Harti <strong>de</strong> stari ...................................................................................................168<br />

3


1. Introducere<br />

1.1. Contextul programarii orientate-obiect concurente<br />

Problema unificarii conceptelor programarii orientate-obiect cu mecanismele<br />

specifice programarii concurente reprezinta o preocupare constanta <strong>în</strong> lumea<br />

informaticii <strong>în</strong> ultimele doua <strong>de</strong>cenii. Aceasta preocupare este justificata <strong>de</strong> puterea<br />

ridicata <strong>de</strong> mo<strong>de</strong>lare, proprie limbajelor orientate-obiect, <strong>si</strong> puterea <strong>de</strong> calcul, proprie<br />

limbajelor concurente, care au facut ca limbajele <strong>de</strong> programare orientate-obiect<br />

concurente sa fie aplicabile <strong>în</strong>tr-un numar <strong>în</strong>semnat <strong>de</strong> domenii, cum ar fi: <strong>si</strong>stemele<br />

<strong>de</strong> operare distribuite, inteligenta artificiala distribuita, <strong>si</strong>mularea distribuita, baze <strong>de</strong><br />

date distribuite, <strong>de</strong>zvoltarea <strong>de</strong> <strong>si</strong>steme <strong>în</strong> timp real, controlul proceselor distribuite,<br />

<strong>proiectarea</strong> <strong>de</strong> arhitecturi multi-procesor etc.<br />

Programarea orientata-obiect concurenta se bazeaza pe metodologia<br />

programarii orientate-obiect 1 , care este recunoscuta <strong>în</strong> acest moment ca fiind<br />

metodologia <strong>de</strong> vârf pentru <strong>de</strong>zvoltarea <strong>de</strong> aplicatii reutilizabile <strong>de</strong> nivel <strong>în</strong>alt. Ea<br />

permite <strong>de</strong>scrierea contextului unui <strong>si</strong>stem prin intermediul unei colectii <strong>de</strong> obiecte.<br />

Obiectele reprezinta entitati fizice <strong>si</strong> conceptuale ce compun un anumit <strong>si</strong>stem.<br />

Ele <strong>în</strong>capsuleaza anumite proprietati <strong>si</strong> pot efectua anumite operatii. Aplicatiile<br />

<strong>de</strong>zvoltate <strong>în</strong>tr-o maniera orientata-obiect nu contin un algoritm global. Ele se<br />

compun dintr-o multime <strong>de</strong> obiecte care interactioneaza <strong>în</strong>tre ele prin cereri <strong>si</strong><br />

schimburi <strong>de</strong> informatii. Aceste interactiuni se realizeaza prin intermediul unui<br />

protocol unificat <strong>de</strong> comunicare, numit transmi<strong>si</strong>e <strong>de</strong> mesaje, protocol care presupune<br />

4


existenta unui obiect sursa <strong>si</strong> a unui obiect receptor. Trimiterea unui mesaj are ca<br />

scop executia unei operatii <strong>de</strong>finite la nivelul obiectului receptor. Mesajul receptionat<br />

va contine informatii pe baza carora obiectul receptor va putea <strong>de</strong>termina operatia<br />

care va fi executata precum <strong>si</strong> valorile eventualilor parametrii ai acesteia. Aceasta<br />

metodologie reprezinta, <strong>de</strong> fapt, o abstractizare a modului natural <strong>în</strong> care sunt<br />

rezolvate cooperativ anumite probleme <strong>în</strong> diverse comunitati biologice.<br />

Alte notiuni fundamentale intim legate <strong>de</strong> paradigma programarii orientate<br />

obiect sunt abstractizarea (care introduce conceptul <strong>de</strong> clasa) <strong>si</strong> mostenirea (ce<br />

introduce conceptul <strong>de</strong> subclasa), ele permitând specificarea, cla<strong>si</strong>ficarea <strong>si</strong><br />

reutilizarea <strong>de</strong>scrierilor <strong>de</strong> obiecte.<br />

Primul limbaj <strong>de</strong> programare bazat pe aceste concepte, numit Simula, a aparut<br />

la sfâr<strong>si</strong>tul anilor ’60 <strong>si</strong> a fost <strong>de</strong>zvoltat <strong>în</strong> scopul realizarii <strong>de</strong> aplicatii pentru<br />

<strong>si</strong>mularea anumitor evenimente ale lumii reale [DAH67]. Odata cu aparitia acestui<br />

limbaj cercetarile relative la programarea orientata-obiect au luat amploare,<br />

conceptele acesteia au fost clar i<strong>de</strong>ntificate, iar metodologia orientata-obiect a fost<br />

calificata <strong>de</strong> ingineria soft ca o îmbunatatire semnificativa <strong>în</strong> <strong>de</strong>zvoltarea programelor<br />

<strong>si</strong> cresterea calitatii, fiabilitatii <strong>si</strong> reutilizabilitatii aplicatiilor.<br />

Facând <strong>în</strong>sa mai <strong>de</strong>parte analogia cu lumea reala constatam ca aici obiectele<br />

sunt <strong>în</strong> mod natural concurente. Acest lucru implica po<strong>si</strong>bilitatea ca la un moment dat<br />

mai multe obiecte sa efectueze concomitent anumite operatii (concurenta inter-<br />

obiect), sau un acela<strong>si</strong> obiect sa execute <strong>în</strong> paralel doua sau mai multe operatii<br />

(concurenta intra-obiect).<br />

Abilitatea <strong>de</strong> a exprima paralelismul potential al activitatilor prin programe<br />

concurente a <strong>de</strong>venit subiect <strong>de</strong> cercetare pentru <strong>si</strong>stemele viitoare. Iata doar câteva<br />

aspecte care sugereaza importanta acestei tendinte <strong>în</strong> programare:<br />

?? generalizarea <strong>si</strong>stemelor <strong>de</strong> operare multi-tasking <strong>si</strong> a <strong>si</strong>stemelor multi-<br />

procesor,<br />

?? distribuirea cunostintelor (informatiilor), prin intermediul retelelor <strong>de</strong><br />

calculatoare,<br />

1 În [BRI93] programarea orientata-obiect este privita ca o restrictie tehnologica a conceptului mai<br />

general <strong>de</strong> programare orientata obiect concurenta.<br />

5


?? existenta <strong>de</strong> interactiuni multiple <strong>în</strong> cadrul unor programe interactive mari<br />

(cum ar fi controlul proceselor, un<strong>de</strong> intrarile <strong>si</strong> controlul acestora trebuie<br />

sa fie multiple <strong>si</strong> distribuite),<br />

?? exprimarea naturala a anumitor aplicatii prin intermediul mecanismelor <strong>de</strong><br />

concurenta <strong>si</strong> coordonare a activitatilor.<br />

Prin urmare i<strong>de</strong>ea <strong>de</strong> combinare a conceptelor programarii orientate-obiect cu<br />

mecanisme <strong>de</strong> specificare <strong>si</strong> coordonare a activitatilor concurente are la baza doua<br />

criterii distincte: unul obiectiv (<strong>de</strong>terminat <strong>de</strong> cresterea performantelor <strong>si</strong> a<br />

complexitatii <strong>si</strong>stemelor <strong>de</strong> calcul) <strong>si</strong> altul subiectiv (<strong>de</strong>terminat practic <strong>de</strong> "bun <strong>si</strong>mt",<br />

care ne <strong>în</strong><strong>de</strong>amna sa mo<strong>de</strong>lam diverse probleme abstracte cautând <strong>si</strong>milaritati cu<br />

lumea reala).<br />

Pentru a se putea realiza o integrare optima a acestor doua filozofii <strong>de</strong><br />

programare este utila i<strong>de</strong>ntificarea obiectelor ca unitati <strong>de</strong> activitate <strong>si</strong> asocierea<br />

<strong>si</strong>ncronizarii <strong>în</strong>tre obiecte la nivelul transmiterii <strong>de</strong> mesaje. Astfel <strong>de</strong> obiecte sunt<br />

numite <strong>în</strong> literatura obiecte active, actori sau obiecte concurente [BRI93].<br />

Modul <strong>în</strong> care se realizeaza integrarea <strong>concurentei</strong> <strong>în</strong> cadrul programarii<br />

orientate obiect a reprezentat preocuparea principala a mai multor cercetatori. În<br />

prezent exista peste o suta <strong>de</strong> limbaje <strong>de</strong> programare orientate-obiect concurente<br />

imperative ([PHI95b], [GOL83], [HUT87], [SCH86], [AND93], [AME90], [CAR93],<br />

[KAF93], {YON97b] etc), au fost <strong>de</strong>zvoltate mai multe mo<strong>de</strong>le <strong>de</strong> obiecte concurente<br />

([SHL88], [ELI92], [BER94], [PAP96], [OMG99], [HEN97]) <strong>si</strong> au fost <strong>de</strong>puse<br />

eforturi pentru cla<strong>si</strong>ficarea acestora ([PAP92], [BER94]).<br />

Combinarea <strong>concurentei</strong> cu mecanismele orientate-obiect nu este <strong>în</strong>sa un<br />

proces trivial. Cercetari mai vechi ([YON87]) au evi<strong>de</strong>ntiat existenta unor conflicte<br />

<strong>în</strong>tre mecanismul <strong>de</strong> mostenire <strong>si</strong> mecanismele <strong>de</strong> coordonare a operatiilor concurente<br />

<strong>în</strong> cadrul unor astfel <strong>de</strong> limbaje. Aceste conflicte, numite anomalii <strong>de</strong> mostenire, au<br />

<strong>de</strong>terminat mai multi proiectanti <strong>de</strong> limbaje orientate-obiect concurente sa elimine<br />

mostenirea din limbajele lor sau sa implementeze mecanismele <strong>de</strong> coordonare<br />

in<strong>de</strong>pen<strong>de</strong>nt <strong>de</strong> ierarhiile <strong>de</strong> mostenire.<br />

6


1.2. Meto<strong>de</strong> <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare a aplicatiilor<br />

Realizarea <strong>de</strong> aplicatii <strong>de</strong> complexitate medie sau mare nu mai poata fi<br />

conceputa astazi fara utilizarea meto<strong>de</strong>lor <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare. Prin meto<strong>de</strong> <strong>de</strong><br />

<strong>analiza</strong> <strong>si</strong> proiectare <strong>în</strong>telegem o multime <strong>de</strong> proce<strong>de</strong>e, tehnici <strong>si</strong> recomandari utilizate<br />

<strong>în</strong> etapele timpurii ale ciclului <strong>de</strong> viata al unei aplicatii având ca scop final crearea<br />

unui mo<strong>de</strong>l al aplicatiei care urmeaza a fi construite. Specificarea acestui mo<strong>de</strong>l se<br />

realizeaza prin intermediul unui limbaj sau formalism vizual compus dintr-un set <strong>de</strong><br />

<strong>si</strong>mboluri grafice <strong>si</strong> adnotari textuale.<br />

Ciclul <strong>de</strong> viata al unei aplicatii reprezinta totalitatea etapelor care sunt parcurse<br />

<strong>în</strong> procesul <strong>de</strong> <strong>de</strong>zvoltare a aplicatiei respective. Dintre cele mai importante etape<br />

amintim:<br />

- Analiza - <strong>în</strong> cadrul careia se realizeaza i<strong>de</strong>ntificarea caracteristicilor<br />

esentiale tuturor solutiilor corecte po<strong>si</strong>bile,<br />

- Proiectarea - care adauga mo<strong>de</strong>lelor <strong>de</strong> <strong>analiza</strong> noi elemente care <strong>de</strong>finesc<br />

o solutie particulara, pe baza optimizarii anumitor criterii,<br />

- Implementarea - <strong>în</strong> care se realizeaza un proiect executabil al solutiei<br />

particulare mo<strong>de</strong>lata <strong>în</strong> faza <strong>de</strong> proiectare,<br />

- Testarea - <strong>în</strong> care se verifica echivalenta implementarii cu mo<strong>de</strong>lul<br />

proiectat <strong>si</strong> vali<strong>de</strong>aza faptul ca <strong>implementare</strong>a respecta criteriile <strong>de</strong><br />

corectitudine i<strong>de</strong>ntificate <strong>în</strong> etapa <strong>de</strong> <strong>analiza</strong>.<br />

Într-o abordare orientata-obiect <strong>în</strong> etapa <strong>de</strong> <strong>analiza</strong> <strong>si</strong>stemele informatice sunt<br />

mo<strong>de</strong>late prin in<strong>de</strong>ntificarea <strong>de</strong> clase <strong>si</strong> obiecte <strong>si</strong> ale relatiilor dintre acestea.<br />

Proiectarea adauga <strong>de</strong>talii necesare implementarii mo<strong>de</strong>lului <strong>de</strong> <strong>analiza</strong> pe un <strong>si</strong>stem<br />

<strong>de</strong> calcul, <strong>de</strong>talii referitoare la interactiunea utilizatorului cu aplicatia finala,<br />

gestionarea proceselor, <strong>de</strong>talii <strong>de</strong> gestiune a datelor etc. Etapa <strong>de</strong> <strong>implementare</strong><br />

presupune translatarea mo<strong>de</strong>lelor <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare <strong>în</strong> cod sursa, folo<strong>si</strong>nd un<br />

limbaj <strong>de</strong> programare particular. Un mo<strong>de</strong>l <strong>de</strong> <strong>analiza</strong> sau proiectare al unei aplicatii<br />

se numeste executabil daca translatarea sa <strong>în</strong> cod sursa se poate efectua automat.<br />

Automatizarea procesului <strong>de</strong> translatare poate conduce la po<strong>si</strong>bilitatea executarii unui<br />

prototip al aplicatiei <strong>de</strong>zvoltate aproape imediat dupa ce mo<strong>de</strong>lul acestuia a fost<br />

<strong>de</strong>finitivat. Meto<strong>de</strong>le <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare orientata-obiect permit parcurgerea<br />

etapelor ciclului <strong>de</strong> viata a aplicatiilor <strong>în</strong>tr-o maniera iterativa (figura 1.1).<br />

7


Specificatiile<br />

aplicatiei<br />

(limbaj natural)<br />

Parcurgerea <strong>în</strong> sens<br />

invers a etapelor ciclului<br />

<strong>de</strong> viata a unei aplicatii<br />

<strong>analiza</strong><br />

Mo<strong>de</strong>l <strong>de</strong> <strong>analiza</strong><br />

(diagrame)<br />

proiectare<br />

Mo<strong>de</strong>l <strong>de</strong> proiectare<br />

(diagrame)<br />

8<br />

translatare<br />

Mo<strong>de</strong>l <strong>de</strong> <strong>implementare</strong><br />

(cod sursa)<br />

compilare +<br />

link-editare<br />

Mo<strong>de</strong>l executabil<br />

(cod binar)<br />

Figura 1.1. Mo<strong>de</strong>lul iterativ <strong>de</strong> <strong>de</strong>zvoltare a unei aplicatii <strong>în</strong><br />

cazul utilizarii unei meto<strong>de</strong> <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare orientate-obiect<br />

testare<br />

Primele meto<strong>de</strong> <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare orientate-obiect au aparut la sfâr<strong>si</strong>tul<br />

anilor '80, iar la <strong>în</strong>ceputul anilor '90 numarul acestora a crescut spectaculos. Anul<br />

1997 marcheaza un moment important <strong>în</strong> evolutia domeniului prin adoptarea<br />

limbajului UML (Unified Mo<strong>de</strong>ling Language [OMG99]) ca limbaj standard <strong>de</strong><br />

mo<strong>de</strong>lare a aplicatiilor <strong>de</strong> catre consortul international OMG (Object Management<br />

Group).<br />

Pe <strong>de</strong> alta parte, odata cu evolutia meto<strong>de</strong>lor <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare orientate-<br />

obiect s-au <strong>de</strong>zvoltat o serie <strong>de</strong> instrumente care permit automatizarea procesului <strong>de</strong><br />

realizare a aplicatiilor având la baza aceste meto<strong>de</strong>. Astfel <strong>de</strong> instrumente poarta<br />

numele <strong>de</strong> instrumente CASE (Computer Ai<strong>de</strong>d Software Engineering) <strong>si</strong> ele sunt<br />

formate dintr-o colectie <strong>de</strong> componente care sprijina realizarea operatiilor ce trebuie<br />

efectuate <strong>în</strong> cadrul uneia sau mai multor etape ale unei meto<strong>de</strong> <strong>de</strong> <strong>analiza</strong> <strong>si</strong><br />

proiectare.<br />

1.3. Contributiile originale ale tezei<br />

Scopul acestei teze este <strong>de</strong> a <strong>de</strong>fini <strong>si</strong> valida un formalism <strong>de</strong> mo<strong>de</strong>lare a<br />

aplicatiilor orientate-obiect concurente. Pentru a realiza acest lucru am <strong>analiza</strong>t <strong>în</strong><br />

<strong>de</strong>taliu principiile <strong>si</strong> mo<strong>de</strong>lele obiect care stau la baza unui numar mare <strong>de</strong> limbaje <strong>de</strong><br />

programare orientate-obiect concurente <strong>de</strong>zvoltate pâna <strong>în</strong> prezent. Formalizarea


matematica a conflictelor <strong>în</strong>tre concepte <strong>si</strong> a neajunsurilor care caracterizeaza aceste<br />

limbaje a condus <strong>de</strong>finirea unei exten<strong>si</strong>i a formalismului hartilor <strong>de</strong> stari [HAR87]<br />

utilizat <strong>în</strong> mo<strong>de</strong>larea comportamentului <strong>si</strong>stemelor reactive, exten<strong>si</strong>e numita harta <strong>de</strong><br />

stari scalabila. Caracterul executabil al hartilor <strong>de</strong> stari scalabile <strong>de</strong>finite a permis<br />

<strong>implementare</strong>a unui instrument <strong>de</strong> automatizare a <strong>de</strong>zvoltarii <strong>si</strong> <strong>si</strong>mulare a aplicatiilor<br />

orientate-obiect concurente.<br />

Principalele contributii originale continute <strong>în</strong> teza <strong>si</strong> lucrarile <strong>în</strong> care acestea au<br />

fost promovate sunt:<br />

1. <strong>de</strong>finirea unui set con<strong>si</strong>stent <strong>de</strong> principii <strong>de</strong> proiectare a limbajelor <strong>de</strong><br />

programare orientate-obiect concurente care au la baza respectarea<br />

integritatii conceptelor ce caracterizeaza fiecare dintre cele doua<br />

metodologii <strong>de</strong> programare <strong>în</strong> parte (orientata-obiect <strong>si</strong> concurenta) -<br />

[SUC97b];<br />

2. <strong>si</strong>ntetizarea caracteristicilor mo<strong>de</strong>lelor obiect implementate <strong>în</strong> peste o suta<br />

<strong>de</strong> limbaje <strong>de</strong> programare imperative orientate-obiect concurente<br />

<strong>de</strong>zvoltate pâna <strong>în</strong> prezent. Tratarea tuturor acestor mo<strong>de</strong>le obiect <strong>în</strong>tr-o<br />

maniera unitara prin realizarea <strong>de</strong> exten<strong>si</strong>i ale limbajului <strong>de</strong> programare<br />

C++ cu mecanisme speciale <strong>de</strong> <strong>de</strong>clarare <strong>de</strong> proprietati sau operatii <strong>si</strong>/sau<br />

prin <strong>de</strong>finirea <strong>de</strong> noi instructiuni - [SUC98b];<br />

3. <strong>de</strong>finirea conceptului <strong>de</strong> anomalie <strong>de</strong> reutilizare care extin<strong>de</strong> notiunea <strong>de</strong><br />

anomalie <strong>de</strong> mostenire, <strong>si</strong> care trateaza <strong>în</strong>tr-un mod unitar conflictele care<br />

apar <strong>în</strong>tre concurenta <strong>si</strong> conceptele programarii orientate-obiect -<br />

[SUC97a], [SUC98b];<br />

4. extin<strong>de</strong>rea unui <strong>si</strong>stem <strong>de</strong> formalizare a anomaliilor <strong>de</strong> mostenire pentru<br />

mo<strong>de</strong>larea respectarii principiului separarii codului <strong>de</strong> interactiune<br />

concurenta <strong>de</strong>terminat la punctul 1 <strong>si</strong> <strong>de</strong>monstrarea reducerii efectului<br />

anomaliilor <strong>de</strong> mostenire pentru acest caz- [SUC98a];<br />

5. <strong>de</strong>finirea hartilor <strong>de</strong> stari scalabile ca exten<strong>si</strong>e a formalismului vizual al<br />

hartilor <strong>de</strong> stari <strong>de</strong>finit <strong>în</strong> [HAR87]. Acest tip <strong>de</strong> harti <strong>de</strong> stari conduce la<br />

<strong>si</strong>mplificarea mo<strong>de</strong>larii dinamice a obiectelor active cu comportament<br />

complex, prin reducerea complexitatii <strong>în</strong> faza <strong>de</strong> mo<strong>de</strong>lare [SUC99];<br />

6. <strong>de</strong>finirea unei semantici care sa atribuie hartilor <strong>de</strong> stari scalabile un<br />

caracter executabil, <strong>si</strong> care sa permita mo<strong>de</strong>larea <strong>de</strong> obiecte active<br />

9


corespunzatoare unui mo<strong>de</strong>l obiect general, comun unei clase<br />

semnificative <strong>de</strong> limbaje <strong>de</strong> programare orientate-obiect concurente -<br />

[SUC98c], [SUC98d], [SCU97], [BOZ94b];<br />

7. <strong>de</strong>zvoltarea unui instrument <strong>de</strong> proiectare, <strong>implementare</strong> <strong>si</strong> <strong>si</strong>mulare a<br />

1.4. Structura tezei<br />

aplicatiilor orientate-obiect concurente, având la baza hartile <strong>de</strong> stari<br />

scalabile. Acest instrument, numit ActiveCASE se constituie <strong>în</strong>tr-un<br />

modul din cadrul unui instrument CASE mult mai general, Rocase -<br />

[SUC98e], [CHI97], [SUC96b], [BOZ94a].<br />

Capitolul al doilea, "Specificarea <strong>si</strong> coordonarea <strong>concurentei</strong> <strong>în</strong> programarea<br />

orientata-obiect concurenta", este un capitol <strong>de</strong> <strong>si</strong>nteza <strong>în</strong> cadrul caruia am realizat o<br />

<strong>analiza</strong> a constructiilor <strong>si</strong> mecanismelor <strong>de</strong> mo<strong>de</strong>lare a <strong>concurentei</strong> implementate <strong>în</strong><br />

peste o suta <strong>de</strong> limbaje <strong>de</strong> programare orientate-obiect concurente. De asemenea, am<br />

enuntat patru principii <strong>de</strong> proiectare a mo<strong>de</strong>lelor <strong>de</strong> obiecte concurente care au stat la<br />

baza evaluarii acestor mecanisme. Exemplificarea mecanismelor <strong>analiza</strong>te s-a realizat<br />

prin intermediul unor exten<strong>si</strong>i ale limbajului C++.<br />

În capitolul al treilea, "Anomalii <strong>de</strong> mostenire", am formalizat princiipiile<br />

enuntate <strong>în</strong> cadrul capitolului al doilea <strong>si</strong> am <strong>de</strong>mostrat importanta respectarii acestora<br />

<strong>în</strong> ameliorarea anomaliilor <strong>de</strong> mostenire. Am aratat, <strong>de</strong> asemenea, ca termenul <strong>de</strong><br />

anomalie <strong>de</strong> mostenire este impropriu. Astfel, am <strong>de</strong>monstrat ca mecanismele <strong>de</strong><br />

initiere <strong>si</strong> coordonare a activitatilor concurente din limbajele <strong>de</strong> programare orientate<br />

obiect concurente existente <strong>în</strong> prezent genereaza conflicte <strong>în</strong> raport cu relatiile <strong>de</strong><br />

asociere, agregare <strong>si</strong> <strong>de</strong>legare <strong>în</strong>tre clase. Cauzele <strong>si</strong> comportamentul acestor<br />

conflicte sunt comune cu cele care <strong>de</strong>termina anomaliile <strong>de</strong> mostenire. De asemenea,<br />

am <strong>de</strong>monstrat ca termenul <strong>de</strong> anomalie <strong>de</strong> mostenire <strong>de</strong>fineste un conflict particular<br />

generat <strong>de</strong> integrarea <strong>concurentei</strong> <strong>în</strong>tr-un context orientat-obiect <strong>si</strong> am propus<br />

termenul mai general <strong>de</strong> anomalie <strong>de</strong> reutilizare.<br />

Capitolul patru, "Mo<strong>de</strong>larea comportamentului obiectelor active", surprin<strong>de</strong><br />

aspecte privind mo<strong>de</strong>larea aplicatiilor orientate-obiect concurente. Am realizat o<br />

trecere <strong>în</strong> revista a principalelor mo<strong>de</strong>le obiect <strong>de</strong>zvoltate pâna <strong>în</strong> prezent in<strong>si</strong>stând<br />

10


asupra aspectelor <strong>de</strong> concurenta specifice. În centrul atentiei acestei analize se va afla<br />

limbajul UML (Unified Mo<strong>de</strong>ling Language) ver<strong>si</strong>unea 1.3 [OMG99].<br />

Rezultatele obtinute <strong>în</strong> capitolul trei <strong>în</strong> studiul anomaliilor <strong>de</strong> mostenire alaturi<br />

<strong>de</strong> interpretarea obiectelor active ca <strong>si</strong> (sub)<strong>si</strong>steme reactive, conduc la i<strong>de</strong>ea<br />

mo<strong>de</strong>larii comportamentului acestora prin intermediul formalismului hartilor <strong>de</strong> stari<br />

[HAR87]. Lipsa unei semantici bine <strong>de</strong>finite a acestor harti <strong>de</strong> stari pentru <strong>analiza</strong> <strong>si</strong><br />

<strong>proiectarea</strong> orientata-obiect au <strong>de</strong>terminat specificarea <strong>în</strong> finalul capitolului a unei<br />

variante <strong>de</strong> harti <strong>de</strong> stari, numita harta <strong>de</strong> stari scalabila, care sa permita crearea <strong>de</strong><br />

mo<strong>de</strong>le executabile, care ofera suport pentru generarea automata <strong>de</strong> cod <strong>si</strong> <strong>si</strong>mularea<br />

executiei obiectelor active.<br />

În acest sens am propus mai multe modificari (exten<strong>si</strong>i <strong>si</strong> constrângeri) ale<br />

diagramelor <strong>de</strong> stari <strong>de</strong>scrise <strong>în</strong> UML, <strong>în</strong> cadrul capitolului cinci, "ActiveCASE -<br />

instrument <strong>de</strong> mo<strong>de</strong>lare <strong>si</strong> <strong>si</strong>mulare a comportamentului obiectelor active". Aici este<br />

<strong>de</strong>scris un meta-mo<strong>de</strong>l al hartilor <strong>de</strong> stari scalabile <strong>si</strong> este prezentata <strong>implementare</strong>a<br />

acestuia <strong>în</strong> cadrul unei aplicatii <strong>de</strong> mo<strong>de</strong>lare <strong>si</strong> <strong>si</strong>mulare a aplicatiilor orientate-obiect<br />

concurente. Aceasta aplicatie se va constitui <strong>în</strong>tr-un modul distinct <strong>în</strong> cadrul<br />

intrumentului CASE <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare orientata obiect Rocase, care a fost<br />

realizat in cadrul Laboratorului <strong>de</strong> Cercetare <strong>în</strong> Informatica al Univer<strong>si</strong>tatii "Babes-<br />

Bolyai" din Cluj-Napoca [CHI97].<br />

În cadrul capitolului sase am expus concluziile finale rezultate <strong>în</strong> urma<br />

studiilor efectuate <strong>în</strong> cadrul tezei, <strong>si</strong> se propun directii viitoare <strong>de</strong> cercetare <strong>în</strong><br />

domeniul analizei <strong>si</strong> proiectarii aplicatiilor orientate-obiect concurente.<br />

În final, anexele A <strong>si</strong> B contin <strong>de</strong>scrieri ale notatiilor matematice <strong>si</strong> grafice<br />

utilizate <strong>în</strong> mo<strong>de</strong>lele formale <strong>si</strong>/sau vizuale <strong>de</strong>zvoltate <strong>în</strong> cadrul tezei.<br />

11


2. Specificarea <strong>si</strong> coordonarea <strong>concurentei</strong> <strong>în</strong> programarea<br />

orientata-obiect concurenta<br />

2.1. Introducere<br />

În clipa <strong>de</strong> fata exista o diver<strong>si</strong>tate <strong>de</strong> limbaje <strong>de</strong> programare orientate-obiect<br />

concurente, numarul acestora fiind <strong>în</strong> continua crestere datorita cercetarilor tot mai<br />

intense <strong>în</strong> acest domeniu. Majoritatea acestor limbaje au fost <strong>de</strong>zvoltate <strong>în</strong> scopuri <strong>de</strong><br />

cercetare, pentru a <strong>de</strong>monstra sau infirma anumite rezultate teoretice.<br />

În cadrul acestui capitol am enuntat un set <strong>de</strong> patru principii <strong>de</strong> proiectare a<br />

limbajelor <strong>de</strong> programare orientate-obiect concurente. Acestea sunt <strong>în</strong> marea lor<br />

majoritate principii care stau la baza filozofiei <strong>de</strong> programare orientata-obiect pe <strong>de</strong> o<br />

parte <strong>si</strong> a programarii concurente pe <strong>de</strong> alta parte. De<strong>si</strong> unificarea acestor doua clase<br />

<strong>de</strong> principii pare a fi una naturala, referindu-se la doua paradigme ortogonale ale<br />

programarii, se va arata ca respectarea unora dintre ele poate aduce atingere<br />

integritatii celorlalte. Determinarea acestor principii s-a facut <strong>în</strong>tr-o maniera<br />

informala, având la baza cercetari realizate <strong>în</strong> acest domeniu <strong>în</strong> [BLO79], [PAP89],<br />

[MAT90], [FRO92], [PAP92], [MAT93], [MEY93] <strong>si</strong> [PHI95].<br />

Prezentul capitol contine <strong>de</strong> asemenea un studiu amanuntit a modalitatilor <strong>de</strong><br />

specificare <strong>si</strong> coordonare a activitatilor concurente <strong>în</strong> peste o suta <strong>de</strong> limbaje<br />

orientate-obiect concurente. Acest studiu are la baza <strong>de</strong>scrieri <strong>si</strong> analize <strong>de</strong> limbaje <strong>de</strong><br />

programare, biblioteci <strong>de</strong> clase concurente sau mo<strong>de</strong>le <strong>de</strong> obiecte concurente <strong>si</strong> are ca<br />

scop principal evaluarea acestora <strong>în</strong> raport cu respectarea principiilor <strong>de</strong>terminate.<br />

Rezultatele evaluarilor sunt prezentate <strong>în</strong> finalul capitolului sub o forma tabelara <strong>si</strong> ele<br />

12


eleva faptul ca nici unul dintre mecanismele studiate nu respecta <strong>în</strong> totalitate cele<br />

patru principii.<br />

Pentru fiecare mecanism particular <strong>de</strong> specificare a interactiunilor <strong>în</strong>tre obiecte<br />

concurente am propus exten<strong>si</strong>i ale limbajului <strong>de</strong> programare C++ care le<br />

implementeaza. Aceste exten<strong>si</strong>i vizeaza introducerea <strong>de</strong> instructiuni sau constructii<br />

<strong>de</strong> <strong>de</strong>clarare noi <strong>si</strong> ele pot fi utilizate <strong>în</strong> <strong>de</strong>zvoltarea <strong>de</strong> aplicatii prin construirea <strong>de</strong><br />

preprocesoare sau compilatoare speciale. Modul <strong>de</strong> utilizare a exten<strong>si</strong>ilor propuse<br />

este exemplificat prin <strong>implementare</strong>a unei clase concurente concrete, care specifica o<br />

coada cu numar finit <strong>de</strong> elemente.<br />

2.2. Principii <strong>de</strong> proiectare a limbajelor <strong>de</strong> programare orientate-obiect<br />

concurente<br />

În programarea orientata-obiect concurenta un <strong>si</strong>stem informatic este privit ca<br />

un mo<strong>de</strong>l fizic <strong>de</strong> <strong>si</strong>mulare a comportamentului unei parti din lumea reala sau<br />

conceptuala. Acest mo<strong>de</strong>l fizic este <strong>de</strong>finit prin intermediul unui limbaj <strong>de</strong><br />

programare <strong>si</strong> el se concretizeaza <strong>în</strong>tr-o aplicatie ce poate fi executata pe un <strong>si</strong>stem <strong>de</strong><br />

calcul.<br />

Obiectele sunt elemente cheie ale programarii orientate-obiect concurente <strong>si</strong><br />

ele reprezinta entitati individuale reale sau abstracte cu un rol bine <strong>de</strong>finit <strong>în</strong> contextul<br />

unui <strong>si</strong>stem. Un obiect are o i<strong>de</strong>ntitate, o stare <strong>si</strong> un comportament. Tot ceea ce<br />

obiectele cunosc (starea) <strong>si</strong> pot efectua (comportamentul) este exprimat prin<br />

intermediul unor multimi <strong>de</strong> proprietati (sau atribute) <strong>si</strong> operatii (sau meto<strong>de</strong>).<br />

Astfel, starea unui obiect este data <strong>de</strong> valorile proprietatilor acestuia la un moment<br />

dat. Operatiile sunt proceduri sau functii care permit modificarea acestor valori <strong>si</strong><br />

implementeaza comportamentul obiectelor.<br />

Aplicatiile orientate-obiect concurente sunt compuse dintr-o multime <strong>de</strong><br />

obiecte care interactioneaza <strong>si</strong> comunica <strong>în</strong>tre ele prin intermediul mesajelor. Un<br />

mesaj reprezinta o cerere adresata unui obiect <strong>de</strong> a executa o anumita operatie.<br />

Mesajul este compus din trei elemente distincte: i<strong>de</strong>ntitatea obiectului caruia îi este<br />

adresat mesajul, numele operatiei care se doreste a fi executata <strong>si</strong> o lista <strong>de</strong> parametri<br />

necesari executarii operatiei. Aceste trei informatii sunt suficiente pentru ca un obiect<br />

care receptioneaza un mesaj sa poata executa operatia dorita. Mecanismul transmi<strong>si</strong>ei<br />

13


<strong>de</strong> mesaje permite prin urmare comunicarea <strong>în</strong>tre obiecte aflate <strong>în</strong> contexte (sau<br />

procese) diferite sau pe diferite <strong>si</strong>steme <strong>de</strong> calcul. Deoarece <strong>în</strong>treaga activitate a unui<br />

obiect este exprimata prin intermediul operatiilor sale, mecanismul transmi<strong>si</strong>ei <strong>de</strong><br />

mesaje poate exprima toate interactiunile po<strong>si</strong>bile <strong>în</strong>tre obiecte.<br />

Multimea <strong>de</strong> proprietati ale unui obiect formeaza nucleul acestuia. O parte din<br />

operatiile sale sunt vizibile <strong>în</strong> exterior <strong>si</strong> ascund nucleul <strong>de</strong> celelalte obiecte dintr-un<br />

<strong>si</strong>stem. Ascun<strong>de</strong>rea proprietatilor interne ale unui obiect <strong>si</strong> oferirea <strong>de</strong> operatii care sa<br />

le manipuleze poarta numele <strong>de</strong> <strong>în</strong>capsulare. Încapsularea este utilizata pentru a<br />

ascun<strong>de</strong> <strong>de</strong>talii <strong>de</strong> <strong>implementare</strong> <strong>de</strong> alte obiecte aflate <strong>în</strong> <strong>si</strong>stem. Astfel poate fi<br />

modificata <strong>implementare</strong>a unui obiect fara a afecta alte parti ale <strong>si</strong>stemului din care<br />

acesta face parte. Încapsularea confera modularitate, <strong>implementare</strong>a unui obiect<br />

putând fi modificata sau actualizata in<strong>de</strong>pen<strong>de</strong>nt <strong>de</strong> <strong>implementare</strong>a celorlalte obiecte<br />

din <strong>si</strong>stem. Multimea tuturor operatiilor unui obiect care sunt vizibile <strong>în</strong> exteriorul<br />

acestuia poarta numele <strong>de</strong> interfata a obiectului.<br />

Interfetele obiectelor <strong>de</strong>finesc tipul acestora. Obiectele care au aceea<strong>si</strong><br />

interfata apartin aceluia<strong>si</strong> tip. Deoarece interfata este o submultime a operatiilor care<br />

<strong>de</strong>finesc comportamentul obiectelor, ea mai poarta numele <strong>de</strong> comportament extern<br />

observabil.<br />

I<strong>de</strong>ntificarea unei multimi <strong>de</strong> obiecte care au proprietati <strong>si</strong> comportamente<br />

comune poarta numele <strong>de</strong> cla<strong>si</strong>ficare. Clasa este un alt concept <strong>de</strong> baza al<br />

programarii orientate-obiect concurente, <strong>si</strong> ea reprezinta o abstractizarea a elementelor<br />

(proprietatilor <strong>si</strong> operatiilor) comune partajate <strong>de</strong> o multime <strong>de</strong> obiecte <strong>si</strong> <strong>de</strong>scrie<br />

<strong>implementare</strong>a acestora.<br />

Obiectele sunt reprezentari concrete ale claselor, iar procesul <strong>de</strong> creare a unui<br />

obiect pe baza <strong>de</strong>finitiei unei clase poarta numele <strong>de</strong> instantiere. De aceea <strong>în</strong><br />

literatura un obiect este numit <strong>si</strong> instanta a clasei care îl <strong>de</strong>fineste.<br />

Pentru a exemplifica notiunile introduse pâna <strong>în</strong> acest moment vom specifica<br />

<strong>în</strong> cele ce urmeaza o clasa care implementeaza cozi cu numar finit <strong>de</strong> elemente, <strong>si</strong> pe<br />

care o vom numi Coada. Proprietatile unei astfel <strong>de</strong> cozi sunt:<br />

- maxElem - numarul maxim <strong>de</strong> elemente care pot fi stocate <strong>în</strong> coada,<br />

- elemIntroduse – numarul elementelor introduse <strong>în</strong> coada pâna la un<br />

moment dat,<br />

- elemExtrase – numarul elementelor extrase din coada,<br />

14


- listaElemente – lista circulara care contine elementele stocate <strong>în</strong> coada<br />

(vom con<strong>si</strong><strong>de</strong>ra un caz general <strong>de</strong> coada, <strong>în</strong> care elementele stocate sunt<br />

instante ale unei clase Element).<br />

Valorile acestor proprietati vor putea fi modificate prin intermediul a doua<br />

operatii, Adauga() <strong>si</strong> Extrage(), care adauga, respectiv extrag elemente din coada.<br />

Figura 2.1. contine o <strong>de</strong>scriere vizuala a clasei Coada, utilizând limbajul <strong>de</strong><br />

mo<strong>de</strong>lare UML (Unified Mo<strong>de</strong>ling Language). Notatiile grafice folo<strong>si</strong>te aici sunt<br />

<strong>de</strong>scrise <strong>în</strong> <strong>de</strong>taliu <strong>în</strong> cadrul Anexei B.<br />

Obiectul oCoada prezentat <strong>în</strong> figura 2.2. este un exemplu <strong>de</strong> instanta a clasei<br />

Coada. Starea obiectului oCoada la momentul surprins <strong>în</strong> figura este caracterizata <strong>de</strong><br />

valoarea numarului maxim <strong>de</strong> elemente ce pot fi stocate (10), numarul <strong>de</strong> elemente<br />

introduse (5), numarul elementelor extrase (3) <strong>si</strong> continutul vectorului listaElemente.<br />

15<br />

oCoada<br />

maxElem : 10<br />

elemIntroduse : 5<br />

elemExtrase : 3<br />

listaElemente :<br />

0 1 2 3 4 5 6 7 8 9<br />

Adauga() Extrage()<br />

Figura 2.1. Mo<strong>de</strong>lul static al clasei Coada Figura 2.2. Descriere grafica a instantei<br />

oCoada a clasei Coada<br />

Dam mai jos <strong>si</strong> un exemplu <strong>de</strong> <strong>implementare</strong> a clasei Coada folo<strong>si</strong>nd limbajul<br />

<strong>de</strong> programare C++ [STR91]. Codul prezentat va constitui o baza pentru <strong>de</strong>scrierea<br />

exten<strong>si</strong>ilor limbajului C++ pe care le vom propune pentru <strong>implementare</strong>a<br />

mecanismelor <strong>de</strong> <strong>si</strong>ncronizare a operatiilor concurente. Proprietatea listaElemente,<br />

implementata aici ca un tablou <strong>de</strong> elemente, <strong>si</strong>muleaza o lista circulara. Un nou<br />

element adaugat <strong>în</strong> coada va ocupa pozitia elemeIntroduse mod maxElem, iar<br />

extragerea unui element din coada se va realiza <strong>de</strong> pe pozitia elemeExtrase mod<br />

maxElem.<br />

class Coada{<br />

protected:<br />

Element listaElemente[]; //tablou cu elementele cozii<br />

int maxElem; //nr. maxim <strong>de</strong> elemente din coada<br />

int elemIntroduse; //nr. elementelor introduse <strong>în</strong> coada<br />

int elemExtrase; //nr. elementelor extrase din coada<br />

public:<br />

Coada();<br />

~Coada();


void Adauga(Element elem);<br />

Element Extrage();<br />

}<br />

Coada::Coada(){<br />

//pentru <strong>si</strong>mplitate nu am <strong>de</strong>finit constructor explicit<br />

maxElem=10;<br />

listaElemente=new [maxElem] Element;<br />

elemIntroduse=elemExtrase=0;<br />

}<br />

Coada::~Coada{<br />

<strong>de</strong>lete [] listaElemente;<br />

}<br />

void Coada::Adauga(Element elem){<br />

if(elemIntroduse - elemExtrase >=maxElem)<br />

return; // eventual afisare mesaj <strong>de</strong> eroare<br />

elemIntroduse++;<br />

listaElemente[elemIntroduse % maxElem - 1]=elem;<br />

}<br />

Element Coada::Extrage(){<br />

if(elemIntroduse - elemExtrase == 0)<br />

return -1; // eventual afisare mesaj <strong>de</strong> eroare<br />

elemExtrase++;<br />

return listaElemente[elemExtrase % maxElem - 1];<br />

}<br />

Alaturi <strong>de</strong> notiunile <strong>de</strong> obiect <strong>si</strong> clasa, programarea orientata-obiect introduce<br />

un mecanism puternic <strong>si</strong> natural <strong>de</strong> organizare <strong>si</strong> structurare a <strong>si</strong>stemelor informatice:<br />

mecanismul <strong>de</strong> mostenire. Mostenirea permite <strong>de</strong>finirea <strong>de</strong> noi clase (numite sub-<br />

clase) pe baza unor clase <strong>de</strong>ja existente (super-clase) <strong>în</strong>tr-o maniera incrementala.<br />

Sub-clasele vor mosteni toate proprietatile <strong>si</strong> operatiile super-claselor. Relatia <strong>de</strong><br />

mostenire <strong>în</strong>tre clase induce organizarea claselor <strong>în</strong> ierarhii.<br />

Caracterul concurent al unui limbaj <strong>de</strong> programare reprezinta capacitatea<br />

limbajului <strong>de</strong> a exprima un paralelism potential. Limbajele <strong>de</strong> programare orientate-<br />

obiect concurente permit <strong>implementare</strong>a <strong>de</strong> aplicatii <strong>în</strong> care doua sau mai multe<br />

operatii apartinând obiectelor ce compun aplicatia pot fi executate <strong>în</strong> paralel, <strong>în</strong> fire <strong>de</strong><br />

executie distincte. Un fir <strong>de</strong> executie reprezinta un calcul ce poate fi executat <strong>în</strong><br />

paralel cu alte calcule. Pentru fire <strong>de</strong> executie <strong>în</strong> literatura mai sunt utilizate<br />

termenele <strong>de</strong> activitati sau procese.<br />

Un prim aspect <strong>de</strong>osebit <strong>de</strong> important care caracterizeaza mo<strong>de</strong>lele <strong>de</strong> obiecte<br />

concurente este dat <strong>de</strong> natura relatiei dintre obiectele unui <strong>si</strong>stem <strong>si</strong> firele <strong>de</strong> executie.<br />

Din acest punct <strong>de</strong> ve<strong>de</strong>re exista trei abordari: ortogonala, omogena <strong>si</strong> eterogena.<br />

În abordarea ortogonala obiectele <strong>si</strong> firele <strong>de</strong> executie sunt privite ca <strong>si</strong><br />

concepte in<strong>de</strong>pen<strong>de</strong>nte. Implicit obiectele nu sunt protejate <strong>de</strong> apeluri concurente ale<br />

operatiilor proprii (<strong>în</strong> orice moment un obiect va putea fi apelat din cadrul oricarui fir<br />

<strong>de</strong> executie). Prin urmare protejarea starii interne a obiectelor <strong>de</strong> executiile<br />

concurente ale propriilor operatii va trebui sa fie realizata explicit, prin intermediul<br />

16


unor mecanisme <strong>de</strong> <strong>si</strong>ncronizare <strong>de</strong> nivel scazut, specifice limbajelor <strong>de</strong> programare<br />

procedurale cum ar fi semafoarele ([DIJ68]) sau regiunile critice conditionale<br />

([HAN72], [HAN73]).<br />

Abordarea omogena introduce un concept nou, <strong>si</strong> anume acela <strong>de</strong> obiect activ.<br />

Un obiect activ este un obiect care poate controla <strong>si</strong> planifica executia propriilor<br />

operatii. Astfel, obiectele <strong>de</strong>tin fire <strong>de</strong> executie proprii care (<strong>în</strong> majoritatea mo<strong>de</strong>lelor<br />

obiect omogene) sunt create implicit atunci când este receptionat un mesaj. Astfel <strong>de</strong><br />

obiecte pot sau nu sa fie protejate implicit <strong>de</strong> invocari concurente din exterior <strong>si</strong><br />

contin mecanisme specifice pentru protejarea explicita a starii interne (multimi <strong>de</strong><br />

activare [TOM89], abstractizarea comportamentului [PAP96], meto<strong>de</strong> cu garzi<br />

[FER95], etc).<br />

Abordarea eterogena permite existenta <strong>în</strong> cadrul unui <strong>si</strong>stem a doua tipuri <strong>de</strong><br />

obiecte: active (având <strong>în</strong>telesul <strong>de</strong>scris mai sus) <strong>si</strong> pa<strong>si</strong>ve. Obiectele pa<strong>si</strong>ve nu <strong>de</strong>tin<br />

fire <strong>de</strong> executie proprii, nu sunt protejate (implicit sau explicit) <strong>de</strong> apeluri concurente<br />

din exterior, iar propriile operatii sunt executate <strong>în</strong> cadrul firelor <strong>de</strong> executie ale<br />

obiectelor care le apeleaza.<br />

În mo<strong>de</strong>lele obiect eterogene exista trei tipuri <strong>de</strong> abordari ale obiectelor pa<strong>si</strong>ve.<br />

Un prim caz este acela <strong>în</strong> care <strong>în</strong> obiectele pa<strong>si</strong>ve nu poate exista mai mult <strong>de</strong> un fir <strong>de</strong><br />

executie la un moment <strong>de</strong> timp dat (astfel <strong>de</strong> obiecte sunt echivalente obiectelor<br />

existente <strong>în</strong> cadrul limbajelor <strong>de</strong> programare orientate-obiect secventiale). Un al<br />

doilea caz este acela al obiectelor pa<strong>si</strong>ve partajate, care permit executarea <strong>în</strong> interiorul<br />

lor a mai multor fire <strong>de</strong> executie <strong>si</strong> care pot fi apelate <strong>de</strong> catre orice alt obiect din<br />

<strong>si</strong>stem (activ sau pa<strong>si</strong>v). In fine, al treilea caz este cel al obiectelor pa<strong>si</strong>ve care<br />

reprezinta o proprietate a unui obiect activ. În acest ultim caz obiectele pa<strong>si</strong>ve nu pot<br />

fi apelate <strong>de</strong>cât <strong>de</strong> catre obiectele active care le <strong>de</strong>tin (<strong>si</strong> care vor realiza <strong>si</strong> protejarea<br />

acestora).<br />

Un alt element important care caracterizeaza mo<strong>de</strong>lele obiect pentru<br />

concurenta implementate <strong>în</strong> diverse limbaje <strong>de</strong> programare este dat <strong>de</strong> gradul <strong>de</strong><br />

concurenta interna a obiectelor. Din acest punct <strong>de</strong> ve<strong>de</strong>re exista mo<strong>de</strong>le cu obiecte<br />

secventiale, cva<strong>si</strong>-concurente <strong>si</strong> concurente [PAP92].<br />

Mo<strong>de</strong>lele cu obiecte secventiale nu permit executia a mai mult <strong>de</strong> un fir <strong>de</strong><br />

executie <strong>în</strong> interiorul unui obiect. Mai mult, toate mesajele care sunt receptionate in<br />

timpul executiei unei operatii vor fi luate <strong>în</strong> con<strong>si</strong><strong>de</strong>rare doar dupa ce executia<br />

17


espectivei operatii a luat sfâr<strong>si</strong>t. Se poate spune ca <strong>în</strong> cazul acestor tipuri <strong>de</strong> mo<strong>de</strong>le<br />

nu exista concurenta interna.<br />

Mo<strong>de</strong>lele cu obiecte cva<strong>si</strong>-concurente sunt caracterizate <strong>de</strong> faptul ca obiectele<br />

pot <strong>de</strong>tine mai multe fire <strong>de</strong> executie, <strong>în</strong>sa numai unul dintre acestea este activ la un<br />

moment dat. De asemenea, exista po<strong>si</strong>bilitatea ca la un moment dat firul <strong>de</strong> executie<br />

activ sa fie blocat <strong>si</strong> sa se realizeze activarea unui alt fir <strong>de</strong> executie aflat <strong>în</strong> asteptare.<br />

Mo<strong>de</strong>lele cu obiecte concurente sunt cele "i<strong>de</strong>ale", ele permitând existenta a<br />

mai mult <strong>de</strong> un fir <strong>de</strong> executie <strong>în</strong> interiorul unui obiect. Firele <strong>de</strong> executie pot fi create<br />

atât implicit cât <strong>si</strong> explicit. Cele implicite sunt create <strong>în</strong> momentul receptionarii unui<br />

mesaj, când <strong>în</strong> cadrul noului fir <strong>de</strong> executie este executata operatia ceruta <strong>de</strong> acesta.<br />

Crearea explicita <strong>de</strong> fire <strong>de</strong> executie se realizeaza prin intermediul asa-numitelor<br />

mecanisme <strong>de</strong> initiere a <strong>concurentei</strong>. Majoritatea mo<strong>de</strong>lelor obiect pentru concurenta<br />

propun crearea implicita a firelor <strong>de</strong> executie. Mo<strong>de</strong>lele care folosesc cea <strong>de</strong>-a doua<br />

varianta utilizeaza mecanisme preluate din limbajele <strong>de</strong> programare procedurala.<br />

Asa cum am aratat, obiectele comunica <strong>în</strong>tre ele prin intermediul transmiterii<br />

<strong>de</strong> mesaje. Din punct <strong>de</strong> ve<strong>de</strong>re al sursei mesajului interactiunea (comunicarea) poate<br />

fi unidirectionala (fara primirea unui raspuns) sau bidirectionala (obiectul caruia îi<br />

este <strong>de</strong>stinat mesajul raspun<strong>de</strong> mesajului obiectului sursa). În acest ultim caz se pune<br />

problema daca obiectul sursa asteapta raspunsul sau î<strong>si</strong> continua activitatea, urmând a<br />

lua <strong>în</strong> con<strong>si</strong><strong>de</strong>rare raspunsul <strong>în</strong>tr-o faza ulterioara.<br />

Din perspectiva obiectului <strong>de</strong>stinatie, interactiunea cu obiectul sursa este<br />

privita prin prisma acceptarii mesajului transmis <strong>de</strong> acesta <strong>si</strong> a modalitatii <strong>în</strong> care se<br />

realizeaza acceptarea. Daca interactiunea dintre obiecte este controlata direct <strong>de</strong> catre<br />

<strong>si</strong>stem, fara a se specifica explicit, prin mecanisme oferite <strong>de</strong> limbaj, constrângeri<br />

privind aceasta interactiune, mo<strong>de</strong>lul este cu control extern. Urmatoarea categorie<br />

este aceea a mo<strong>de</strong>lelor cu control mixt, <strong>în</strong> care responsabilitatea coordonarii<br />

interactiunilor <strong>în</strong>tre activitatile concurente ale obiectelor este împartita <strong>în</strong>tre <strong>si</strong>stem <strong>si</strong><br />

impementarea obiectelor respective. În fine, din cea <strong>de</strong>-a treia categorie fac parte<br />

mo<strong>de</strong>lele cu control reflectiv, <strong>în</strong> care constrângerile <strong>de</strong> <strong>si</strong>ncronizare sunt exprimate cu<br />

ajutorul unei meta-clase.<br />

Sectiunile 3.3 <strong>si</strong> 3.4 contin <strong>de</strong>scrierile <strong>de</strong>taliate ale mecanismelor <strong>si</strong><br />

primitivelor <strong>de</strong> limbaj utilizate <strong>în</strong> programarea orientata-obiect concurenta pentru<br />

18


specificarea <strong>si</strong> coordonarea <strong>concurentei</strong>. Aceste mecanisme acopera toate categoriile<br />

<strong>de</strong> mo<strong>de</strong>le <strong>de</strong> obiecte concurente <strong>de</strong>scrise.<br />

Vom enunta <strong>în</strong> continuare un set <strong>de</strong> principii pe baza carora vom realiza o<br />

evaluare a mecanismelor <strong>analiza</strong>te. Aceste principii caracterizeaza un mo<strong>de</strong>l obiect<br />

general, cu o putere ridicata <strong>de</strong> exprimare a interactiunii <strong>si</strong> <strong>si</strong>ncronizarii activitatilor<br />

concurente <strong>si</strong> care vizeaza pastrarea integritatii conceptelor orientate-obiect<br />

(mostenirea, <strong>în</strong>capsularea, modularitatea etc).<br />

Mo<strong>de</strong>le obiect cu cea mai mare putere <strong>de</strong> exprimare a <strong>concurentei</strong> sunt cele<br />

care permit executarea <strong>în</strong> paralel a doua sau mai multe operatii ale aceluia<strong>si</strong> obiect.<br />

Pastrarea integritatii proprietatilor obiectelor asupra carora actioneaza mai multe<br />

operatii <strong>în</strong> mod concurent presupune utilizarea <strong>de</strong> mecanisme <strong>de</strong> limbaj <strong>de</strong><br />

<strong>si</strong>ncronizare <strong>si</strong> planificare a executiei operatiilor. Planificarea operatiilor unui obiect<br />

poate fi realizata <strong>în</strong> functie <strong>de</strong> starea obiectului la un moment dat sau <strong>de</strong> istoricul<br />

executiilor operatiilor acestuia. Prin urmare un prim principiu care trebuie respectat<br />

<strong>de</strong> catre un mo<strong>de</strong>l <strong>de</strong> obiecte concurente este ca acesta sa contina un mecanism <strong>de</strong><br />

specificare <strong>si</strong> interactiune <strong>în</strong>tre obiecte care sa permita exprimarea: a) <strong>concurentei</strong><br />

intra-obiect, b) executiei <strong>de</strong>pen<strong>de</strong>nte <strong>de</strong> stare <strong>si</strong> c) executiei <strong>de</strong>pen<strong>de</strong>nte <strong>de</strong> istoric.<br />

Vom numi acest principiu: Principiul expre<strong>si</strong>bilitatii <strong>concurentei</strong>.<br />

Conditiile pe baza carora se realizeaza <strong>si</strong>ncronizarea operatiilor concurente ale<br />

unui obiect poarta numele <strong>de</strong> constrângeri <strong>de</strong> <strong>si</strong>ncronizare. Constrângerile <strong>de</strong><br />

<strong>si</strong>ncronizare reprezinta expre<strong>si</strong>i logice <strong>în</strong> care, <strong>în</strong> general, sunt implicate proprietatile<br />

obiectului. Pentru a evita violarea <strong>în</strong>capsularii unui obiect concurent constrângerile<br />

<strong>de</strong> <strong>si</strong>ncronizare ale operatiilor sale trebuie sa poata fi specificate la nivelul acestuia <strong>si</strong><br />

sa fie transparente celorlalte obiecte din <strong>si</strong>stem. Aceasta conditie naturala impusa<br />

unui mo<strong>de</strong>l <strong>de</strong> obiecte concurente o vom referi <strong>în</strong> continuare ca Principiul codului <strong>de</strong><br />

<strong>si</strong>ncronizare orientat pe obiectul apelat.<br />

Ultimele doua principii pe care le vom lua <strong>în</strong> con<strong>si</strong><strong>de</strong>rare se refera la<br />

localizarea constrângerilor <strong>de</strong> <strong>si</strong>ncronizare <strong>în</strong> <strong>de</strong>finirea comportamentului obiectelor<br />

concurente. Astfel, Principiul izolarii codului <strong>de</strong> <strong>si</strong>ncronizare concurenta vizeaza<br />

<strong>de</strong>tasarea codului care implementeaza functionalitatea unei operatii <strong>de</strong> codul<br />

corespunzator <strong>de</strong>scrierii constrângerilor <strong>si</strong>ncronizare. De asemenea, po<strong>si</strong>bilitatea <strong>de</strong> a<br />

mosteni separat codul care implementeaza functionalitatea unei operatii <strong>si</strong> codul care<br />

19


eprezinta constrângerea <strong>de</strong> <strong>si</strong>ncronizare caracterizeaza Principiul separarii codului<br />

<strong>de</strong> <strong>si</strong>ncronizare concurenta.<br />

Respectarea ultimelor doua principii enuntate are o importanta <strong>de</strong>osebita <strong>în</strong><br />

ameliorarea conflictelor care apar <strong>în</strong>tre mostenire <strong>si</strong> mecanismele <strong>de</strong> <strong>si</strong>ncronizare<br />

concurenta. Acest lucru va fi <strong>de</strong>monstrat prin <strong>de</strong>scrierea lor <strong>în</strong>tr-un context formal <strong>în</strong><br />

cadrul capitolului 3.<br />

2.3. Mecanisme <strong>de</strong> specificare a <strong>concurentei</strong><br />

În cadrul acestei sectiuni vor fi enumerate <strong>si</strong> <strong>analiza</strong>te mecanismele <strong>de</strong><br />

specificare a <strong>concurentei</strong> <strong>în</strong> limbajele <strong>de</strong> programare orientate obiect existente pâna <strong>în</strong><br />

prezent <strong>si</strong> vor fi discutate avantajele <strong>si</strong> <strong>de</strong>zavantajele fiecaruia dintre acestea. Nici<br />

unul dintre aceste mecanisme nu se distinge ca fiind net superior celorlalte, fiecare<br />

având propriile neajunsuri. Majoritatea mecanismelor reprezinta adaptari ale<br />

mecanismelor cla<strong>si</strong>ce, folo<strong>si</strong>te <strong>în</strong> limbajele <strong>de</strong> programare ne-orientate obiect.<br />

Descrieri <strong>în</strong> <strong>de</strong>taliu ale acestora fi ga<strong>si</strong>te <strong>în</strong> [PHI95], [ELE91] <strong>si</strong> [GEO96].<br />

Paralelizarea automata. Aceasta abordare a paralelismului este una extrema<br />

<strong>si</strong> este caracterizata prin neimplicarea programatorului <strong>în</strong> activitatea <strong>de</strong> specificare a<br />

<strong>concurentei</strong>. Programul secvential este preluat <strong>si</strong> convertit automat <strong>în</strong>tr-o<br />

"reprezentare paralela". De<strong>si</strong> nu reprezinta un mecanism propriu-zis, am luat <strong>în</strong><br />

con<strong>si</strong><strong>de</strong>rare paralelizarea automata datorita potrivirii conceptuale perfecte cu<br />

programarea orientata pe obiecte. Aceasta potrivire provine din neinterferenta cu<br />

caracteristicile limbajului. În acest mod <strong>în</strong>sa nu poate fi obtinut un grad ridicat <strong>de</strong><br />

performanta, datorita numarului ridicat <strong>de</strong> <strong>de</strong>pen<strong>de</strong>nte <strong>în</strong>tre obiecte care compun o<br />

aplicatie.<br />

Fork-join, apeluri a<strong>si</strong>ncrone/variabile future, post-procesarea. Mecanismele<br />

din aceasta categorie sunt folo<strong>si</strong>te pentru lansarea a exact unei activitati concurente la<br />

un moment <strong>de</strong> timp.<br />

Mecanismul fork-join reprezinta prima constructie utilizata <strong>în</strong> programare<br />

pentru specificarea <strong>concurentei</strong> la nivel <strong>de</strong> limbaj. El este foarte asemanator cu apelul<br />

unei rutine. Rutina apelata este precedata <strong>de</strong> instructiunea fork <strong>si</strong> ea se va executa<br />

20


concurent cu rutina care o apeleaza. De obicei, alaturi <strong>de</strong> instructiunea fork mai este<br />

prezenta <strong>în</strong> limbaj <strong>si</strong> instructiunea join care este utila la <strong>si</strong>ncronizarea activitatilor<br />

concurente (activitatea care executa o instructiune join va fi blocata pâna la<br />

terminarea unui proces specificat <strong>în</strong> instructiune). Dezavantajele acestui mecanism<br />

sunt numeroase. Mentionam aici doar lizibilitatea scazuta a codului sursa <strong>si</strong><br />

dificultatea <strong>de</strong>panarii <strong>si</strong> <strong>în</strong>tretinerii aplicatiilor realizate cu acest mecanism. Acest<br />

fapt se datoreaza <strong>în</strong> principal nivelului scazut al instructiunii care poate fi con<strong>si</strong><strong>de</strong>rata<br />

ca o transpunere a instructiunii go to <strong>în</strong>tr-un mediu concurent.<br />

Pe <strong>de</strong> alta parte, <strong>în</strong>tr-un context orientat-obiect acest mecanism poate<br />

<strong>de</strong>termina distrugerea <strong>în</strong>capsularii din cel putin doua motive. În primul rând<br />

apelatorul unei rutine concurente trebuie sa se a<strong>si</strong>gure ca rutina respectiva poate fi<br />

executata <strong>în</strong> paralel cu restul firelor <strong>de</strong> executie fara a <strong>de</strong>termina incon<strong>si</strong>stente ale<br />

datelor programului. Daca pastrarea con<strong>si</strong>stentei nu este garantata <strong>de</strong> catre<br />

mecanismul <strong>de</strong> coordonare a <strong>concurentei</strong> folo<strong>si</strong>t <strong>în</strong> limbajul <strong>de</strong> programare orientat pe<br />

obiecte (iar <strong>în</strong> majoritatea cazurilor aceste mecanisme nu ofera o astfel <strong>de</strong> garantie,<br />

dupa cum vom observa <strong>în</strong> sectiunea urmatoare), atunci apelatorul trebuie sa cunoasca<br />

<strong>în</strong> <strong>de</strong>taliu <strong>implementare</strong>a rutinei apelate. Acest lucru, <strong>în</strong>sa, va reduce dramatic<br />

utilitatea bibliotecilor <strong>de</strong> clase.<br />

În al doilea rând este practic impo<strong>si</strong>bila modificarea codului rutinei fara a<br />

<strong>analiza</strong> cu atentie toate secventele <strong>de</strong> cod <strong>în</strong> care aceasta rutina este lansata <strong>în</strong> paralel.<br />

Prin urmare, rescrierea unei rutine poate <strong>de</strong>termina adaugarea <strong>de</strong> noi conditii <strong>în</strong><br />

constrângerile <strong>de</strong> <strong>si</strong>ncronizare <strong>de</strong> care apelatorul sau trebuie sa tina seama.<br />

Apelurile a<strong>si</strong>ncrone <strong>de</strong> operatii cu variabile future <strong>si</strong> post-procesarea<br />

mostenesc <strong>în</strong> principal toate aceste <strong>de</strong>zavantaje. Totu<strong>si</strong>, <strong>în</strong> cazul mecanismului <strong>de</strong><br />

post-procesare (<strong>de</strong>seori numit <strong>si</strong> cu retur timpuriu <strong>de</strong>oarece paralelismul este initiat<br />

doar <strong>în</strong> momentul <strong>în</strong> care este <strong>în</strong>tâlnita instructiunea return a unei rutine) poate fi<br />

impusa o disciplina <strong>de</strong> programare care sa evite violarea <strong>în</strong>capsularii. Acest avantaj<br />

fragil este secondat <strong>în</strong>sa <strong>de</strong> o sca<strong>de</strong>re a puterii <strong>de</strong> <strong>de</strong>scriere a <strong>concurentei</strong> (nu pot fi<br />

mo<strong>de</strong>late anumite scenarii <strong>de</strong> concurenta <strong>în</strong>tre procese).<br />

Cobegin - coend (parbegin - parend). Mecanismele din aceasta categorie<br />

permit executia mai multor fire <strong>de</strong> executie concurente <strong>în</strong> acela<strong>si</strong> timp. Astfel,<br />

instructiunile care sunt cuprinse <strong>în</strong>tre cuvintele cheie cobegin <strong>si</strong> coend vor fi lansate<br />

21


concurent <strong>în</strong> executie. Instructiunea cobegin reprezinta un pas <strong>în</strong>ainte <strong>în</strong> structurarea<br />

programelor concurente <strong>în</strong> raport cu instructiunea fork, dar spre <strong>de</strong>osebire <strong>de</strong> aceasta<br />

din urma nu are aceea<strong>si</strong> putere <strong>de</strong> <strong>de</strong>scriere a <strong>concurentei</strong>.<br />

Pe lânga avantajul unei mai bune structurari a programului acest mecanism<br />

<strong>de</strong>termina <strong>si</strong> o lizibilitate crescuta <strong>si</strong> usurinta <strong>în</strong> <strong>de</strong>panarea programelor. Din pacate,<br />

<strong>de</strong>zavantajul privind distrugerea <strong>în</strong>capsularii obiectelor amintit <strong>si</strong> la mecanismul<br />

anterior este prezent <strong>si</strong> <strong>în</strong> acest caz. Bine<strong>în</strong>teles, folo<strong>si</strong>rea unor mecanisme potrivite<br />

<strong>de</strong> coordonare a <strong>concurentei</strong> pot duce la restrângerea cazurilor potentiale <strong>de</strong><br />

interferente nedorite.<br />

Mecanisme forall, aggregate <strong>si</strong> mecanisme echivalente. Aceste mecanisme<br />

sunt cazuri particulare ale mecanismelor cobegin - coend. Diferenta consta <strong>în</strong> faptul<br />

ca activitatile care sunt executate concurent se refera fiecare la câte un element<br />

particular dintr-o anumita structura <strong>de</strong> date. Dezavantajele semnalate mai sus se<br />

pastreaza <strong>si</strong> <strong>în</strong> cazul acestor mecanisme, dar riscul aparitiei cazurilor <strong>de</strong> violare a<br />

<strong>în</strong>capsularii este mai scazut.<br />

Cod autonom. Din aceasta categorie fac parte constructii <strong>de</strong> limbaj care<br />

lanseaza o <strong>si</strong>ngura activitate concurenta la un moment dat, cum sunt: procesele,<br />

rutinele autonome <strong>si</strong> rutinele active. Mecanismele prezentate pâna acum reprezinta<br />

structuri <strong>de</strong> control care exprima paralelismul <strong>în</strong> interiorul unor fragmente <strong>de</strong> cod<br />

secventiale. În cazul proceselor <strong>în</strong>sa se realizeaza o <strong>de</strong>clarare explicita a unui proces<br />

asemanator <strong>de</strong>clararii unei rutine obisnuite. Apelarea unui astfel <strong>de</strong> proces are ca<br />

efect executia acestuia <strong>în</strong> paralel cu celelalte procese existente pâna <strong>în</strong> momentul<br />

respectiv. În functie <strong>de</strong> limbajul <strong>de</strong> programare care ofera aceasta constructie,<br />

procesele pot fi create static sau dinamic. Diferenta esentiala <strong>în</strong>tre procese <strong>si</strong> celelalte<br />

mecanisme <strong>de</strong> specificare a <strong>concurentei</strong> este aceea ca procesele nu mai reprezinta<br />

<strong>si</strong>mple instructiuni ci sunt concepte <strong>de</strong> baza al limbajului <strong>de</strong> programare. De<br />

asemenea, activitatile concurente vor avea <strong>în</strong>tot<strong>de</strong>auna un nume. Aceste diferente<br />

<strong>în</strong>sa nu influenteaza comportamentul mecanismului relativ la conceptele orientate-<br />

obiect, astfel ca specificarea <strong>concurentei</strong> prin intemediul <strong>de</strong>clararii explicite <strong>de</strong><br />

procese prezinta acelea<strong>si</strong> <strong>de</strong>zavantaje ca <strong>si</strong> mecanismele prezentate anterior. În plus<br />

acest mecanism <strong>de</strong>termina o limitare a puterii <strong>de</strong> exprimare a <strong>concurentei</strong> [PHI95].<br />

22


Rutinele autonome reprezinta o exten<strong>si</strong>e a <strong>de</strong>clararii proceselor <strong>în</strong>tr-un context<br />

orientat-obiect. Astfel, <strong>în</strong> momentul <strong>în</strong> care un obiect este creat sunt lansate una sau<br />

mai multe activitati care executa anumite operatii ale acestuia. Aceste operatii poarta<br />

numele <strong>de</strong> rutine autonome. În functie <strong>de</strong> limbaj operatiile vor fi lansate automat<br />

imediat dupa crearea obiectului sau vor fi necesare apeluri explicite ale acestora.<br />

Rutinele autonome sunt prezente mai ales <strong>în</strong> limbaje <strong>de</strong> programare care utilizeaza<br />

biblioteci <strong>de</strong> clase speciale pentru exprimarea <strong>concurentei</strong>. În astfel <strong>de</strong> limbaje exista<br />

o clasa care <strong>de</strong>fineste activitatile care vor fi lansate <strong>în</strong> paralel, iar ele pot fi reutilizate<br />

<strong>si</strong>/sau rescrise prin intermediul mostenirii. Exista <strong>de</strong> asemenea <strong>si</strong> limbaje <strong>de</strong><br />

programare <strong>în</strong> care este permisa etichetarea operatiilor unei clase ca fiind rutine<br />

autonome. De<strong>si</strong> rutinele autonome par a fi mai bine integrate <strong>în</strong> paradigma orientata-<br />

obiect <strong>de</strong>cât procesele, ele sufera <strong>de</strong> acelea<strong>si</strong> <strong>de</strong>zavantaje (favorizeaza distrugerea<br />

<strong>în</strong>capsularii <strong>si</strong> a modularitatii).<br />

O forma speciala <strong>de</strong> rutina autonoma este rutina activa. Aceasta rutina este<br />

lansata <strong>în</strong> executie <strong>în</strong> momentul creerii obiectului <strong>si</strong> ea "supervizeaza" executia<br />

celorlalte operatii ale obiectului. Astfel, rutina activa - numita <strong>si</strong> corp-ul clasei sau<br />

rutina <strong>de</strong> vitalizare (life routine) - trateaza toate mesajele (sau apelurile <strong>de</strong> operatii)<br />

lansate catre obiect. Daca rutina activa î<strong>si</strong> <strong>în</strong>ceteaza activitatea atunci obiectul nu mai<br />

poate fi utilizat. În general codul unei astfel <strong>de</strong> rutine contine un ciclu <strong>în</strong> care sunt<br />

receptionate toate mesajele transmise catre obiect <strong>si</strong>, <strong>în</strong> functie <strong>de</strong> anumite<br />

constrângeri <strong>de</strong> <strong>si</strong>ncronizare, lanseaza <strong>în</strong> executie operatiile obiectului<br />

corespunzatoare mesajelor sau stocheaza aceste mesaje <strong>în</strong>tr-o coada <strong>de</strong> asteptare.<br />

Simpla existenta a rutinei active <strong>în</strong>tr-o clasa nu poate duce <strong>în</strong>sa la executarea<br />

<strong>de</strong> activitati concurente. Concurenta poate fi obtinuta prin transmiterea a<strong>si</strong>ncrona a<br />

unui mesaj <strong>de</strong> catre un obiect apelant sau prin utilizarea <strong>în</strong> cadrul rutinei active a unui<br />

mecanism din cele amintite anterior.<br />

Acest mecanism <strong>de</strong> specificare nu garanteaza separarea codului <strong>de</strong><br />

<strong>si</strong>ncronizare <strong>de</strong> codul <strong>de</strong> <strong>implementare</strong> a functionalitatii (principiul al treilea enuntat<br />

<strong>în</strong> sectiunea prece<strong>de</strong>nta). Implicatiile acestui fapt vor fi discutat <strong>în</strong> <strong>de</strong>taliu <strong>în</strong> capitolul<br />

urmator. Aici vom aminti doar ca nesepararea codului <strong>de</strong> <strong>si</strong>ncronizare conduce la<br />

impo<strong>si</strong>bilitatea rescrierii unei rutine active a unei super-clase <strong>în</strong> <strong>de</strong>scen<strong>de</strong>ntii sai fara a<br />

cunoaste codul <strong>de</strong> <strong>implementare</strong> al acesteia (prin urmare, <strong>de</strong>termina distrugerea<br />

<strong>în</strong>capsularii).<br />

23


Mecanismele <strong>de</strong> specificare a <strong>concurentei</strong> prezentate pot fi împartite <strong>în</strong> doua<br />

categorii: mecanisme care pot <strong>de</strong>clansa o <strong>si</strong>ngura activitate concurenta la un moment<br />

dat (fork-join & mecanisme echivalente, cod autonom), respectiv mecanisme care pot<br />

<strong>de</strong>clansa un numar oarecare <strong>de</strong> activitati concurente (cobegin - coend, forall,<br />

aggregate, etc.).<br />

De asemenea, primele trei tipuri <strong>de</strong> mecanisme discutate (paralelizare<br />

automata, fork-join & mecanisme echivalente, cobegin - coend) sunt orientate pe fire<br />

<strong>de</strong> executie. Activitatile care sunt create <strong>si</strong> lansate <strong>în</strong> executie prin intermediul acestor<br />

mecanisme nu sunt corelate cu nici o structura <strong>de</strong> date. Spre <strong>de</strong>osebire <strong>de</strong> acestea,<br />

ultimele doua categorii <strong>de</strong> mecanisme (cod autonom, forall, aggregate, etc.) privesc<br />

paralelismul ca fiind legat <strong>de</strong> anumite structuri <strong>de</strong> date (activitatile concurente<br />

opereaza asupra unei structuri <strong>de</strong> date particulare sau sunt asociate <strong>si</strong>ntactic <strong>de</strong> un<br />

anumit obiect sau clasa). Mecanismele care par a se integra cel mai usor <strong>în</strong>tr-un cadru<br />

orientat-obiect sunt acestea din urma. Totu<strong>si</strong>, superioritatea unuia sau altuia dintre<br />

mecanisme nu poate fi <strong>de</strong>terminata <strong>în</strong> aceasta etapa, fara sa fie luate <strong>în</strong> con<strong>si</strong><strong>de</strong>rare <strong>si</strong><br />

mecanismele care realizeaza coordonarea <strong>concurentei</strong>.<br />

2.4. Mecanisme <strong>de</strong> interactiune <strong>si</strong> <strong>si</strong>ncronizare a obiectelor concurente<br />

În cele ce urmeaza vom realiza o evaluare a mecanismelor <strong>de</strong> interactiune <strong>si</strong><br />

<strong>si</strong>ncronizare <strong>în</strong>tre activitati concurente utilizate <strong>în</strong> peste o suta <strong>de</strong> limbaje <strong>de</strong><br />

programare orientate-obiect concurente. Evaluarea acestor mecanisme se va realiza <strong>în</strong><br />

raport cu respectarea principiilor enuntate <strong>în</strong> cadrul sectiunii 2.2. Vom propune <strong>de</strong><br />

asemenea exten<strong>si</strong>i ale limbajului C++ care permit <strong>implementare</strong>a mecanismelor<br />

studiate. Aceste exten<strong>si</strong>i vizeaza introducerea <strong>de</strong> constructii <strong>de</strong> <strong>de</strong>clarare sau<br />

instructiuni noi <strong>si</strong> ele pot fi utilizate <strong>în</strong> <strong>de</strong>zvoltarea <strong>de</strong> aplicatii prin construirea <strong>de</strong><br />

preprocesoare sau compilatoare speciale. Utilizarea exten<strong>si</strong>ilor este exemplificata<br />

prin <strong>implementare</strong>a <strong>de</strong> ver<strong>si</strong>uni concurente ale clasei Coada, a carei specificare a fost<br />

data <strong>în</strong> cadrul sectiunii 2.2. Exten<strong>si</strong>ile <strong>de</strong> limbaj sunt scoase <strong>în</strong> evi<strong>de</strong>nta <strong>în</strong><br />

fragmentele <strong>de</strong> cod sursa prin utilizarea <strong>de</strong> caractere pline.<br />

Figura 2.3 prezinta o cla<strong>si</strong>ficare a mecanismelor evaluate. O prima categorie<br />

este data <strong>de</strong> mecanismele care a<strong>si</strong>gura gestionarea corespunzatoare a proprietatilor<br />

24


partajate <strong>de</strong> mai multe operatii din interiorul acestora. Mecanismele din aceasta<br />

categorie nu impun conditii <strong>de</strong> <strong>si</strong>ncronizare la nivel <strong>de</strong> obiect, iar interfetele<br />

obiectelor vor ramâne neschimbate <strong>si</strong> sunt acce<strong>si</strong>bile pe <strong>în</strong>treaga perioada <strong>de</strong> viata a<br />

acestora. În general aceste mecanisme nu respecta principiul interactiunii orientate pe<br />

apelant.<br />

Mecanisme <strong>de</strong> interactiune orientate pe operatii:<br />

<strong>si</strong>ncronizare prin terminare,<br />

semafoare, mutex <strong>si</strong> lock,<br />

regiuni critice conditionale,<br />

<strong>si</strong>ncronizare "piggy-backed"<br />

Mecanisme <strong>de</strong> interactiune bazate pe <strong>în</strong>capsulare:<br />

a) mecanisme cu control extern:<br />

monitorul,<br />

variabile <strong>de</strong> conditie,<br />

asteptarea conditionala<br />

b) mecanisme cu control mixt:<br />

coada <strong>de</strong> asteptare,<br />

inclu<strong>de</strong>re/exclu<strong>de</strong>re <strong>de</strong> meto<strong>de</strong>,<br />

abstractizarea comportamentului,<br />

mo<strong>de</strong>lul Actor,<br />

meto<strong>de</strong> cu garzi,<br />

multimi <strong>de</strong> acceptare,<br />

expre<strong>si</strong>i <strong>de</strong> cale,<br />

rutine <strong>de</strong> vitalizare,<br />

c) mecanisme cu control reflectiv<br />

Figura 2.3. Cla<strong>si</strong>ficarea mecanismelor <strong>de</strong> interactiune <strong>si</strong> <strong>si</strong>ncronizare<br />

a obiectelor concurente<br />

Caracteristica principala a mecanismelor <strong>de</strong> interactiune concurenta orientate<br />

pe <strong>în</strong>capsulare este aceea ca impun un caracter dinamic interfetelor <strong>de</strong> obiecte.<br />

Aceste mecanisme permit <strong>în</strong>târzierea executarii <strong>de</strong> operatii <strong>în</strong> functie <strong>de</strong> anumite<br />

conditii date, <strong>în</strong>târzieri care pot fi privite ca <strong>si</strong> <strong>în</strong><strong>de</strong>partari temporare a operatiilor<br />

respective din interfata unui obiect. Dupa cum sugereaza <strong>si</strong> numele, mecanismele din<br />

aceasta categorie sunt <strong>în</strong>tâlnite numai <strong>în</strong> limbajele <strong>de</strong> programare <strong>în</strong> care este <strong>de</strong>finit<br />

conceptul <strong>de</strong> <strong>în</strong>capsulare a datelor. Majoritatea acestor mecanisme au fost <strong>de</strong>zvoltate<br />

odata cu <strong>de</strong>zvoltarea <strong>de</strong> limbaje <strong>de</strong> programare orientate-obiect concurente.<br />

Toate mecanismele din aceasta categorie realizeaza coordonarea activitatilor<br />

concurente la nivelul obiectelor. Diferenta majora dintre ele este data <strong>de</strong> gradul <strong>de</strong><br />

distributie a responsabilitatii <strong>de</strong> control al acestei coordonari <strong>în</strong>tre <strong>si</strong>stem <strong>si</strong> obiecte.<br />

În functie <strong>de</strong> raspunsul dat la aceasta <strong>în</strong>trebare se pot distinge trei subcategorii<br />

25


distincte <strong>de</strong> mecanisme <strong>de</strong> interactiune concurenta orientate pe <strong>în</strong>capsulare: cu control<br />

extern, cu control mixt <strong>si</strong> cu control reflectiv.<br />

Mecanismele <strong>de</strong> interactiune cu control extern sunt caracterizate <strong>de</strong> faptul ca<br />

<strong>si</strong>stemul este cel care este direct raspunzator <strong>de</strong> interactiunea dintre obiecte. În acest<br />

caz, coordonarea interactiunii concurente nu este specificata explicit. Astfel,<br />

specificarea claselor <strong>de</strong> obiecte nu influenteaza ordinea <strong>de</strong> satisfacere a apelurilor<br />

concurente <strong>de</strong> operatii <strong>si</strong> nici nu poate <strong>de</strong>ci<strong>de</strong> care operatie va fi executata <strong>si</strong> care nu la<br />

un moment dat. Acest lucru este realizat implicit <strong>de</strong> catre <strong>si</strong>stem. Mecanismele care<br />

fac parte din aceasta subcategorie respecta principiul codului <strong>de</strong> interactiune orientat<br />

pe obiectul apelat. De asemenea, <strong>de</strong>oarece <strong>în</strong> cadrul claselor nu exista cod explicit<br />

care sa <strong>de</strong>scrie interactiunea concurenta dintre obiecte este evi<strong>de</strong>nt faptul ca sunt<br />

respectate <strong>si</strong> principiile cu privire la izolarea <strong>si</strong> separarea codului <strong>de</strong> interactiune. Un<br />

<strong>de</strong>zavantaj important al acestor mecanisme rezulta din po<strong>si</strong>bilitatile reduse <strong>de</strong><br />

specificare a <strong>concurentei</strong>, la un moment dat <strong>în</strong> cadrul unui obiect fiind permisa<br />

executia unei <strong>si</strong>ngure operatii. Daca <strong>în</strong> interiorul unui obiect exista o operatie <strong>în</strong><br />

executie, toate celelalte mesaje <strong>de</strong> apel <strong>de</strong> operatii receptionate <strong>de</strong> obiect vor fi<br />

amânate pâna când executia acesteia se <strong>în</strong>cheie. Aceasta restrictie conduce la crearea<br />

<strong>de</strong> programe concurente cu performante reduse.<br />

În cazul mecanismelor cu control mixt responsabilitatea coordonarii<br />

interactiunilor dintre activitatile concurente din cadrul unui obiect este împartita <strong>în</strong>tre<br />

<strong>si</strong>stem <strong>si</strong> <strong>de</strong>scrierea clasei obiectului. Astfel, codul scris pentru <strong>implementare</strong>a<br />

obiectelor contine portiuni care au ca unic scop specificarea interactiunilor concurente<br />

(mai precis realizarea modificarii dinamice a interfetei obiectului). Sistemul<br />

reactioneaza la rândul sau corespunzator acestor specificari. În general mecanismele<br />

cu control mixt respecta principiul codului <strong>de</strong> interactiune orientat pe obiectul apelat.<br />

Mecanismele <strong>de</strong> interactiune cu control reflectiv se caracterizeaza prin<br />

<strong>de</strong>sprin<strong>de</strong>rea totala a codului <strong>de</strong> interactiune <strong>de</strong> <strong>implementare</strong>a clasei. În acest caz se<br />

pot formula constrângeri <strong>de</strong> interactiune explicit, <strong>în</strong> cadrul unor asa-numite metaclase.<br />

În cele ce urmeaza vor fi <strong>de</strong>scrise <strong>si</strong> <strong>analiza</strong>te <strong>în</strong> <strong>de</strong>taliu fiecare dintre<br />

mecanismele enumerate <strong>în</strong> figura 2.3, rezultatele evaluarii acestora fiind prezentate <strong>în</strong><br />

finalul capitolului <strong>în</strong>tr-un format tabelar.<br />

26


2.2.1. Mecanisme <strong>de</strong> interactiune orientate pe operatii<br />

Sincronizare prin terminare. Aproape toate mecanismele <strong>de</strong> initiere a<br />

<strong>concurentei</strong> prezentate (exceptie facând doar cele din categoria cod autonom)<br />

furnizeaza <strong>si</strong> o modalitate prin care o activitate poate fi blocata pâna când o alta<br />

activitate (sau mai multe activitati) se termina. Principalul <strong>de</strong>zavantaj al acestei<br />

primitive este faptul ca nu respecta principiul interactiunii orientate pe obiectul apelat.<br />

Semafoare, mutex <strong>si</strong> lock. Un concept <strong>de</strong> baza al organizarii accesului<br />

concurent la date partajate este semaforul (împreuna cu ver<strong>si</strong>unile mutex <strong>si</strong> lock care<br />

reprezinta cazuri particulare), mecanism care a fost propus <strong>de</strong> catre E. W. Dijkstra <strong>în</strong><br />

[DIJ68]. Un semafor este implementat prin intermediul unei variabile <strong>în</strong>tregi<br />

nenegative asupra careia sunt permise doua operatii atomice: prima operatie se<br />

numeste P (sau wait) <strong>si</strong> ea blocheaza executia activitatii care o apeleaza pâna variabila<br />

<strong>de</strong>vine strict pozitiva dupa care o <strong>de</strong>crementeaza, iar cea <strong>de</strong>-a doua operatie, numita V<br />

(sau <strong>si</strong>gnal) incrementeaza aceasta variabila. Programatorul va folo<strong>si</strong> aceste doua<br />

operatii pentru a <strong>de</strong>limita o sectiune critica 2 .<br />

Semafoarele sunt mecanisme <strong>de</strong> nivel scazut, cu un caracter foarte general.<br />

Aceasta generalitate poate <strong>de</strong>termina cu usurinta intrarea <strong>în</strong>tr-un impas daca<br />

<strong>implementare</strong>a nu este realizata cu mare atentie, iar <strong>de</strong>panarea programelor este<br />

evi<strong>de</strong>nt <strong>în</strong>greunata. Ele sunt <strong>de</strong>osebit <strong>de</strong> utile <strong>în</strong> implementari <strong>de</strong> <strong>în</strong>alta performanta la<br />

nivel <strong>de</strong> <strong>si</strong>stem. Totu<strong>si</strong>, integrarea lor <strong>în</strong>tr-un mediu orientat obiect nu este o alegere<br />

potrivita, ele nerespectând majoritatea dintre principiile enuntate anterior.<br />

Asa cum am anticipat, acest mecanism nu respecta principiul coordonarii<br />

orientate pe activitatea apelata, <strong>de</strong>oarece apelatorul este responsabil cu <strong>implementare</strong>a<br />

acceptarii unui potential paralelism. În acest caz se remarca acelea<strong>si</strong> probleme care au<br />

fost discutate <strong>si</strong> la <strong>si</strong>ncronizarea prin terminare. De aceea este po<strong>si</strong>bila violarea<br />

modularitatii <strong>si</strong>, <strong>în</strong> consecinta, este dificil <strong>de</strong> a <strong>de</strong>monstra corectitudinea implementarii<br />

unei clase.<br />

27


Totu<strong>si</strong>, din punct <strong>de</strong> ve<strong>de</strong>re conceptual exista o modalitate <strong>de</strong> a rezolva aceasta<br />

problema. Astfel, daca limbajul <strong>de</strong> programare permite folo<strong>si</strong>rea semafoarelor doar<br />

pentru marcarea <strong>de</strong> sectiuni critice ce se refera la proprietati private, atunci codul <strong>de</strong><br />

coordonare a <strong>concurentei</strong> poate fi implementat cu respectarea principiului codului <strong>de</strong><br />

interactiune orientat pe activitatea apelata, dar evi<strong>de</strong>nt numai relativ la apelatorii care<br />

fac parte din celelalte clase din domeniul aplicatiei. Nici unul dintre limbajele <strong>de</strong><br />

programare orientate-obiect concurente cunoscute nu suporta <strong>în</strong>sa o astfel <strong>de</strong><br />

restrictie.<br />

Pe <strong>de</strong> alta parte semafoarele au o putere restrânsa <strong>de</strong> specificare a<br />

interactiunilor <strong>în</strong>tre fire <strong>de</strong> executie concurente. Astfel, <strong>de</strong>oarece initializarea<br />

variabilei unui semafor poate permite executia paralela a mai multor activitati <strong>în</strong><br />

interiorul unei sectiuni critice este po<strong>si</strong>bila <strong>implementare</strong>a <strong>concurentei</strong> intra-obiect.<br />

Semafoarele <strong>în</strong>sa nu ofera suport pentru coordonarea <strong>concurentei</strong> <strong>de</strong>pen<strong>de</strong>nta <strong>de</strong><br />

istoric. Mai mult, este dificila <strong>implementare</strong>a unei interactiuni conditionale <strong>în</strong>tre mai<br />

multe activitati <strong>de</strong>oarece conditia <strong>si</strong> evaluarea acesteia trebuie <strong>si</strong>mulata explicit prin<br />

intermediul operatiilor asupra variabilei semaforului. Prin urmare semafoarele nu<br />

ofera un suport real pentru executia <strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> stare.<br />

De asemenea, semafoarele nu satisfac principiul izolarii codului <strong>de</strong><br />

interactiune. Exemplul care urmeaza, <strong>în</strong> care este implementata clasa Coada,<br />

ilustreaza foarte clar importanta acestui principiu. Bine<strong>în</strong>teles, nerespectarea <strong>de</strong> catre<br />

semafoare a principiului izolarii codului <strong>de</strong> interactiune atrage automat dupa <strong>si</strong>ne <strong>si</strong><br />

nerespectarea principiului separarii acestuia.<br />

class Coada{<br />

. . .<br />

//<strong>de</strong>clararea tuturor proprietatilor <strong>si</strong> a operatiilor este i<strong>de</strong>ntica<br />

//cu cea din exemplul <strong>de</strong> <strong>implementare</strong> secventiala<br />

. . .<br />

//<strong>de</strong>clararea <strong>de</strong> proprietati specifice <strong>si</strong>ncronizarii<br />

//cu semafoare<br />

private:<br />

semaphore pozGoale;<br />

semaphore pozPline;<br />

semaphore secCritica1;//pt. modificare elemIntroduse<br />

semaphore secCritica2;//pt. modificare elemExtrase<br />

}<br />

Implementarea cozii <strong>de</strong>clarate mai sus este realizata astfel <strong>în</strong>cât sa fie respectat<br />

principiul codului <strong>de</strong> interactiune orientat pe obiectul apelat <strong>în</strong> maniera amintita mai<br />

2 sectiune critica = fragment <strong>de</strong> cod <strong>în</strong> care se realizeaza anumite actiuni asupra unei proprietati<br />

partajate<br />

28


sus (adica semafoarele marcheaza sectiuni critice caracteristice unor proprietati<br />

private ale clasei). Semafoarele pozGoale <strong>si</strong> pozPline coordoneaza adaugarea,<br />

respectiv extragerea <strong>de</strong> elemente din coada (<strong>în</strong> functie <strong>de</strong> starea <strong>în</strong> care se afla<br />

aceasta), iar secCritica1 <strong>si</strong> secCritica2 au rolul <strong>de</strong> a evita efectuarea <strong>de</strong> modificari<br />

concurente asupra proprietatilor private elemIntroduse, respectiv elemExtrase precum<br />

<strong>si</strong> realizarea <strong>în</strong> paralel a introducerii <strong>si</strong> extragerii efective <strong>de</strong> elemente. Prin urmare<br />

exemplul surprin<strong>de</strong> atât <strong>implementare</strong>a exclu<strong>de</strong>rii mutuale cât <strong>si</strong> a <strong>si</strong>ncronizarii<br />

conditionale.<br />

Coada::Coada():<br />

pozGoale(100),<br />

pozPline(0),<br />

secCritica1(1),<br />

secCritica2(1)<br />

{<br />

//pentru <strong>si</strong>mplitate nu am <strong>de</strong>finit constructor explicit<br />

maxElem=100;<br />

listaElemente=new [maxElem] Element;<br />

elemIntroduse=elemExtrase=0;<br />

}<br />

Coada::~Coada(){<br />

... //<strong>de</strong>structor i<strong>de</strong>ntic cu cel din ver<strong>si</strong>unea secventiala<br />

}<br />

void Coada::Adauga(Element elem){<br />

pozGoale.P();<br />

secCritica1.P();<br />

elemIntroduse++;<br />

listaElemente[elemIntroduse % maxElem - 1]=elem<br />

secCritica1.V();<br />

pozPline.V();<br />

}<br />

Element Coada::Extrage(){<br />

pozPline.P();<br />

secCritica2.P();<br />

elemExtrase++;<br />

Element elemTmp=listaElemente[elemExtrase % maxElem - 1];<br />

secCritica2.V();<br />

pozGoale.V();<br />

return elemTmp;<br />

}<br />

Asa cum se poate observa din <strong>implementare</strong>a <strong>de</strong> mai sus, operatiile asupra<br />

semafoarelor (care <strong>de</strong>limiteaza sectiunea critica) sunt efectuate <strong>în</strong> interiorul corpului<br />

operatiilor clasei. Prin urmare, codul care <strong>de</strong>scrie interactiunea concurenta nu este<br />

separat <strong>de</strong> codul care implementeaza functionalitatea operatiilor, lucru care poate<br />

<strong>de</strong>termina aparitia asa-numitelor anomalii <strong>de</strong> mostenire <strong>în</strong> cazul reutilizarii.<br />

La rândul lor, mecanismele mutex (<strong>de</strong>rivat pe baza termenului <strong>de</strong> exclu<strong>de</strong>re<br />

mutuala) <strong>si</strong> lock sunt cazuri particulare <strong>de</strong> semafoare care permit unei <strong>si</strong>ngure<br />

activitati sa intre <strong>în</strong> sectiunea critica la un moment dat. Concluziile trase relativ la<br />

29


semafoare sunt valabile <strong>si</strong> pentru aceste mecanisme care pot fi foarte usor <strong>si</strong>mulate cu<br />

operatii pe semafoare.<br />

Regiuni critice conditionale. Regiunile critice conditionale au fost proiectate<br />

pentru a se furniza un suport <strong>si</strong>ntactic pentru <strong>si</strong>ncronizarea conditionala. De<br />

asemenea, spre <strong>de</strong>osebire <strong>de</strong> semafoare, coordonarea accesului la variabilele partajate<br />

este mai transparent. I<strong>de</strong>ea principala <strong>în</strong> cazul regiunilor critice conditionale este<br />

aceea <strong>de</strong> a grupa laolalta mai multe variabile <strong>în</strong> cadrul unor asa-numite resurse.<br />

Oricare variabila poate corespun<strong>de</strong> unei <strong>si</strong>ngure resurse, iar <strong>de</strong>clararea se face astfel:<br />

resource r={v1, v2, ..., vn}<br />

Regiunea critica este apoi specificata <strong>în</strong> cod astfel:<br />

region r when { }<br />

un<strong>de</strong> reprezinta <strong>de</strong>scrierea actiunilor care urmeaza sa fie<br />

executate <strong>de</strong> catre activitate <strong>în</strong> cazul <strong>în</strong> care este evaluata ca a<strong>de</strong>varata. În<br />

cazul <strong>în</strong> care expre<strong>si</strong>a nu este a<strong>de</strong>varata sau resursa r este ocupata <strong>de</strong> catre<br />

o alta activitate paralela, activitatea curenta intra <strong>în</strong>tr-o coada <strong>de</strong> asteptare.<br />

Implementarea ver<strong>si</strong>unii concurente a clasei Coada folo<strong>si</strong>nd regiuni critice<br />

conditionale este redata mai jos:<br />

class Coada{<br />

. . .<br />

//<strong>de</strong>clararea tuturor proprietati <strong>si</strong> a operatiilor este i<strong>de</strong>ntica<br />

//cu cea din exemplul <strong>de</strong> <strong>implementare</strong> secventiala<br />

. . .<br />

//<strong>de</strong>clararea <strong>de</strong> proprietati specifice <strong>si</strong>ncronizarii<br />

//cu regiuni critice conditionale<br />

private:<br />

resource r1={elemIntroduse};<br />

resource r2={elemExtrase};<br />

}<br />

//constructor <strong>si</strong> <strong>de</strong>structor i<strong>de</strong>ntici cu cei din ver<strong>si</strong>unea secventiala<br />

. . .<br />

void Coada::Adauga(Element elem){<br />

region r1 when(elemIntroduse-elemExtrase 0){<br />

elemExtrase++;<br />

unElement=listaElemente[elemExtrase % maxElem - 1];<br />

}<br />

return unElement;<br />

}<br />

30


Regiunile critice conditionale se afla <strong>în</strong>tr-o relatie foarte strânsa cu<br />

semafoarele ele putând fi <strong>si</strong>mulate prin intermediul acestora. În concluzie regiunile<br />

conditionale sunt caracterizate <strong>de</strong> acelea<strong>si</strong> <strong>de</strong>zavantaje ca <strong>si</strong> semafoarele. În plus,<br />

regiunile critice conditionale nu permit intrarea <strong>în</strong>tr-o anumita regiune <strong>de</strong>cât a unei<br />

<strong>si</strong>ngure activitati la un moment dat. Prin urmare nu se poate exprima un paralelism<br />

intra-obiect folo<strong>si</strong>nd acest tip <strong>de</strong> mecanism <strong>de</strong> interactiune concurenta.<br />

Pe <strong>de</strong> alta parte <strong>în</strong>sa, existenta clauzei when <strong>în</strong> <strong>si</strong>ntaxa regiunii critice<br />

conditionale face ca acest mecanism sa fie potrivit pentru a coordona mai multe<br />

activitati paralele <strong>în</strong> functie <strong>de</strong> starea unei instante la un moment dat.<br />

De asemenea, regiunile critice conditionale reusesc sa elimine anumite<br />

probleme care apar <strong>în</strong> cazul semafoarelor <strong>si</strong> care se datoreaza caracterului general al<br />

acestora din urma. Astfel, nu apare pericolul <strong>de</strong> a ignora <strong>în</strong>chi<strong>de</strong>rea unei regiuni<br />

critice, iar <strong>implementare</strong>a unor interactiuni concurente <strong>de</strong> nivel mai <strong>în</strong>alt se realizeaza<br />

cu mai mare usurinta <strong>de</strong>cât <strong>în</strong> cazul semafoarelor datorita specificarii grupate <strong>si</strong><br />

explicite a conditiilor.<br />

Totu<strong>si</strong>, problemele principale ramân: <strong>în</strong> cazul <strong>în</strong> care <strong>implementare</strong>a<br />

interactiunilor concurente nu este atent realizata se poate ajunge foarte usor la <strong>si</strong>tuatii<br />

<strong>de</strong> impas, iar raspunsul la <strong>în</strong>trebarea "ce <strong>si</strong> când se <strong>în</strong>capsuleaza <strong>în</strong>tr-o regiune<br />

critica?" trebuie sa fie dat <strong>în</strong> continuare <strong>de</strong> catre programator.<br />

Sincronizare "piggy-backed". În limbajele <strong>de</strong> programare <strong>în</strong> care<br />

comunicarea <strong>în</strong>tre activitatile paralele se realizeaza prin transmitere <strong>de</strong> mesaje,<br />

executarea paralela a activitatilor este <strong>si</strong>ncronizata <strong>de</strong> obicei prin comenzi <strong>de</strong> blocare a<br />

comunicarii. Sa con<strong>si</strong><strong>de</strong>ram spre exemplu urmatoarea intructiune care are ca efect<br />

punerea activitatii curente <strong>în</strong> asteptare pâna când este receptionat mesajul m (<strong>si</strong>ntaxa<br />

instructiunii poate permite <strong>si</strong> specificarea sursei care transmite mesajul). :<br />

receive m [from s]<br />

O <strong>si</strong>tuatie <strong>si</strong>milara are loc <strong>si</strong> <strong>în</strong> cazul <strong>în</strong> care este utilizata o abordare <strong>de</strong> tip<br />

"apel invers". În locul unei instructiuni receive explicite <strong>de</strong> acceptare a unui mesaj,<br />

este furnizata o operatie care este apelata <strong>de</strong> s. În ambele cazuri raspunsul activitatii<br />

acceptate este coordonat cu activitatea <strong>de</strong> transmitere.<br />

Majoritatea limbajelor <strong>de</strong> programare orientate-obiect concurente care se<br />

bazeaza pe apeluri a<strong>si</strong>ncrone <strong>de</strong> operati, mesaje <strong>si</strong> variabile future (discutate <strong>în</strong><br />

31


sectiunea anterioara) ofera po<strong>si</strong>bilitatea <strong>si</strong>ncronizarii <strong>de</strong> tip "piggy-backed". Din<br />

nefericire acest tip <strong>de</strong> <strong>si</strong>ncronizare nece<strong>si</strong>ta cunoasterea cu exactitate a protocolului <strong>de</strong><br />

apelare. Apelatorul trebuie sa stie ce mesaj este asteptat <strong>de</strong> catre obiectul tinta.<br />

Deoarece acest tip <strong>de</strong> informatie nu este acce<strong>si</strong>bila prin intermediul interfetei<br />

obiectului "apelat"; este necesar ca apelatorul sa cunoasca anumite <strong>de</strong>talii privind<br />

<strong>implementare</strong>a obiectului apelat. Prin urmare nu este respectat principiul orientarii<br />

codului <strong>de</strong> <strong>si</strong>ncronizare pe obiectul apelat. Din aceasta cauza nu sunt respectate nici<br />

principiile izolarii <strong>si</strong> a separarii codului <strong>de</strong> interactiune.<br />

Mai mult, <strong>si</strong>ncronizarea "piggy-baked" permite acceptarea unui <strong>si</strong>ngur mesaj<br />

la un moment dat, ceea ce <strong>în</strong>seamna ca nu poate fi folo<strong>si</strong>ta pentru exprimarea<br />

<strong>concurentei</strong> intra-obiect. Bine<strong>în</strong>teles, acest mecanism este capabil sa implementeze o<br />

interactiune inter-activitati <strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> starea obiectului.<br />

Deoarece <strong>si</strong> acest mecanism <strong>de</strong> comunicare (ca <strong>si</strong> regiunile critice<br />

conditionale) poate fi mo<strong>de</strong>lat cu ajutorul semafoarelor, <strong>de</strong>zavantajele amintite la<br />

acestea din urma sunt valabile <strong>si</strong> pentru <strong>si</strong>ncronizarea "piggy-baked".<br />

2.2.2. Mecanisme <strong>de</strong> interactiune concurenta bazate pe <strong>în</strong>capsulare<br />

a) Mecanisme <strong>de</strong> interactiune concurenta cu control extern<br />

Monitorul. Din punctul <strong>de</strong> ve<strong>de</strong>re al unui programator <strong>de</strong> aplicatii concurente<br />

monitorul poate fi con<strong>si</strong><strong>de</strong>rat ca <strong>si</strong> o combinatie <strong>si</strong>ntactica <strong>în</strong>tre <strong>de</strong>finirea unei resurse<br />

(v. regiunile critice conditionale) <strong>si</strong> operatiile care sunt aplicate asupra variabilelor<br />

dintr-o resursa, la un moment dat putând fi executata o <strong>si</strong>ngura operatie asupra unei<br />

variabile din resursa respectiva. Din perspectiva unui programator <strong>de</strong> aplicatii<br />

orientate-obiect monitorul poat fi privit ca <strong>si</strong> un obiect ce poseda propriile variabile<br />

(prorpietati) care îi <strong>de</strong>finesc starea <strong>si</strong> furnizeaza meto<strong>de</strong> (operatiile asupra<br />

proprietatilor) prin apelarea carora poate fi modificata aceasta stare.<br />

De<strong>si</strong> monitoarele satisfac majoritatea principiilor care au fost enuntate <strong>în</strong><br />

sectiunea 2.2, ele sunt caracterizate printr-o putere scazuta <strong>de</strong> exprimare a<br />

<strong>concurentei</strong>. Acest lucru este <strong>de</strong>terminat, asa cum am mentionat mai <strong>de</strong>vreme, <strong>de</strong><br />

faptul ca este permisa executia doar a unei <strong>si</strong>ngure meto<strong>de</strong> dintr-un monitor la un<br />

moment dat. Mai mult, monitoarele nu pot fi utilizate <strong>în</strong> <strong>implementare</strong>a <strong>de</strong><br />

32


<strong>si</strong>ncronizari conditionale, <strong>si</strong> <strong>de</strong>ci nu poate fi realizata o <strong>si</strong>ncronizare inter-activitati<br />

<strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> starea monitorului (mai exact, starea obiectului reprezentat printr-un<br />

monitor) la un moment dat. "Greutatea" acestui <strong>de</strong>zavantaj poate fi masurata prin<br />

prisma unui exemplu ce va fi dat <strong>în</strong> cele ce urmeaza <strong>si</strong> care implementeaza o clasa<br />

Coada folo<strong>si</strong>nd monitorul ca mecanism <strong>de</strong> interactiune intre activitatile concurente.<br />

class monitor Coada{<br />

protected:<br />

Element listaElemente[]; //tablou cu elementele cozii<br />

int maxElem; //nr. maxim <strong>de</strong> elemente din coada<br />

int elemIntroduse; //nr. elementelor introduse <strong>în</strong> coada<br />

int elemExtrase; //nr. elementelor extrase din coada<br />

public:<br />

Coada(){…};<br />

~Coada(){…};<br />

void Adauga(Element elem) {…};<br />

Element Extrage(){…};<br />

BOOL EGoala(return elemIntroduse-elemExtrase==0;);<br />

BOOL EPlina(return elemIntroduse-elemExtrase==maxElem;)<br />

}<br />

Daca monitorul permitea mo<strong>de</strong>larea <strong>si</strong>ncronizarii conditionale atunci, <strong>în</strong><br />

momentul <strong>în</strong> care un obiect <strong>de</strong> tip Coada ar fi fost <strong>în</strong> starea plin (adica au fost<br />

introduse <strong>în</strong> coada cu maxElemente mai multe elemente <strong>de</strong>cât au fost extrase) <strong>si</strong> ar fi<br />

receptionat un mesaj Adauga(), mesajul respectiv ar fi fost pus <strong>în</strong>tr-o coada <strong>de</strong><br />

asteptare urmând ca, dupa extragerea a cel putin unui element, mesajul sa fie acceptat.<br />

Din pacate monitorul nu poseda nici o modalitate <strong>de</strong> specificare a activarii sau<br />

inactivarii unei operatii pe baza unei conditii. Pozitionarea mesajelor <strong>în</strong>tr-o coada <strong>de</strong><br />

asteptare se realizeaza strict pentru respectarea exclu<strong>de</strong>rii mutuale.<br />

Astfel, pentru a se tine cont <strong>de</strong> starea unui obiect, trebuiesc <strong>de</strong>finite <strong>în</strong> clasa<br />

Coada doua meto<strong>de</strong> care sa poata fi folo<strong>si</strong>te la inspectarea acestei stari - EGoala(),<br />

respectiv EPlina(). Cele doua meto<strong>de</strong> vor fi folo<strong>si</strong>te <strong>de</strong> catre obiectele care doresc<br />

introducerea sau extragerea <strong>de</strong> elemente dintr-un obiect <strong>de</strong> tip Coada. Acest lucru<br />

<strong>în</strong>sa implica nerespectarea principiului implementarii codului <strong>de</strong> interactiune <strong>în</strong> cadrul<br />

obiectului apelat.<br />

Un alt <strong>de</strong>zavantaj major al monitoarelor este acela ca <strong>în</strong> cazul unei utilizari<br />

neglijente ele pot conduce cu usurinta, asemanator semafoarelor, la <strong>si</strong>tuatii <strong>de</strong> impas.<br />

Aceasta problema este cunoscuta <strong>în</strong> literatura <strong>de</strong> specialitate <strong>si</strong> sub <strong>de</strong>numirea <strong>de</strong><br />

problema apelului monitoarelor <strong>în</strong>castrate (nested monitors call).<br />

33


Variabile <strong>de</strong> conditie. Variabilele <strong>de</strong> conditie reprezinta o exten<strong>si</strong>e a<br />

conceptului <strong>de</strong> monitor <strong>si</strong> ele au fost introduse <strong>de</strong> C. A. R. Hoare <strong>în</strong> 1974 [HOA74].<br />

Prin aceasta exten<strong>si</strong>e o activitate intrata <strong>în</strong>tr-un monitor poate fi blocata <strong>în</strong> interiorul<br />

acestuia cu ajutorul unei variabile <strong>de</strong> conditie. Cât timp aceasta activitate este blocata<br />

se poate da curs unui solicitari <strong>de</strong> apel <strong>de</strong> operatie care se afla <strong>în</strong> coada <strong>de</strong> asteptare a<br />

monitorului. O variabila <strong>de</strong> conditie are doua operatii, wait <strong>si</strong> <strong>si</strong>gnal, care pot<br />

<strong>de</strong>termina blocarea sau <strong>de</strong>blocarea unei activitati. Problema care apare este data <strong>de</strong><br />

alegerea algortimului <strong>de</strong> <strong>de</strong>cizie <strong>în</strong> cazul <strong>de</strong>blocarii a doua sau mai multe activitati <strong>în</strong><br />

acela<strong>si</strong> timp (<strong>de</strong>oarece, asa cum am vazut, <strong>în</strong>tr-un monitor poate fi activa cel mult o<br />

activitate). De asemenea, trebuie stabilit daca activitatea care a generat <strong>de</strong>blocarea î<strong>si</strong><br />

va continua executia pâna la ie<strong>si</strong>rea din monitor dupa care va fi reactivata una dintre<br />

operatiile <strong>de</strong>blocate sau, dimpotriva, activitatea curenta va fi suspendata pâna când<br />

vor para<strong>si</strong> monitorul activitatile <strong>de</strong>blocate <strong>de</strong> acesta.<br />

Câstigul evi<strong>de</strong>nt al extin<strong>de</strong>rii monitorului cu variabile <strong>de</strong> conditie este acela ca<br />

pot fi mo<strong>de</strong>late <strong>si</strong>ncronizari conditionale <strong>în</strong>tre activitati concurente. Prin urmare pot fi<br />

mo<strong>de</strong>late interactiuni concurente <strong>în</strong> functie <strong>de</strong> starea monitorului la un moment dat.<br />

class monitor Coada{<br />

. . .<br />

//<strong>de</strong>clararea tuturor proprietati <strong>si</strong> a operatiilor este i<strong>de</strong>ntica<br />

//cu cea din exemplul <strong>de</strong> <strong>implementare</strong> secventiala<br />

. . .<br />

//<strong>de</strong>clararea <strong>de</strong> proprietati specifice <strong>si</strong>ncronizarii<br />

//cu variabile <strong>de</strong> conditie<br />

private:<br />

condition Gol;//variabila <strong>de</strong> conditie pentru coada goala<br />

condition Plin;//variabila <strong>de</strong> conditie pentru coada plina<br />

}<br />

void Coada::Adauga(Element elem){<br />

if(elemIntroduse-elemExtrase==maxElem)<br />

Plin.wait();<br />

elemIntroduse++;<br />

listaElemente[elemIntroduse % maxElem - 1]=elem<br />

Gol.<strong>si</strong>gnal();<br />

}<br />

Element Coada::Extrage(){<br />

if(elemIntroduse-elemExtrase==0)<br />

Gol.wait();<br />

elemExtrase++;<br />

Element elemTmp=listaElemente[elemExtrase % maxElem - 1];<br />

Plin.<strong>si</strong>gnal();<br />

return elemTmp;<br />

}<br />

Implementarea unei cozi cu numar limitat <strong>de</strong> elemente folo<strong>si</strong>nd variabilele <strong>de</strong><br />

conditie sugereaza o asemanare dintre aceasta abordare <strong>de</strong> mo<strong>de</strong>lare a interactiunilor<br />

concurente <strong>si</strong> abordarea folo<strong>si</strong>nd semafoare.<br />

34


Aceasta asemanare nu este <strong>în</strong>tâmplatoare (dupa cum nu este <strong>în</strong>tâmplator nici<br />

faptul ca operatiile care corespund variabilelor <strong>de</strong> conditie poarta acela<strong>si</strong> nume ca <strong>si</strong><br />

operatiile corespunzatoare semafoarelor) dar nici benefica. Prin urmare, extin<strong>de</strong>rea<br />

monitorului <strong>în</strong> aceasta maniera este caracterizata <strong>de</strong> acelea<strong>si</strong> <strong>de</strong>zavantaje ce<br />

caracterizeaza <strong>si</strong> semafoarele. Astfel, <strong>de</strong>oarece codul corespunzator coordonarii<br />

interactiunii concurente se implementeaza intercalat cu codul <strong>de</strong> <strong>implementare</strong> a<br />

functionalitatii operatiilor nu mai sunt respectate principiile izolarii <strong>si</strong> separarii<br />

codului <strong>de</strong> interactiune concurenta.<br />

De asemenea, este evi<strong>de</strong>nt mai dificil <strong>de</strong> <strong>de</strong>monstrat corectitudinea unei clase<br />

astfel implementate. Trebuie remarcat <strong>si</strong> faptul ca, <strong>în</strong> cazul <strong>în</strong> care variabilele <strong>de</strong><br />

conditie sunt publice (<strong>de</strong>ci sunt vizibile <strong>în</strong> afara monitoarelor <strong>în</strong> care au fost <strong>de</strong>finite)<br />

poate fi <strong>în</strong>calcat cu usurinta principiul care enunta faptul ca specificarea interactiunii<br />

<strong>în</strong>tre obiecte concurente trebuie sa fie realizata exclu<strong>si</strong>v <strong>în</strong> cadrul entitatii apelate.<br />

Asteptare conditionala. Conceptul <strong>de</strong> asteptare conditionala a fost introdus tot<br />

<strong>în</strong> scopul extin<strong>de</strong>rii monitoarelor pentru a putea fi mo<strong>de</strong>late <strong>si</strong>ncronizari conditionale<br />

inter-activitati. Acest concept a fost introdus <strong>de</strong> catre Kessels <strong>în</strong> anul 1977 [KES77]<br />

<strong>si</strong> este caracterizat <strong>de</strong> separarea <strong>si</strong>ntactica <strong>în</strong> cadrul monitorului a conditiilor <strong>de</strong><br />

<strong>si</strong>ncronizare:<br />

condition is ;<br />

În urma unei <strong>de</strong>claratii ca cea <strong>de</strong> mai sus se poate introduce <strong>în</strong>tr-una dintre<br />

operatiile monitorului linia <strong>de</strong> cod wait() ce are ca efect <strong>în</strong>târzierea<br />

executiei activitatii curente care a apelat operatia respectiva pâna <strong>în</strong> momentul<br />

verificarii conditiei data <strong>de</strong> . Prin aceasta metoda se pot <strong>de</strong>termina cu<br />

usurinta care sunt portiunile <strong>de</strong> cod ce mo<strong>de</strong>leaza <strong>si</strong>ncronizarea concurenta. Din<br />

nefericire <strong>si</strong> <strong>în</strong> acest caz riscul blocarii unei activitati sau al intrarii <strong>în</strong>tr-o <strong>si</strong>tuatie <strong>de</strong><br />

impas este la fel <strong>de</strong> crescut. De asemenea, nu poate fi <strong>de</strong>terminata activitatea care va<br />

fi executata <strong>în</strong> cazul <strong>în</strong> care sunt mai multe activitati blocate <strong>de</strong> aceea<strong>si</strong> conditie iar<br />

conditia este <strong>în</strong><strong>de</strong>plinita <strong>în</strong> momentul executiei unei alte activitati.<br />

Implementarea unei cozi limitate folo<strong>si</strong>nd monitoare extinse cu variabile <strong>de</strong><br />

asteptare conditionala se poate realiza <strong>în</strong> maniera <strong>de</strong> mai jos:<br />

class monitor Coada{<br />

. . .<br />

//<strong>de</strong>clararea tuturor proprietatilor <strong>si</strong> a operatiilor este<br />

//i<strong>de</strong>ntica cu cea din exemplul <strong>de</strong> <strong>implementare</strong> secventiala<br />

35


. . .<br />

//<strong>de</strong>clararea <strong>de</strong> proprietati specifice <strong>si</strong>ncronizarii<br />

//prin asteptare conditionala<br />

private:<br />

//conditia ce este respectata cand coada nu e goala<br />

condition nuGol is not (elemIntroduse-elemExtrase==0);<br />

//conditia ce este respectata cand coada e nu plina<br />

condition nuPlin is not (elemIntroduse-elemExtrase==maxElem);<br />

}<br />

void Coada::Adauga(Element elem){<br />

wait(nuPlin);<br />

elemIntroduse++;<br />

listaElemente[elemIntroduse % maxElem - 1]=elem<br />

}<br />

Element Coada::Extrage(){<br />

wait(nuGol);<br />

elemExtrase++;<br />

Element elemTmp=listaElemente[elemExtrase % maxElem - 1];<br />

return elemTmp;<br />

}<br />

În cadrul acestei implementari am tinut cont <strong>de</strong> faptul ca mecanismul <strong>de</strong><br />

monitor este bazat pe principiul "o <strong>si</strong>ngura activitate executata la un moment <strong>de</strong> timp<br />

dat". În cazul <strong>în</strong> care se doreste mo<strong>de</strong>larea unui paralelism intra-obiect este necesara<br />

inclu<strong>de</strong>rea variabilelor care compun <strong>în</strong> sectiuni critice, <strong>în</strong> caz contrar<br />

valoarea <strong>de</strong> a<strong>de</strong>var rezultata <strong>în</strong> urma evaluarii conditiei din nemaifiind<br />

certa. Introducerea unor astfel <strong>de</strong> sectiuni critice conduce la aparitia unor <strong>de</strong>zavantaje<br />

asemanatoare cu cele care au fost semnalate la semafoare <strong>si</strong> variabile <strong>de</strong> conditie.<br />

Principiul codului <strong>de</strong> interactiune orientat pe obiectul apelat este respectat <strong>de</strong><br />

acest mecanism doar <strong>în</strong> cazul evi<strong>de</strong>nt <strong>în</strong> care i<strong>de</strong>ntificatorii ce reprezinta conditiile<br />

împreuna cu toate variabilele care compun conditiile respective sunt proprietati<br />

private ale obiectului.<br />

Nu poate fi mo<strong>de</strong>lata interactiunea concurenta <strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> istoric. De<br />

asemenea prezenta codului ce <strong>de</strong>scrie interactiunea concurenta <strong>în</strong> cadrul codului care<br />

<strong>de</strong>scrie functionalitatea operatiei <strong>de</strong>termina nerespectarea principiilor izolarii <strong>si</strong><br />

separarii codului <strong>de</strong> <strong>si</strong>ncronizare.<br />

b) Mecanisme <strong>de</strong> interactiune concurenta cu control mixt<br />

Coada <strong>de</strong> asteptare. Anumite limbaje <strong>de</strong> programare orientate-obiect<br />

concurente permit programatorilor sa <strong>de</strong>fineasca instante ale unei clase mai speciale,<br />

numita Coada_<strong>de</strong>_asteptare. Aceste instante pot fi atasate operatiilor unei clase <strong>si</strong> ele<br />

au ca efect scoaterea, respectiv introducerea dinamica a operatiilor respective <strong>în</strong><br />

36


interfata publica a obiectelor clasei. Interfata clasei Coada_<strong>de</strong>_asteptare este<br />

compusa din doua operatii: blocheaza(), respectiv <strong>de</strong>blocheaza(). Daca, <strong>de</strong> exemplu,<br />

o instanta a acestei clase este <strong>de</strong>blocata, atunci se da curs oricarei solicitari <strong>de</strong> apel al<br />

operatiilor atasate instantei, <strong>în</strong> caz contrar apelurile fiind <strong>în</strong>târziate.<br />

Coada_<strong>de</strong>_intarziere CI;<br />

Operatie()/CI {. . .};<br />

În exemplul <strong>de</strong> mai sus operatia Operatie() este atasata cozii <strong>de</strong> asteptare CI.<br />

Daca CI este blocata, apelul operatiei Operatie() este amânat. Apelul poate fi realizat<br />

din momentul <strong>în</strong> care are loc <strong>de</strong>blocarea variabilei CI (<strong>de</strong>blocare ce poate fi realizata<br />

doar <strong>de</strong> catre o activitate care apeleaza una dintre operatiile neblocate ale clasei). Este<br />

important <strong>de</strong> subliniat ca este permisa legarea mai multor operatii ale aceluia<strong>si</strong> obiect<br />

la o aceea<strong>si</strong> coada <strong>de</strong> asteptare.<br />

class Coada{<br />

protected:<br />

Element listaElemente[]; //tablou cu elementele cozii<br />

int maxElem; //nr. maxim <strong>de</strong> elemente din coada<br />

int elemIntroduse; //nr. elementelor introduse <strong>în</strong> coada<br />

int elemExtrase; //nr. elementelor extrase din coada<br />

public:<br />

//cozi <strong>de</strong> intarziere care vor fi blocate in momentul<br />

//in care obiectul Coada va fi plin, respectiv gol.<br />

Coada_<strong>de</strong>_asteptare nuEPlin;<br />

Coada_<strong>de</strong>_ asteptare nuEGol;<br />

. . .<br />

}<br />

void Coada::Adauga (Element elem)/nuEPlin {<br />

elemIntroduse++;<br />

listaElemente[elemIntroduse % maxElem - 1]=elem<br />

nuEGol.<strong>de</strong>blocheaza();<br />

if(elemIntroduse- elemExtrase==0)<br />

nuEPlin.blocheaza();<br />

}<br />

Element Coada::Extrage()/nuEGol{<br />

elemExtrase++;<br />

Element elem= listaElemente[elemExtrase % maxElem - 1];<br />

nuEPlin.<strong>de</strong>blocheaza();<br />

if(elemIntroduse- elemExtrase==0)<br />

nuEGol.blocheaza();<br />

return elem<br />

}<br />

Cozile <strong>de</strong> asteptare respecta principiul al doilea enuntat la <strong>în</strong>ceputul acestei<br />

sectiuni daca variabilele <strong>de</strong> tip Coada_<strong>de</strong>_asteptare sunt private. În caz contrar exista<br />

po<strong>si</strong>bilitatea blocarii sau <strong>de</strong>blocarii acestor variabile din exteriorul obiectului, <strong>si</strong> <strong>de</strong>ci<br />

influentarea interactiunii concurente ale operatiilor unei clase <strong>de</strong> catre activitatile<br />

apelatoare.<br />

37


Deoarece cozile <strong>de</strong> asteptare pot fi blocate sau <strong>de</strong>blocate pe baza unor conditii<br />

este evi<strong>de</strong>nt faptul ca se poate mo<strong>de</strong>la o interactiune <strong>de</strong> tip "<strong>si</strong>ncronizare<br />

conditionala". De aici rezulta faptul ca activitatile concurente care ajung <strong>în</strong> interiorul<br />

unui obiect pot fi coordonate pe baza starii <strong>în</strong> care se afla obiectul. Cozile <strong>de</strong><br />

asteptare, <strong>în</strong>sa, nu pot specifica interactiuni <strong>de</strong>pen<strong>de</strong>nte <strong>de</strong> istoricul apelurilor<br />

anterioare <strong>de</strong> operatii.<br />

În plus acest mecanism a fost gândit pe baza acelea<strong>si</strong> restrictii prezente <strong>si</strong> <strong>în</strong><br />

cazul monitorului: este permisa executia unei <strong>si</strong>ngure activitati la un moment dat <strong>în</strong><br />

interiorul unui obiect. Acest lucru usureaza, asa cum am vazut, <strong>de</strong>monstrarea<br />

corectitudinii programelor orientate-obiect concurente dar limiteaza performantele<br />

paralele ale acestora. Extin<strong>de</strong>rea acestui mecanism pentru a putea permite executia<br />

unui numar arbitrar <strong>de</strong> activitati paralele presupune practic introducerea unui nou<br />

mecanism <strong>de</strong> interactiune concurenta (care sa nu permita blocari <strong>si</strong>/sau <strong>de</strong>blocari<br />

concurente a unei cozi <strong>de</strong> asteptare), lucru care va <strong>de</strong>termina o crestere a complexitatii<br />

programelor <strong>si</strong> a meto<strong>de</strong>lor <strong>de</strong> <strong>de</strong>monstrare a corectitudinii acestora. Mai mult,<br />

mecanismul va fi mai <strong>de</strong>graba unul orientat pe activitati <strong>de</strong>cât bazat pe <strong>în</strong>capsulare,<br />

mostenind astfel toate <strong>de</strong>zavantajele amintite la aceasta categorie <strong>de</strong> mecanisme.<br />

Daca mai adaugam <strong>si</strong> faptul ca liniile <strong>de</strong> cod corespunzatoare coordonarii<br />

interactiunilor concurente nu respecta principiul izolarii <strong>si</strong> nici cel al separarii putem<br />

trage concluzia ca acest mecanism, <strong>de</strong><strong>si</strong> la prima ve<strong>de</strong>re elegant <strong>si</strong> expre<strong>si</strong>v<br />

favorizeaza distrugerea <strong>în</strong>capsularii.<br />

Inclu<strong>de</strong>re/exclu<strong>de</strong>re <strong>de</strong> operatii. Limbajele <strong>de</strong> programare orientate-obiect<br />

concurente care contin acest tip <strong>de</strong> mecanism permit programatorului sa includa sau<br />

sa excluda operatii din operatiile publice ale obiectelor (<strong>si</strong> care constituie interfata<br />

dinamica a acestora). Astfel, apelul unei operatii care este exclusa din interfata unui<br />

obiect este blocat pâna la reintroducerea acesteia <strong>în</strong> interfata. Spre <strong>de</strong>osebire <strong>de</strong><br />

mecanismul anterior acest mecanism presupune existenta unei <strong>si</strong>ngure cozi <strong>de</strong> astfel<br />

<strong>de</strong> apeluri. Nu exista po<strong>si</strong>bilitatea combinarii mai multor operatii care au constrângeri<br />

<strong>de</strong> interactiune <strong>si</strong>milare <strong>în</strong>tr-o unica coada, iar exclu<strong>de</strong>rea sau inclu<strong>de</strong>rea fiecarei<br />

operatii <strong>în</strong> coada trebuie sa fie facuta individual (din nou, <strong>în</strong> contrast cu coada <strong>de</strong><br />

asteptare).<br />

38


Pentru exemplul studiat pâna acum, <strong>si</strong> anume <strong>implementare</strong>a unei clase pentru<br />

o coada cu numar limitat <strong>de</strong> elemente, este evi<strong>de</strong>nt faptul ca operatia Extrage() nu se<br />

afla <strong>în</strong> interfata <strong>în</strong> momentul creerii unei instante a clasei Coada (<strong>de</strong>oarece initial<br />

coada este goala). Am presupus <strong>în</strong> acest exemplu faptul ca initial toate operatiile<br />

publice ale clasei sunt incluse <strong>în</strong> interfata <strong>si</strong> ca inclu<strong>de</strong>rea, respectiv exclu<strong>de</strong>rea<br />

operatiilor din interfata se realizeaza prin intermediul a doua functii globale,<br />

INCLUDE(), respectiv EXCLUDE() ale caror parametrii sunt nume <strong>de</strong> operatii. O<br />

restrictie care trebuie sa fie impusa acestui mecanism este interzicerea ca <strong>de</strong>structorul<br />

<strong>si</strong> constructorii sa fie exclu<strong>si</strong> din interfata.<br />

class Coada{<br />

//<strong>de</strong>claratia clasei Coada este i<strong>de</strong>ntica cu<br />

//cea din cazul secvential<br />

protected:<br />

. . .<br />

public:<br />

. . .<br />

}<br />

Coada::Coada(){<br />

//pentru <strong>si</strong>mplitate nu am <strong>de</strong>finit constructor explicit<br />

maxElem=100;<br />

listaElemente=new [maxElem] Element;<br />

elemIntroduse=elemExtrase=0;<br />

EXCLUDE(Extrage);<br />

}<br />

void Coada::Adauga(Element elem){<br />

elemIntroduse++;<br />

listaElemente[elemIntroduse % maxElem - 1]=elem<br />

if(elemIntroduse - elemExtrase == maxElem)<br />

EXCLUDE(Adauga);<br />

INCLUDE(Extrage);<br />

}<br />

Element Coada::Extrage(){<br />

elemExtrase++;<br />

Element elem=listaElemente[elemExtrase % maxElem - 1];<br />

if(elemIntroduse - elemExtrase == 0)<br />

EXCLUDE(Extrage);<br />

INCLUDE(Adauga);<br />

return elem;<br />

}<br />

De<strong>si</strong> dintr-un anumit punct <strong>de</strong> ve<strong>de</strong>re codul <strong>de</strong> interactiune pare a fi separat <strong>de</strong><br />

codul care <strong>de</strong>scrie functionalitatea, totu<strong>si</strong> functiile INCLUDE() <strong>si</strong> EXCLUDE() sunt<br />

apelate din interiorul operatiilor. Prin urmare nu sunt respectate principiile izolarii <strong>si</strong><br />

ale separarii codului <strong>de</strong> interactiune, fapt care poate <strong>de</strong>termina aparitia unor anomalii<br />

(rescrieri complete ale unor operatii, etc.) <strong>în</strong> cazul reutilizarii clasei.<br />

Este evi<strong>de</strong>nt ca se respecta principiul <strong>de</strong>pen<strong>de</strong>ntei codului <strong>de</strong> interactiune <strong>de</strong><br />

obiectul apelat <strong>si</strong> ca poate fi realizata o interactiune concurenta <strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> starea<br />

obiectului. Din pacate nici acest mecanism nu permite exprimarea <strong>concurentei</strong> intra-<br />

39


obiect, fiind admisa executia a doar unei <strong>si</strong>ngure operatii a unui obiect la un moment<br />

dat. Argumentele care au <strong>de</strong>terminat nece<strong>si</strong>tatea unei astfel <strong>de</strong> restrictii sunt comune<br />

cu cele din cazul mecanismului cu coada <strong>de</strong> asteptare.<br />

Abstractizarea comportamentului. Introducerea <strong>în</strong> limbajele <strong>de</strong> programare<br />

orientate-obiect concurente a mecanismului <strong>de</strong> abstractizare a comportamentului<br />

ofera programatorilor po<strong>si</strong>bilitatea <strong>de</strong> a specifica mai multe interfete pentru un obiect,<br />

interfete care se pot permuta dinamic <strong>în</strong> functie <strong>de</strong> nece<strong>si</strong>tati [PAP96], [PAP97].<br />

Daca <strong>în</strong> prece<strong>de</strong>ntele doua mecanisme acest lucru se realizeaza direct, <strong>în</strong> cadrul<br />

mecanismului <strong>de</strong> abstractizare comportamentala modificarea dinamica a interfetei se<br />

face prin intermediul unui concept nou pentru un limbaj <strong>de</strong> programare, <strong>si</strong> care poarta<br />

numele <strong>de</strong> stare.<br />

Figura 2.4. Descrierea comportametului clasei Coada folo<strong>si</strong>nd formalismul hartilor <strong>de</strong> stari<br />

O astfel <strong>de</strong> abordare este foarte apropiata <strong>de</strong> tehnica mo<strong>de</strong>larii<br />

comportamentului unei clase folo<strong>si</strong>ta <strong>în</strong> meto<strong>de</strong>le <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare orientate-<br />

obiect. Astfel, <strong>în</strong>ainte <strong>de</strong> a implementa o clasa programatorul va trebui sa faca o<br />

<strong>analiza</strong> a comportamentului acesteia, sa specifice (folo<strong>si</strong>nd hartile <strong>de</strong> stari <strong>de</strong>scrise <strong>de</strong><br />

David Harel sau variante ale acesteia) starile <strong>în</strong> care se poate ga<strong>si</strong> o instanta a clasei <strong>si</strong><br />

sa <strong>de</strong>termine pentru fiecare stare <strong>în</strong> parte operatiile care pot fi apelate. Vom anticipa o<br />

astfel <strong>de</strong> <strong>analiza</strong> prin intermediul unui exemplu <strong>de</strong> mo<strong>de</strong>lare cu ajutorul hartilor <strong>de</strong><br />

stari a comportamentului clasei Coada (figura 2.4), urmând ca <strong>în</strong> cadrul capitolului 4<br />

sa tratam <strong>în</strong> <strong>de</strong>taliu acest formalism vizual. Semantica notatiilor utilizate <strong>în</strong> figura 2.4<br />

este explicata <strong>de</strong> asemenea <strong>si</strong> <strong>în</strong> Anexa B.<br />

40


Din diagrama prezentata <strong>în</strong> figura 2.4 <strong>de</strong>ducem ca un obiect al clasei Coada se<br />

poate afla <strong>în</strong>tr-una din urmatoarele stari: Gol, Plin sau Partial. Implementarea clasei<br />

Coada realizata pe baza acestei diagrame <strong>de</strong>fineste aceste trei stari <strong>în</strong> cadrul sectiunii<br />

behavior <strong>si</strong> modifica starea obiectelor folo<strong>si</strong>nd instructiunea become asupra<br />

i<strong>de</strong>ntificatorului starii tinta. Constructorii <strong>si</strong> <strong>de</strong>structorul se con<strong>si</strong><strong>de</strong>ra ca facând parte<br />

din interfata obiectului indiferent <strong>de</strong> stare.<br />

class Coada{<br />

protected:<br />

Element listaElemente[]; //tablou cu elementele cozii<br />

int maxElem; //nr. maxim <strong>de</strong> elemente din coada<br />

int elemIntroduse; //nr. elementelor introduse <strong>în</strong> coada<br />

int elemExtrase; //nr. elementelor extrase din coada<br />

public:<br />

Coada();<br />

~Coada(){ . . . };<br />

void Adauga(Element elem);<br />

Element Extrage();<br />

//<strong>de</strong>finirea starilor clasei<br />

behavior:<br />

Plin = {Extrage};<br />

Gol = {Adauga};<br />

Partial = {Extrage, Adauga};<br />

}<br />

Coada::Coada(){<br />

//pentru <strong>si</strong>mplitate nu am <strong>de</strong>finit constructor explicit<br />

maxElem=100;<br />

listaElemente=new [maxElem] Element;<br />

elemIntroduse=elemExtrase=0;<br />

become Gol;<br />

}<br />

void Coada::Adauga(Element elem){<br />

elemIntroduse++;<br />

listaElemente[elemIntroduse % maxElem - 1]=elem;<br />

if (elemIntroduse - elemExtrase == maxElem)<br />

become Plin;<br />

else<br />

become Partial;<br />

}<br />

Element Coada::Extrage(){<br />

elemExtrase++;<br />

Element elem=listaElemente[elemExtrase % maxElem - 1];<br />

if (elemIntroduse - elemExtrase == 0)<br />

become Gol;<br />

else<br />

become Partial;<br />

return elem;<br />

}<br />

Codul <strong>de</strong> coordonare a interactiunilor concurente este <strong>în</strong>tr-un anumit fel mai<br />

izolat. Totu<strong>si</strong> ramân instructiunile become care sunt executate <strong>în</strong> cadrul codului ce<br />

<strong>de</strong>scrie functionalitatea unei clase. Prin urmare nici <strong>în</strong> acest caz nu sunt respectate<br />

principiile izolarii <strong>si</strong> separarii codului <strong>de</strong> interactiune.<br />

Evi<strong>de</strong>nt mecanismele bazate pe abstractizari <strong>de</strong> comportament respecta<br />

principiul codului <strong>de</strong> interactiune orientat pe apelat. Mai mult, datorita conceptului <strong>de</strong><br />

41


stare nou introdus, aceste mecanisme permit <strong>de</strong>scrierea <strong>de</strong> interactiuni <strong>de</strong>pen<strong>de</strong>nte <strong>de</strong><br />

stare <strong>si</strong> <strong>de</strong>pen<strong>de</strong>nte <strong>de</strong> istoric.<br />

Un alt avantaj al acestei abordari este acela ca, spre <strong>de</strong>osebire <strong>de</strong> cozile <strong>de</strong><br />

asteptare sau mecanismele cu inclu<strong>de</strong>re/exclu<strong>de</strong>re <strong>de</strong> operatii un<strong>de</strong> sunt precizate la<br />

un moment dat doar operatiile care sunt introduse sau scoase din interfata la<br />

momentul respectiv, <strong>în</strong> cazul abstractizarii comportamentului se cunoaste <strong>în</strong> fiecare<br />

moment continutul acestei interfete.<br />

Mecanismul abstractizarii comportamentului este caracterizat <strong>de</strong> acela<strong>si</strong><br />

neajuns ca <strong>si</strong> cozile <strong>de</strong> asteptare sau mecanismul <strong>de</strong> inclu<strong>de</strong>/exclu<strong>de</strong>re <strong>de</strong> operatii, <strong>si</strong><br />

anume acela ca permite executia unei <strong>si</strong>ngure activitati la un moment dat <strong>în</strong> interiorul<br />

unui obiect.<br />

De asemenea, la <strong>implementare</strong>a unor <strong>de</strong>scen<strong>de</strong>nti ai unei clase <strong>în</strong> care s-au<br />

folo<strong>si</strong>t abstractizari <strong>de</strong> comportament, diagramele <strong>de</strong> stari ale acestora pot diferi <strong>de</strong>stul<br />

<strong>de</strong> mult <strong>de</strong> diagrama <strong>de</strong> stari a clasei parinte. Din acest motiv <strong>în</strong> multe cazuri este<br />

necesara rescrierea operatiilor clasei parinte, rescriere ce poate implica cunoasterea<br />

codului operatiei corespunzatoare din clasa parinte, adica distrugerea modularitatii.<br />

Mo<strong>de</strong>lul Actor. Mecanismele <strong>de</strong> specificare <strong>si</strong> coordonare a interactiunilor<br />

concurente din mo<strong>de</strong>lul Actor [AGH86] pur combina conceptul <strong>de</strong> obiect cu<br />

conceptul <strong>de</strong> interfata dinamica. Astfel, modificare interfetei unui obiect (numit<br />

actor) are ca efect transformarea acestuia intr-un nou obiect care va avea un<br />

comportament diferit. Noul actor poate fi implementat printr-o clasa diferita <strong>de</strong> cea a<br />

vechiului actor. Practic, <strong>în</strong> mo<strong>de</strong>lul Actor nu sunt specificate dinamic operatiile care<br />

sunt disponibile sau nu, ci este selectat <strong>în</strong> mod dinamic un nou comportament.<br />

În exemplul anterior folo<strong>si</strong>t pentru a prezenta mecanismele ce contin<br />

abstractizari <strong>de</strong> comportament am distins trei stari <strong>în</strong> care se poate afla la un moment<br />

dat un obiect al clasei Coada. În limbajele bazate pe mo<strong>de</strong>lul Actor fiecarei stari din<br />

cele trei îi corespun<strong>de</strong> o clasa! În timpul executiei un obiect poate apartine la un<br />

moment dat unei <strong>si</strong>ngure clase din cele trei.<br />

//clasa actor Coada_Plina<br />

actor Coada_Plina{<br />

protected:<br />

Element listaElemente[]; //tablou cu elementele cozii<br />

int maxElem; //nr. maxim <strong>de</strong> elemente din coada<br />

int elemIntroduse; //nr. elementelor introduse <strong>în</strong> coada<br />

public:<br />

42


}<br />

Coada_Plina(int mE, int eIn, Element* lista){. . .};<br />

~Coada_Plina(){ . . .};<br />

Element Extrage();<br />

Element Coada_Plina::Extrage()<br />

{<br />

. . .<br />

become Coada_Partiala(maxElem, elemIntroduse,<br />

(elemIntroduse-maxElem+1), listaElemente);<br />

. . . //returnarea unei valori<br />

}<br />

//clasa actor Coada_Partiala<br />

actor Coada_Partiala{<br />

protected:<br />

//acelea<strong>si</strong> proprietati ca in cazul cozii pline +<br />

int elemExtrase; //nr. elementelor extrase din coada<br />

public:<br />

Coada_Partiala(int mE,int eIn,int eEx,Element* lista);<br />

~Coada_Partiala(){ . . .};<br />

void Adauga(Element elem);<br />

Element Extrage();<br />

}<br />

Coada_Partiala::Coada_Partiala(int mE,int eIn,int eEx,Element* lista)<br />

{<br />

if(eIn-eEx==mE)<br />

become Coada_Plina(mE,mIn,lista);<br />

if(eIn-eEx==0)<br />

become Coada_Goala(mE,mIn,lista);<br />

//initializarea proprietatilor<br />

. . .<br />

}<br />

Element Coada_Partiala::Extrage()<br />

{<br />

. . .<br />

if(elemIntroduse-elemExtrase==0)<br />

become Coada_Goala(maxElem,elemIntroduse,listaElemente);<br />

. . . //returnarea unei valori<br />

}<br />

void Coada_Partiala::Adauga(Element elem)<br />

{<br />

. . .<br />

if(elemIntroduse-elemExtrase==maxElem)<br />

become Coada_Plina(maxElem,elemIntroduse,listaElemente);<br />

}<br />

//clasa actor Coada_Goala<br />

actor Coada_Goala{<br />

protected:<br />

//acelea<strong>si</strong> proprietati ca in cazul cozilor anterioare<br />

. . .<br />

public:<br />

Coada_Goala(int mE,int eIn, Element* lista){. . .};<br />

~Coada_Goala(){ . . .};<br />

void Adauga(Element elem);<br />

}<br />

void Adauga(Element elem)<br />

{<br />

become Coada_Partiala(maxElem, elemIntroduse,<br />

(elemIntroduse+1), listaElemente);<br />

}<br />

Pentru ca <strong>implementare</strong>a bazata pe mo<strong>de</strong>lul Actor sa fie functionala am<br />

adaugat fiecareia dintre cele trei clase câte un constructor explicit care este necesar <strong>în</strong><br />

43


momentul <strong>în</strong> care obiectul trece dintr-o clasa <strong>în</strong> alta. De asemenea, constructor<br />

implicit este <strong>de</strong>finit doar pentru clasa Coada_Goala pentru <strong>si</strong>mplitate. Se poate<br />

observa din aceasta <strong>implementare</strong> ca pentru clasa Coada_Plina nu este <strong>de</strong>finita<br />

operatia Adauga(), respectiv pentru clasa Coada_Goala operatia Extrage(). Pentru a<br />

realiza schimbarea clasei pentru un actor am folo<strong>si</strong>t, ca <strong>si</strong> <strong>în</strong> cazul mecanismului <strong>de</strong><br />

interactiune concurenta prin abstractizarea comportamentului, intructiunea become.<br />

Privite <strong>în</strong> context orientat-obiect mecanismele bazate pe mo<strong>de</strong>lul Actor au<br />

doua mari neajunsuri. În primul rând mostenirea este dificil <strong>de</strong> implementat, <strong>de</strong>oarece<br />

<strong>în</strong> momentul <strong>în</strong> care se doreste <strong>de</strong>finirea unei subclase cu un comportament<br />

specializat, este necesara re<strong>de</strong>finirea fiecarui actor ce corespun<strong>de</strong> unei stari <strong>în</strong> parte.<br />

Mai mult, <strong>în</strong> timpul executiei un actor se poate transforma <strong>în</strong>tr-un altul cu un<br />

comportament total diferit. Aceste neajunsuri au <strong>de</strong>terminat ca majoritatea limbajelor<br />

<strong>de</strong> programare bazate pe actori sa nu implementeze conceptul <strong>de</strong> mostenire.<br />

În al doilea rând, asa cum se poate observa <strong>si</strong> din exemplul cu <strong>implementare</strong>a<br />

unei cozi limitate, nu este clar ce se <strong>în</strong>tâmpla <strong>în</strong> momentul <strong>în</strong> care un actor se afla <strong>în</strong><br />

starea Coada_Plina <strong>si</strong> receptioneaza mesaj Adauga(). În general nu se ofera nici o<br />

indicatie <strong>în</strong> ceea ce priveste faptul ca <strong>în</strong>tr-o alta stare actorul respectiv ar putea<br />

raspun<strong>de</strong> acestui mesaj. Prin urmare majoritatea limbajelor cu actori nu realizeaza<br />

introducerea mesajelor <strong>în</strong>tr-o coada <strong>de</strong> asteptare.<br />

Si pentru acest mecanism principiul orientarii pe obiectul apelat al codului <strong>de</strong><br />

interactiune este respectat, iar principiile izolarii <strong>si</strong> separarii acestui cod nu. De<br />

asemenea, mo<strong>de</strong>lul Actor este un mo<strong>de</strong>l bazat pe principiul "o <strong>si</strong>ngura activitate<br />

executata la un moment dat". Totu<strong>si</strong> o concurenta intra-obiect mai restrânsa poate fi<br />

mo<strong>de</strong>lata folo<strong>si</strong>nd post-procesarea discutata <strong>în</strong> sectiunea 2.3. Astfel, imediat dupa<br />

executarea unei instructiuni become poate fi acceptat apelul unei alte operatii, <strong>în</strong> timp<br />

ce operatia curenta î<strong>si</strong> continua executia. Din pacate, pentru a fi pastrata con<strong>si</strong>stenta<br />

starii actorului, operatia care eventual se va executa <strong>în</strong> paralel cu cea curenta trebuie<br />

sa fie o operatie ce nu modifica <strong>în</strong> nici un mod starea obiectului (<strong>în</strong> acest context prin<br />

starea obiectului am <strong>în</strong>teles un tuplu <strong>de</strong> valori corespunzatoare tuturor proprietatilor<br />

actorului, asa cum a fost ea <strong>de</strong>finita <strong>în</strong> sectiunea 2.2, <strong>si</strong> nu starea abstracta <strong>de</strong>finita mai<br />

<strong>de</strong>vreme <strong>în</strong> cadrul mecanismului <strong>de</strong> abstractizare a comportamentului).<br />

44


Meto<strong>de</strong> cu garzi. Meto<strong>de</strong>le cu garzi reprezinta o modalitate <strong>de</strong> coordonare a<br />

interactiunilor concurente bazata pe mo<strong>de</strong>lul preconditiilor [MEY93]. Astfel, o<br />

operatie a unei clase poate avea atasata o conditie care este evaluata <strong>în</strong>ainte ca<br />

operatia sa fie executata. Daca respectiva conditie nu este <strong>în</strong><strong>de</strong>plinita, apelul operatie<br />

este <strong>în</strong>târziat, intrând <strong>în</strong>tr-o coada <strong>de</strong> asteptare.<br />

class Coada{<br />

protected:<br />

Element listaElemente[]; //tablou cu elementele cozii<br />

int maxElem; //nr. maxim <strong>de</strong> elemente din coada<br />

int elemIntroduse; //nr. elementelor introduse <strong>în</strong> coada<br />

int elemExtrase; //nr. elementelor extrase din coada<br />

public:<br />

Coada();<br />

~Coada();<br />

void (elemIntroduse-elemExtrase!=maxElem) Adauga(Element elem);<br />

Element (elemIntroduse-elemExtrase!=0) Extrage();<br />

}<br />

Mecanismul <strong>de</strong> meto<strong>de</strong> cu garzi are la rândul sau la baza principiul executiei<br />

exclu<strong>si</strong>ve a operatiilor. Prin urmare o <strong>si</strong>ngura operatie a unui obiect va fi executata la<br />

un moment dat. Exista <strong>în</strong>sa limbaje <strong>de</strong> programare care ofera po<strong>si</strong>bilitatea mo<strong>de</strong>larii<br />

<strong>concurentei</strong> intra-obiect folo<strong>si</strong>nd acest mecanism prin introducerea <strong>în</strong> cadrul unei<br />

conditii a asa-numitelor constrângeri <strong>de</strong> concurenta, care sunt folo<strong>si</strong>te pentru a filtra<br />

operatiile ce pot fi executate concurent cu operatia curenta. Au fost implementate<br />

pâna <strong>în</strong> prezent doua concepte care ofera po<strong>si</strong>bilitatea realizarii acestei filtrari, <strong>si</strong><br />

anume contoarele <strong>si</strong> listele <strong>de</strong> operatii compatibile.<br />

Contoarele reprezinta functii pre<strong>de</strong>finite care pot fi utilizate <strong>în</strong> interiorul<br />

conditiilor atasate unor operatii. Aceste contoare pot <strong>de</strong>termina numarul <strong>de</strong> operatii<br />

active la un moment dat (pentru toate operatiile sau doar pentru o operatie<br />

particulara), numarul <strong>de</strong> invocari sau numarul <strong>de</strong> executii complete ale unor operatii.<br />

Bine<strong>în</strong>teles toate aceste contoare sunt actualizate automat <strong>de</strong> catre <strong>si</strong>stem.<br />

Unele limbaje <strong>de</strong> programare, printre care <strong>si</strong> limbajul CEiffel [LÖH93], permit<br />

specificarea <strong>în</strong> interiorul conditiilor <strong>de</strong> interactiune a numelor <strong>de</strong> operatii din clasa<br />

respectiva care pot fi executate concurent cu operatiile atasate lor. O lista <strong>de</strong> astfel <strong>de</strong><br />

nume <strong>de</strong> operatii poarta numele <strong>de</strong> lista <strong>de</strong> operatii compatibile.<br />

De<strong>si</strong> la prima ve<strong>de</strong>re codul <strong>de</strong> interactiune concurenta este izolat, el este<br />

influentat <strong>de</strong> modificarile proprietatilor obiectelor, modificari ce se realizeaza <strong>în</strong><br />

cadrul codului <strong>de</strong> <strong>de</strong>scriere a functionalitatii. Exista limbaje <strong>de</strong> programare (<strong>de</strong><br />

exemplu SOS [MCH94]) <strong>în</strong> care se permite specificarea a doua tipuri <strong>de</strong> proprietati<br />

45


pentru o clasa. Conditiile care joaca rol <strong>de</strong> garzi <strong>de</strong> meto<strong>de</strong> pot face apel doar la un<br />

tip <strong>de</strong> proprietati, ceea ce conduce la izolarea codului <strong>de</strong> coordonare concurenta <strong>în</strong><br />

a<strong>de</strong>varatul sens al cuvântului.<br />

Un mare avantaj al meto<strong>de</strong>lor cu garzi consta <strong>în</strong> faptul ca operatiile <strong>si</strong><br />

conditiile lor pot fi mostenite sau rescrise separat (este respectat principiul separarii).<br />

Totu<strong>si</strong>, <strong>si</strong> acest mecanism genereaza un anumit tip <strong>de</strong> anomalii <strong>de</strong> mostenire <strong>de</strong>oarece<br />

<strong>în</strong> anumite cazuri, trebuie ca la rescrierea unei conditii sa se cunoasca <strong>implementare</strong>a<br />

acesteia <strong>în</strong> clasa parinte, lucru care <strong>de</strong>termina distrugerea modularitatii ierarhiei <strong>de</strong><br />

clase.<br />

În varianta originala meto<strong>de</strong>le cu garzi nu pot exprima interactiuni concurente<br />

<strong>de</strong>pen<strong>de</strong>nte <strong>de</strong> istoricul apelurilor <strong>de</strong> operatii. Exista <strong>în</strong>sa exten<strong>si</strong>i care permit<br />

introducerea <strong>în</strong> garzile operatiilor a unor expre<strong>si</strong>i <strong>de</strong> logica temporala [FER95].<br />

Meto<strong>de</strong>le cu garzi reprezinta unul dintre mecanismele cele mai populare <strong>si</strong><br />

elegante folo<strong>si</strong>te la <strong>implementare</strong>a interactiunilor activitatilor concurente. De<br />

asemenea, luând <strong>în</strong> con<strong>si</strong><strong>de</strong>rare <strong>si</strong> exten<strong>si</strong>ile amintite mai sus, acest mecanism<br />

respecta toate principiile enuntate la <strong>în</strong>ceputul acestei sectiuni.<br />

Multimi <strong>de</strong> acceptare. Una dintre problemele care apar <strong>în</strong> cadrul<br />

mecanismului <strong>de</strong> abstractizare a comportamentului este aceea ca <strong>de</strong>terminarea<br />

urmatoarei stari este po<strong>si</strong>bil sa se realizeze <strong>în</strong> urma unei analize <strong>de</strong>stul <strong>de</strong> complexe.<br />

Acest fapt poate implica nece<strong>si</strong>tatea rescrierii nejustificate a unor operatii <strong>în</strong> cadrul<br />

claselor <strong>de</strong>rivate.<br />

În aceste mecanisme multimile <strong>de</strong> acceptare ([TOM89]) sunt con<strong>si</strong><strong>de</strong>rate ca<br />

fiind concepte <strong>de</strong> prima-clasa, adica ele pot fi transmise ca parametru <strong>de</strong> operatie sau<br />

pot fi returnate ca <strong>si</strong> rezultat al unor functii. Astfel, instructiunea become poate fi<br />

utilizata <strong>în</strong> acest caz alaturi <strong>de</strong> un nume <strong>de</strong> operatie care returneaza o multime <strong>de</strong><br />

acceptare. Analiza complexa este efectuata <strong>în</strong> cadrul unei astfel <strong>de</strong> operatii. Pentru<br />

clasele <strong>de</strong>rivate modificarea comportamentului are ca efect doar modificarea acestor<br />

operatii.<br />

Implementarea clasei Coada folo<strong>si</strong>nd multimi <strong>de</strong> acceptare va fi realizata pe<br />

baza starilor <strong>de</strong>terminate la exemplul <strong>de</strong> folo<strong>si</strong>re a abstractizarii comportamentului.<br />

class Coada{<br />

protected:<br />

Element listaElemente[]; //tablou cu elementele cozii<br />

46


int maxElem; //nr. maxim <strong>de</strong> elemente din coada<br />

int elemIntroduse; //nr. elementelor introduse <strong>în</strong> coada<br />

int elemExtrase; //nr. elementelor extrase din coada<br />

public:<br />

Coada();<br />

~Coada(){ . . .};<br />

void Adauga(Element elem);<br />

Element Extrage();<br />

protected:<br />

MultimeDeAcceptare Gol();<br />

MultimeDeAcceptare Partial();<br />

MultimeDeAcceptare Plin();<br />

}<br />

Coada::Coada(){<br />

//initializari<br />

. . .<br />

become Gol();<br />

}<br />

void Coada::Adauga(Element elem){<br />

. . .<br />

if(elemIntroduse - elemExtrase == maxElem)<br />

become Plin();<br />

else<br />

become Partial();<br />

}<br />

Element Coada::Extrage(){<br />

. . .<br />

if(elemIntroduse - elemExtrase == 0)<br />

become Gol();<br />

else<br />

become Partial();<br />

. . .<br />

}<br />

MultimeDeAcceptare Coada::Gol(){<br />

return MultimeDeAcceptare(Adauga);<br />

}<br />

MultimeDeAcceptare Coada::Partial(){<br />

return MultimeDeAcceptare(Adauga, Extrage);<br />

}<br />

MultimeDeAcceptare Coada::Plin(){<br />

return MultimeDeAcceptare(Extrage);<br />

}<br />

Operatiile Plin(), Gol() <strong>si</strong> Partial(), numite operatii <strong>de</strong> <strong>de</strong>terminare a starii,<br />

returneaza obiecte <strong>de</strong> tip MultimeDeAcceptare. Analiza privind operatiile care vor fi<br />

acceptate <strong>în</strong> interfata dinamica a obiectelor este stabila <strong>în</strong> cadrul acestor operatii.<br />

Apelul acestor operatii se realizeaza <strong>în</strong> cadrul instructiunilor become pentru<br />

<strong>de</strong>terminarea starii urmatoare.<br />

Multimile <strong>de</strong> acceptare pot fi con<strong>si</strong><strong>de</strong>rate ca <strong>si</strong> perfectionari ale mecanismelor<br />

<strong>de</strong> abstractizare a comportamentului. Ele respecta acelea<strong>si</strong> principii (cod <strong>de</strong><br />

interactiune orientat pe obiectul apelat <strong>si</strong> mo<strong>de</strong>larea <strong>de</strong> interactiuni concurente<br />

<strong>de</strong>pen<strong>de</strong>nte <strong>de</strong> stare <strong>si</strong> <strong>de</strong> istoric). În plus multimile <strong>de</strong> acceptare respecta <strong>si</strong> principiul<br />

separarii codului <strong>de</strong> interactiune <strong>si</strong>, <strong>în</strong>tr-o anumita masura, principiul izolarii acestui<br />

cod (codul nu este complet izolat <strong>de</strong>oarece operatiile <strong>de</strong> <strong>de</strong>terminare a starii folosesc<br />

proprietati care pot fi modificate <strong>în</strong> oricare alta operatie).<br />

47


La fel ca abstractizarea comportamentala, multimile <strong>de</strong> acceptare nu pot<br />

exprima concurenta intra-obiect din acelea<strong>si</strong> motive care au fost amintite <strong>si</strong> la alte<br />

mecanisme (cozi <strong>de</strong> asteptare, inclu<strong>de</strong>re/exclu<strong>de</strong>re <strong>de</strong> operatii).<br />

Un caz particular al multimilor <strong>de</strong> acceptare este obtinut prin eliminarea din<br />

cod a instructiunilor become. Astfel, <strong>în</strong> momentul terminarii executiei unei operatii a<br />

unui obiect este apelata automat o operatie speciala care <strong>de</strong>termina urmatoarea<br />

multime <strong>de</strong> operatii care fac parte din interfata obiectului. Aceasta exten<strong>si</strong>e are rolul<br />

<strong>de</strong> a micsora, <strong>în</strong> anumite <strong>si</strong>tuatii, codul care trebuie rescris <strong>în</strong> cazul specializarii unei<br />

clase.<br />

Expre<strong>si</strong>i <strong>de</strong> cale. Mecanismul expre<strong>si</strong>ilor <strong>de</strong> cale permite specificarea grupata<br />

a tuturor <strong>de</strong>pen<strong>de</strong>ntelor <strong>în</strong>tre operatiile potential concurente. Printr-o constructie <strong>de</strong><br />

forma:<br />

path {lista_<strong>de</strong>_cale}<br />

programatorul poate specifica operatiile care pot fi executate concurent <strong>si</strong> ordinea <strong>în</strong><br />

care acestea pot fi executate. Lista unei expre<strong>si</strong>i <strong>de</strong> cale este formata dintr-o expre<strong>si</strong>e<br />

regulara ce contine mai multe nume <strong>de</strong> operatii alaturi <strong>de</strong> <strong>si</strong>mboluri speciale care<br />

exprima alegerea (|), repetitia ({}), concurenta (; <strong>si</strong> *) etc. Nu este necesara<br />

introducerea <strong>de</strong> cod explicit pentru coordonarea interactiunilor <strong>în</strong>tre activitati<br />

concurente <strong>în</strong> <strong>implementare</strong>a clasei.<br />

De<strong>si</strong> expre<strong>si</strong>ile <strong>de</strong> cale reprezinta o metoda eleganta <strong>de</strong> coordonare a<br />

constrângerilor <strong>de</strong> concurenta <strong>în</strong> interiorul unei clase, ele nu pot specifica <strong>si</strong>ncronizari<br />

conditionale. De asemenea, nu se specifica carei invocare <strong>de</strong> operatie i se va da curs<br />

<strong>în</strong> cazul <strong>în</strong> care asteapta <strong>în</strong> coada mai multe apeluri ale acelea<strong>si</strong> operatii.<br />

Implementarea unei cozi marginite cu expre<strong>si</strong>i <strong>de</strong> cale este triviala <strong>si</strong><br />

ineficienta. Pentru acest exemplu este necesar un mecanism suplimentar <strong>de</strong><br />

specificare a <strong>si</strong>ncronizarii conditionale, fapt care ar <strong>de</strong>termina o micsorare a<br />

numarului <strong>de</strong> avantaje (printre care <strong>si</strong> eleganta) ce caracterizeaza expre<strong>si</strong>ile <strong>de</strong> cale.<br />

Sunt evi<strong>de</strong>nt respectate principiile orientarii pe obiectul apelat <strong>si</strong> al izolarii<br />

codului <strong>de</strong> interactiune concurenta. Din punct <strong>de</strong> ve<strong>de</strong>re al expre<strong>si</strong>bilitatii, expre<strong>si</strong>ile<br />

<strong>de</strong> cale pot specifica concurenta intra-obiect (prin intermediul operatorilor ; <strong>si</strong> *), dar<br />

nu permit coordonarea interactiunilor concurente <strong>de</strong>pen<strong>de</strong>nte <strong>de</strong> stare <strong>si</strong> <strong>de</strong> istoric. Cu<br />

toate acestea exista limbaje <strong>de</strong> programare care suporta expre<strong>si</strong>i <strong>de</strong> cale dar care<br />

48


estrâng numarul <strong>de</strong> activitatii executate la un moment dat <strong>în</strong>tr-un obiect la una<br />

<strong>si</strong>ngura.<br />

Spre <strong>de</strong>osebire <strong>de</strong> majoritatea mecanismelor <strong>de</strong> specificare a interactiunilor<br />

concurente care respecta principiul izolarii, expre<strong>si</strong>ile <strong>de</strong> cale nu a<strong>si</strong>gura<br />

separareacodului <strong>de</strong> interactiune. Astfel, o expre<strong>si</strong>e <strong>de</strong> cale implementata <strong>în</strong>tr-o clasa<br />

parinte va fi sau mostenita sau rescrisa complet <strong>în</strong> clasele fiu, fapt ce conduce<br />

bine<strong>în</strong>teles la distrugerea modularitatii ierarhiilor <strong>de</strong> clase.<br />

Rutina <strong>de</strong> vitalizare (mecanisme cu control centralizat al interfetei).<br />

Limbajele <strong>de</strong> programare care implementeaza rutinele <strong>de</strong> vitalizare ca <strong>si</strong> mecanisme<br />

<strong>de</strong> specificare a <strong>concurentei</strong> furnizeaza anumite constructii specifice <strong>de</strong> coordonare a<br />

<strong>concurentei</strong> ([CAR90], [AME87]). În aceste constructii un mesaj receptionat <strong>de</strong> catre<br />

un obiect nu este interpretat automat <strong>de</strong> catre <strong>si</strong>stem ca <strong>si</strong> un apel <strong>de</strong> operatie. Acest<br />

mesaj este <strong>analiza</strong>t <strong>în</strong> cadrul rutinei <strong>de</strong> vitalizare urmând ca, <strong>în</strong> functie <strong>de</strong> starea<br />

obiectului, sa fie apelate operatiile corespunzatoare. Declararea claselor va contine o<br />

sectiune speciala, numita interface, un<strong>de</strong> sunt <strong>de</strong>scrise toate mesajele care pot fi<br />

receptionate <strong>de</strong> catre obiectele acestora.<br />

În general rutinele <strong>de</strong> vitalizare proceseaza un <strong>si</strong>ngur mesaj la un moment dat,<br />

fapt care <strong>de</strong>termina serializarea stricta a comportamentului obiectelor. Asa cum s-a<br />

aratat <strong>si</strong> <strong>în</strong> sectiunea prece<strong>de</strong>nta, pentru a se putea executa mai multe activitati<br />

concurente prin intermediul rutinelor <strong>de</strong> vitalizare este necesara prezenta unui<br />

mecanism suplimentar <strong>de</strong> initiere a <strong>concurentei</strong>. În cazul <strong>în</strong> care acest mecanism<br />

suplimentar este unul <strong>de</strong> tip fork-join atunci rutina <strong>de</strong> vitalizare poate utiliza comanda<br />

fork pentru a lansa concurent mai multe apeluri <strong>de</strong> operatii. De asemenea, rutina <strong>de</strong><br />

vitalizare poate <strong>de</strong>termina daca este executata la un moment dat o operatie<br />

incompatibila cu mesajul curent receptionat.<br />

În limbajele <strong>de</strong> programare orientate-obiect concurente care suporta rutine <strong>de</strong><br />

vitalizare sunt implementate instructiuni speciale pentru receptionarea <strong>si</strong> <strong>în</strong>târzierea<br />

tratarii mesajelor. O astfel <strong>de</strong> instructiune este <strong>de</strong> forma:<br />

receive {when },<br />

<strong>în</strong> care mesajul va fi tratat doar <strong>în</strong> momentul <strong>în</strong> care expre<strong>si</strong>a <br />

este a<strong>de</strong>varata. În <strong>implementare</strong>a unei cozi limitate folo<strong>si</strong>nd rutine <strong>de</strong> vitalizare am<br />

introdus o operatie noua, numita NrMaxElemente() care va returna numarul maxim <strong>de</strong><br />

49


elemente care pot exista <strong>în</strong> coada la un moment dat. Datorita faptului ca aceasta<br />

operatie nu modifica nici una din proprietatile clasei ea poate fi executata <strong>în</strong> paralel cu<br />

orice alta operatie din clasa (astfel <strong>de</strong> operatii poarta numele <strong>de</strong> observatori, ele<br />

nemodificând starea obiectului <strong>în</strong> timpul executiei). Pentru lansarea unei activitati<br />

concurente am utilizat un mecanism <strong>de</strong> tip fork-join.<br />

class Coada{<br />

interface:<br />

//sabloanele mesajelor<br />

//ce pot fi receptionate<br />

void Adauga(Element elem);<br />

Element Extrage();<br />

int NrMaxElemente();<br />

protected:<br />

Element listaElemente[]; //tablou cu elementele cozii<br />

int maxElem; //nr. maxim <strong>de</strong> elemente din coada<br />

int elemIntroduse; //nr. elementelor introduse <strong>în</strong> coada<br />

int elemExtrase; //nr. elementelor extrase din coada<br />

Coada();<br />

~Coada();<br />

//operatiile ce urmeaza corespund 1:1 sabloanelor <strong>de</strong><br />

//mesaje din interfata (acest lucru nu este necesar)<br />

//ele nu pot fi apelate direct din exterior<br />

void rAdauga(Element elem){. . .};<br />

Element rExtrage(){ . . .};<br />

int rNrMaxElemente(){ return maxElem;};<br />

//LifeBody() reprezinta o operatie (metoda) speciala care are rolul <strong>de</strong> a<br />

//receptiona mesajele transmise unui obiect<br />

void LifeBody();<br />

};<br />

void Coada::LifeBody(){<br />

loop{<br />

receive Adauga(e) when elemIntroduse-elemExtrase0;<br />

rExtrage();<br />

receive NrMaxElemente();<br />

fork rNrMaxElemente(); //lansare concurenta<br />

}<br />

}<br />

Rutinele <strong>de</strong> vitalizare respecta principiul privind <strong>implementare</strong>a codului <strong>de</strong><br />

interactiune concurenta <strong>în</strong> cadrul clasei server. De asemenea, cu ajutorul rutinelor <strong>de</strong><br />

vitalizare poate fi mo<strong>de</strong>lata concurenta intra-obiect (bine<strong>în</strong>teles cu ajutorul unui<br />

mecanism suplimentar <strong>de</strong> specificare a <strong>concurentei</strong>) <strong>si</strong> poate fi exprimata coordonarea<br />

<strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> stare a activitatilor concurente. Exprimarea interactiunilor concurente<br />

<strong>în</strong> functie <strong>de</strong> istoricul apelurilor <strong>de</strong> operatii nu este <strong>în</strong>sa realizabila.<br />

Rutinele <strong>de</strong> vitalizare respecta principiul izolarii codului <strong>de</strong> interactiune<br />

concurenta. doar <strong>în</strong> cazul respectarii unei constrângeri <strong>de</strong> programare, <strong>si</strong> anume aceea<br />

<strong>de</strong> a nu introduce <strong>în</strong> rutina <strong>de</strong> vitalizare cod pentru <strong>de</strong>scrierea functionalitatii. Prin<br />

50


urmare rutina <strong>de</strong> vitalizare trebuie folo<strong>si</strong>ta strict pentru conditionarea tratarii unor<br />

mesaje <strong>si</strong> pentru lansarea <strong>în</strong> executie paralela a operatiilor corespunzatoare mesajelor.<br />

În plus, la fel ca <strong>si</strong> <strong>în</strong> cazul expre<strong>si</strong>ilor <strong>de</strong> cale, rutina <strong>de</strong> vitalizare nu poate fi<br />

refolo<strong>si</strong>ta <strong>în</strong> clasele fiu: ea este sau mostenita integral sau rescrisa integral. Prin<br />

urmare nu este respectat nici principiul separariu codului <strong>de</strong> interactiune. Exista<br />

limbaje <strong>de</strong> programare (<strong>de</strong> exemplu Eiffel// [CAR90], [CAR93]) <strong>în</strong> care au fost<br />

implementate asa-numitele rutine <strong>de</strong> vitalizare generalizate un<strong>de</strong> este necesare<br />

initializarea unei tabele cu doua câmpuri: un câmp ce reprezinta o operatie a clasei iar<br />

cel <strong>de</strong>-al doilea o conditie <strong>de</strong> apelare a acesteia. Prin urmare programatorul nu va<br />

introduce cod efectiv <strong>în</strong> interiorul rutinei <strong>de</strong> vitalizare ci va initializa o astfel <strong>de</strong><br />

tabela. O astfel <strong>de</strong> abordare rezolva problema mostenirii rutinei <strong>de</strong> vitalizare <strong>si</strong>, <strong>în</strong><br />

plus, a<strong>si</strong>gura <strong>si</strong> izolarea codului <strong>de</strong> interactiune nemaifiind necesara respectarea unei<br />

discipline particulare <strong>de</strong> programare. Conditia necesara <strong>si</strong> suficienta pentru<br />

suportarea unei rutine generalizate <strong>de</strong> vitalizare <strong>de</strong> catre un limbaj <strong>de</strong> programare este<br />

aceea ca operatiile sa fie entitati <strong>de</strong> prima clasa ale limbajului.<br />

Operatii (ne)serializate. Anumite limbaje <strong>de</strong> programare orientate-obiect<br />

concurente (cum ar fi Java, Acore, ASK, etc. [PHI95]) folosesc un mod <strong>de</strong> etichetare<br />

a operatiilor unei clase ca neserializate. Aceste operatii pot fi executate <strong>în</strong> paralel cu<br />

oricare alta operatie a clasei. Practic operatiile neserializate sunt observatori (nu<br />

afecteaza starea obiectului pe parcursul executiei lor).<br />

Etichetarea operatiilor <strong>în</strong> maniera <strong>de</strong>scrisa poate stabili operatiile care pot fi<br />

executate <strong>în</strong> paralel. Mo<strong>de</strong>larea exclu<strong>de</strong>rilor mutuale <strong>în</strong>tre astfel <strong>de</strong> operatii poate fi<br />

realizata doar prin intermediul unui mecanism suplimentar <strong>de</strong> coordonare a<br />

<strong>concurentei</strong>.<br />

Din punct <strong>de</strong> ve<strong>de</strong>re al respectarii principiilor enuntate la <strong>în</strong>ceputul acestei<br />

sectiuni mecanismul operatiilor (ne)serializate se comporta foarte bine. Principala<br />

problema consta <strong>în</strong> capacitatea redusa <strong>de</strong> coordonare a interactiunilor concurente.<br />

Un mecanism particular bazat pe operatii (ne)serializate este mecanismul<br />

cititor/scriitor. Acest mecanism permite etichetarea operatiilor ca "cititori" (numite,<br />

asa cum am vazut, <strong>si</strong> observatori) <strong>si</strong> "scriitori" (cunoscute <strong>si</strong> sub <strong>de</strong>numirea <strong>de</strong><br />

modificatori). Operatiile cititor au rolul <strong>de</strong> a inspecta valorile proprietatilor obiectelor<br />

<strong>si</strong> <strong>de</strong> a returna o valoare corespunzatoare, iar operatiile scriitor modifica valorile<br />

51


acestor proprietati. Prin urmare executia operatiilor scriitor se va realiza <strong>în</strong>tr-o<br />

maniera exclu<strong>si</strong>va.<br />

c) Mecanisme <strong>de</strong> interactiune concurenta cu control reflectiv<br />

Mecanismele <strong>de</strong> interactiune cu control reflectiv se caracterizeaza prin<br />

<strong>de</strong>sprin<strong>de</strong>rea totala a codului <strong>de</strong> interactiune <strong>de</strong> <strong>implementare</strong>a clasei. Spre <strong>de</strong>osebire<br />

<strong>de</strong> mecanismele cu control extern un<strong>de</strong> codul <strong>de</strong> interactiune nu era <strong>de</strong>finit explicit, <strong>în</strong><br />

acest caz se pot formula constrângeri <strong>de</strong> interactiune explicit, iar acest lucru poate fi<br />

realizat <strong>în</strong> cadrul unor asa-numite meta-clase.<br />

Pentru a implementa o coada finita folo<strong>si</strong>nd acest mecanism <strong>de</strong> interactiune va<br />

trebui <strong>de</strong>finita clasa Coada asa cum este a fost ea <strong>de</strong>finita pentru cazul secvential,<br />

împreuna cu o noua clasa (MetaCoada) a carei interfata va contine doua operatii<br />

numite Entry, respectiv Exit:<br />

class Coada{<br />

protected:<br />

Element listaElemente[]; //tablou cu elementele cozii<br />

int maxElem; //nr. maxim <strong>de</strong> elemente din coada<br />

int elemIntroduse; //nr. elementelor introduse <strong>în</strong> coada<br />

int elemExtrase; //nr. elementelor extrase din coada<br />

public:<br />

Coada(){...};<br />

~Coada(){...};<br />

void Adauga(Element elem) {...};<br />

Element Extrage(){...};<br />

}<br />

class MetaCoada{<br />

public:<br />

Entry(){...};<br />

Exit(){...};<br />

}<br />

...<br />

Coada::attach(coada, meta_coada, Entry, Exit);<br />

Ultima linie <strong>de</strong> cod realizeaza practic legatura dinamica dintre obiectul coada<br />

<strong>de</strong> tip Coada <strong>si</strong> obiectul meta_coada <strong>de</strong> tip MetaCoada. În urma acestei legaturi<br />

realizate dinamic orice apel <strong>de</strong> operatie a obiectului coada va avea ca efect executarea<br />

operatiei Entry() din obiectul atasat dinamic meta_coada urmata <strong>de</strong> executia operatiei<br />

apelate <strong>si</strong>, <strong>în</strong> final, lansarea <strong>în</strong> executie a operatiei Exit() apartinând tot obiectului<br />

meta_coada.<br />

Este evi<strong>de</strong>nt faptul ca mecanismele din aceasta subcategorie respecta<br />

principiile codului <strong>de</strong> interactiune orientat pe obiectul apelat <strong>si</strong> principiul izolarii<br />

codului <strong>de</strong> interactiune. De asemenea, aceste mecanisme pot exprima concurenta<br />

52


intra-obiect <strong>si</strong> executia concurenta <strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> stare, neavând <strong>în</strong>sa instrumente<br />

specifice exprimarii executiilor concurente <strong>de</strong>pen<strong>de</strong>nte <strong>de</strong> istoric.<br />

În ceea ce priveste respectarea principiului separarii codului <strong>de</strong> interactiune,<br />

aceasta <strong>de</strong>pin<strong>de</strong> <strong>de</strong> <strong>implementare</strong>a mecanismelor <strong>în</strong> limbajul <strong>de</strong> programare. În cazul<br />

<strong>în</strong> care meta-clasa poate fi utilizata ca <strong>si</strong> o rutina <strong>de</strong> vitalizare generalizata,<br />

neimplementându-se <strong>în</strong> cadrul ei cod care sa afecteze functionalitatea clasei <strong>de</strong> care<br />

este legata dinamic atunci codul <strong>de</strong> interactiune respecta principiul amintit. În caz<br />

contrar este evi<strong>de</strong>nt ca, codul <strong>de</strong> interactiune nu este separabil, <strong>si</strong> <strong>de</strong>ci pentru a<br />

modifica constrângerile <strong>de</strong> interactiune este necesara reprogramarea completa a meta-<br />

clasei.<br />

2.5. Concluzii<br />

Eforturile din ultimele doua <strong>de</strong>cenii <strong>de</strong> unificare a conceptelor orientate-obiect<br />

cu mecanismele <strong>de</strong> initiere <strong>si</strong> coordonare a <strong>concurentei</strong> s-au concretizet <strong>în</strong>tr-un numar<br />

mare <strong>de</strong> limbaje <strong>de</strong> programare <strong>si</strong> mo<strong>de</strong>le <strong>de</strong> concurenta. Cu toate acestea nu s-a<br />

ajuns <strong>de</strong>ocamdata la <strong>de</strong>zvoltarea unui mo<strong>de</strong>l i<strong>de</strong>al, care sa îmbine <strong>în</strong> mod armonios<br />

aceste doua directii diferite ale <strong>de</strong>zvoltarii aplicatiilor. Principiile enuntate <strong>în</strong> cadrul<br />

sectiunii 2.2 <strong>de</strong>scriu un astfel <strong>de</strong> mo<strong>de</strong>l i<strong>de</strong>al, ele fiind <strong>de</strong>terminate pe baza<br />

rezultatelor teoretice <strong>si</strong> a experientei practice <strong>în</strong> fiecare dintre cele doua ramuri ale<br />

programarii.<br />

Nici unul dintre limbajele <strong>de</strong>zvoltate pâna <strong>în</strong> prezent nu respecta <strong>în</strong> totalitate<br />

aceste principii, asa cum s-a aratat <strong>în</strong> sectiunea 2.4. În tabelul 2.1. sunt prezentate<br />

toate mecanismele <strong>de</strong> interactiune concurenta luate <strong>în</strong> con<strong>si</strong><strong>de</strong>rare <strong>în</strong> aceasta sectiune,<br />

pentru fiecare precizându-se principiile care sunt sau nu respectate.<br />

Pe parcursul analizei mecanismelor <strong>de</strong> limbaj au fost semnalate <strong>în</strong> <strong>de</strong>se rânduri<br />

conflicte care apar <strong>în</strong>tre mecanismele <strong>de</strong> coordonare a <strong>concurentei</strong> <strong>si</strong> mecanismul <strong>de</strong><br />

mostenire. Aceste tipuri <strong>de</strong> conflicte, <strong>de</strong>numite <strong>în</strong> literatura anomalii <strong>de</strong> mostenire, au<br />

fost intens studiate <strong>în</strong> ultimii ani. În capitolul 3 se va realiza o <strong>analiza</strong> formala a<br />

acestor anomalii <strong>si</strong> se va <strong>de</strong>monstra faptul ca respectarea celor patru principii<br />

contribuie la ameliorarea lor.<br />

53


În multe cazuri respectarea principiilor este realizata doar <strong>în</strong> cazul <strong>în</strong> care se<br />

impune o anumita disciplina <strong>de</strong> programare, constructiile <strong>de</strong> limbaj neputând garanta<br />

acest lucru.<br />

Mecanism <strong>de</strong> interactiune Principiul<br />

Principiul Principiul Principiul<br />

concurenta<br />

expre<strong>si</strong>bilitatii orientarii pe apelat izolarii separarii<br />

<strong>si</strong>ncronizare prin terminare concurenta intra-obiect<br />

executie <strong>de</strong>p. <strong>de</strong> stare<br />

nu nu nu<br />

semafoare, mutex <strong>si</strong> lock concurenta intra-obiect nu (câteodata da) nu nu<br />

regiuni critice conditionale executie <strong>de</strong>p. <strong>de</strong> stare nu (câteodata da) nu nu<br />

<strong>si</strong>ncronizare piggy-backed executie <strong>de</strong>p. <strong>de</strong> stare nu nu nu<br />

monitor nu da da da<br />

variabile <strong>de</strong> conditie executie <strong>de</strong>p. <strong>de</strong> stare da nu nu<br />

asteptare conditionala executie <strong>de</strong>p. <strong>de</strong> stare da nu nu<br />

coada <strong>de</strong> asteptare executie <strong>de</strong>p. <strong>de</strong> stare da nu nu<br />

inclu<strong>de</strong>re/exclu<strong>de</strong>re op. executie <strong>de</strong>p. <strong>de</strong> stare da nu nu<br />

abstrac. comportamentului executie <strong>de</strong>p. <strong>de</strong> stare<br />

executie <strong>de</strong>p. <strong>de</strong> istoric<br />

concurenta intra-obiect<br />

da nu nu<br />

mo<strong>de</strong>lul Actor<br />

executie <strong>de</strong>p. <strong>de</strong> stare<br />

executie <strong>de</strong>p. <strong>de</strong> istoric<br />

conc intra-obiect (uneori)<br />

da<br />

nu<br />

nu<br />

meto<strong>de</strong> cu garzi<br />

executie <strong>de</strong>p. <strong>de</strong> stare<br />

da<br />

da (nu e<br />

da<br />

executie <strong>de</strong>p. <strong>de</strong> istoric<br />

complet izolat)<br />

multimi <strong>de</strong> acceptare executie <strong>de</strong>p. <strong>de</strong> stare<br />

da da (nu e<br />

da<br />

executie <strong>de</strong>p. <strong>de</strong> istoric<br />

complet izolat)<br />

expre<strong>si</strong>i <strong>de</strong> cale concurenta intra-obiect<br />

executie <strong>de</strong>p. <strong>de</strong> istoric<br />

da da nu<br />

rutina <strong>de</strong> vitalizare pos. conc. intra-obiect<br />

da da (nu e<br />

nu<br />

executie <strong>de</strong>p. <strong>de</strong> stare<br />

complet izolat)<br />

rutina generalizata concurenta intra-obiect<br />

executie <strong>de</strong>p. <strong>de</strong> stare<br />

da da da<br />

operatii neserializate conc. intra-ob. restrictiva da da da<br />

protocol cititor/scriitor conc. intra-ob. restrictiva da da da<br />

control reflectiv concurenta intra-obiect<br />

executie <strong>de</strong>p. <strong>de</strong> stare<br />

da da nu (po<strong>si</strong>bil da)<br />

Tabel 2.1.<br />

În alta ordine <strong>de</strong> i<strong>de</strong>i, alaturi <strong>de</strong> nerespectarea principiilor <strong>de</strong> proiectare ale<br />

limbajelor, care sunt direct legate <strong>de</strong> conceptele <strong>de</strong> baza ale programarii orientate-<br />

obiect <strong>si</strong> programarii concurente, multe dintre limbajele <strong>de</strong> programare studiate au<br />

<strong>de</strong>zavantaje majore concretizate prin dificultatea testarii <strong>si</strong> <strong>de</strong>panarii aplicatiilor <strong>si</strong><br />

slaba lizibilitate a codului sursa.<br />

Aceste <strong>de</strong>zavantaje pot fi minimizate prin utilizarea <strong>de</strong> instrumente care sa<br />

automatizeze procesul <strong>de</strong> <strong>implementare</strong>a a aplicatiilor pe baza unor mo<strong>de</strong>le ale<br />

structurii <strong>si</strong> comportamentului claselor <strong>de</strong> obiecte concurente. Aceasta i<strong>de</strong>e va fi<br />

<strong>de</strong>zvoltata pe larg <strong>în</strong> capitolele 4 <strong>si</strong> 5.<br />

54


3. Anomalii <strong>de</strong> mostenire<br />

3.1. Introducere<br />

Analiza limbajelor <strong>de</strong> programare orientate-obiect concurente realizata <strong>în</strong><br />

capitolul prece<strong>de</strong>nt releva faptul ca mecanismele <strong>de</strong> initiere a <strong>concurentei</strong>, precum <strong>si</strong><br />

mecanismele <strong>de</strong> comunicare <strong>si</strong> <strong>si</strong>ncronizare <strong>în</strong>tre activitati concurente interfereaza cu<br />

conceptele programarii orientate-obiect <strong>de</strong>terminând anumite conflicte.<br />

Problema integrarii <strong>concurentei</strong> trebuie studiata cu multa atentie. O abordare<br />

gre<strong>si</strong>ta a mecanismelor <strong>de</strong> concurenta poate conduce la <strong>proiectarea</strong> <strong>de</strong> clase care sa<br />

satisfaca doar nece<strong>si</strong>tatile unei aplicatii particulare. Prin urmare, reutilizarea claselor<br />

respective pentru <strong>de</strong>zvoltarea altor aplicatii va fi dificila, daca nu chiar impo<strong>si</strong>bila.<br />

În acest sens, procesul <strong>de</strong> integrare a mecanismelor <strong>de</strong> initiere <strong>si</strong> coordonare a<br />

<strong>concurentei</strong> cu mecanismul <strong>de</strong> mostenire s-a bucurat <strong>de</strong> un interes constant din partea<br />

cercetatorilor <strong>în</strong> ultimul <strong>de</strong>ceniu. Mostenirea este unul dintre mecanismele cheie, ea<br />

reprezentând o metodologie larg folo<strong>si</strong>ta la reutilizarea codului <strong>în</strong> programarea<br />

orienta-obiect secventiala. În literatura s-a acordat o atentie <strong>de</strong>osebita capacitatii <strong>de</strong><br />

reutilizare a obiectelor active, conflictele dintre concurenta <strong>si</strong> mostenire beneficiind<br />

<strong>de</strong> un interes aparte. Aceste conflicte sunt numite anomalii <strong>de</strong> mostenire, <strong>de</strong>numire<br />

<strong>în</strong>tâlnita pentru prima data <strong>în</strong> [MAT93].<br />

Anomaliile <strong>de</strong> mostenire au loc atunci când adaugarea unor operatii (meto<strong>de</strong>)<br />

<strong>în</strong>tr-o subclasa <strong>de</strong>termina re<strong>de</strong>finirea unor operatii (meto<strong>de</strong>) din superclasa, re<strong>de</strong>finiri<br />

care nu sunt necesare in programarea orientata-obiect secventiala. Nebeneficiind <strong>de</strong><br />

avantajul adaugarii incrementale <strong>de</strong> cod <strong>în</strong>tr-o subclasa, programatorii se confrunta cu<br />

55


problema re<strong>de</strong>finirii, uneori integrale, a codului mostenit, calitatile mostenirii <strong>si</strong><br />

<strong>în</strong>capsularii fiind astfel anulate.<br />

De<strong>si</strong> anomaliile <strong>de</strong> mostenire au beneficiat <strong>de</strong> o atentie <strong>de</strong>osebita <strong>în</strong> ultimii ani,<br />

ele sunt <strong>în</strong>ca vag <strong>de</strong>finite <strong>si</strong> <strong>de</strong>seori interpretate gre<strong>si</strong>t. Dintre cele mai importante<br />

lucrari <strong>în</strong> care au fost propuse solutii <strong>de</strong> evitare <strong>si</strong> ameliorare ale anomaliilor <strong>de</strong><br />

mostenire amintim: [QUI97], [PAP96], [LEC96], [FER95], [AKS94], [MIT94],<br />

[THO94], [MES93]. Rezultatele obtinute <strong>în</strong> aceste lucrari sunt contradictorii <strong>si</strong><br />

incomplete, <strong>de</strong>oarece ele se limiteaza la o abordare informala a anomaliilor, fiind <strong>în</strong><br />

principal <strong>analiza</strong>te pe baza exemplelor particulare introduse <strong>în</strong> [MAT93]. Prin urmare<br />

nu exista o metoda satisfacatoare <strong>de</strong> evaluare a diverselor propuneri (<strong>de</strong> limbaje,<br />

mecanisme sau mo<strong>de</strong>le obiect) existente.<br />

În cadrul urmatoarei sectiuni sunt prezentate doua dintre cele mai importante<br />

cla<strong>si</strong>ficari ale anomaliilor <strong>de</strong> mostenire, realizate <strong>în</strong> [MAT93] <strong>si</strong> [ZEN97b], care au la<br />

baza o <strong>analiza</strong> informala. Vom <strong>de</strong>monstra <strong>în</strong> finalul acestei sectiuni ca aceste<br />

cla<strong>si</strong>ficari sunt incomplete, <strong>si</strong> vom propune o alta abordare care nu va lua <strong>în</strong><br />

con<strong>si</strong><strong>de</strong>rare numai conflictele dintre concurenta <strong>si</strong> mostenire, ci <strong>si</strong> conflinctele dintre<br />

concurenta <strong>si</strong> alte trei relatii importante <strong>în</strong>tre clase, cum sunt relatiile <strong>de</strong> asociere,<br />

agregare <strong>si</strong> <strong>de</strong>legare. Aceste tipuri <strong>de</strong> conflicte au o legatura strânsa cu anomaliile <strong>de</strong><br />

mostenire, <strong>si</strong> <strong>de</strong> aceea am propus abordarea lor unitara. O astfel <strong>de</strong> abordare poate<br />

<strong>de</strong>termina o recon<strong>si</strong><strong>de</strong>rare a conflictelor <strong>de</strong> acest tip dintr-o cu totul alta perspectiva, <strong>si</strong><br />

ar putea conduce la solutii <strong>de</strong> ameliorare a efectelor acestora. De asemenea, vom<br />

propune o noua <strong>de</strong>numire pe care o con<strong>si</strong><strong>de</strong>ram mult mai potrivita pentru a <strong>de</strong>scrie<br />

aceste tipuri <strong>de</strong> conflicte, <strong>si</strong> anume aceea <strong>de</strong> anomalie <strong>de</strong> reutilizare.<br />

În cadrul sectiunii a treia am realizat o exten<strong>si</strong>e a <strong>si</strong>stemului formal utilizat <strong>în</strong><br />

[CRN98] pentru cla<strong>si</strong>ficarea mecanismelor <strong>de</strong> mostenire <strong>în</strong> programarea orientata<br />

obiect concurenta. Exten<strong>si</strong>a se refera la <strong>de</strong>scrierea anomaliilor <strong>de</strong> mostenire pentru<br />

mo<strong>de</strong>lele obiect cu concurenta interna (ca urmare a respectarii principiului<br />

expre<strong>si</strong>bilitatii <strong>concurentei</strong>). De asemenea, <strong>si</strong>stemul formal introdus <strong>în</strong> [CRN98] a<br />

permis mo<strong>de</strong>larea mecanismului <strong>de</strong> mostenire pentru limbajele <strong>de</strong> programare<br />

orientate-obiect concurente care respecta principiile izolarii <strong>si</strong> separarii codului <strong>de</strong><br />

interactiune <strong>în</strong>tre activitati concurente. Pe baza acestui mo<strong>de</strong>l am <strong>de</strong>monstrat una<br />

dintre concluziile <strong>de</strong>sprinse <strong>în</strong> cadrul analizei mecanismelor <strong>de</strong> interactiune <strong>în</strong>tre<br />

activitati concurente <strong>în</strong> cadrul capitolului doi, <strong>si</strong> anume ca respectarea celor doua<br />

56


principii conduce la ameliorarea efectelor induse <strong>de</strong> anomaliile <strong>de</strong> mostenire. Vom<br />

arata <strong>de</strong> asemenea ca acest lucru nu garanteaza <strong>si</strong> eliminarea anomaliilor.<br />

Rezultatele formalizarii vali<strong>de</strong>aza conceptul <strong>de</strong> anomalie <strong>de</strong> reutilizare propus<br />

<strong>în</strong> [SUC97a] pe baza unei analize informale. Astfel, se <strong>de</strong>monstreaza ca mostenirea<br />

nu reprezinta cauza reala a anomaliilor <strong>de</strong> mostenire, <strong>si</strong> ca probleme asemanatoare<br />

anomaliilor <strong>de</strong> mostenire apar <strong>si</strong> <strong>în</strong> alte paradigme. De asemenea, se arata ca nu<br />

exista o solutie i<strong>de</strong>ala <strong>de</strong> rezolvare a acestor tipuri <strong>de</strong> anomalii.<br />

Maniera <strong>de</strong> abordare a formalizarii anomaliilor <strong>de</strong> mostenire <strong>de</strong>monstreaza <strong>si</strong><br />

caracterul reactiv al obiectelor active (modificarea comportamentului extern-<br />

observabil al obiectelor active <strong>în</strong> functie <strong>de</strong> mesajele receptionate). Rezultatele<br />

obtinute <strong>în</strong> urma formalizarii vor sta la baza modificarilor semantice ale hartilor <strong>de</strong><br />

stari pentru mo<strong>de</strong>larea comportamentului obiectelor active care vor fi <strong>de</strong>scrise <strong>în</strong><br />

capitolul patru.<br />

3.2. Cla<strong>si</strong>ficari ale anomaliilor <strong>de</strong> mostenire<br />

Una dintre cele mai importante probleme ridicate <strong>de</strong> programarea orientata-<br />

obiect concurenta, subliniata <strong>si</strong> la <strong>în</strong>ceputul capitolului prece<strong>de</strong>nt, este aceea a<br />

<strong>si</strong>ncronizarii obiectelor concurente: atunci când un obiect concurent se afla <strong>în</strong>tr-o<br />

anumita stare, el poate accepta doar un subset din <strong>în</strong>tregul sau set <strong>de</strong> mesaje pentru a-<br />

<strong>si</strong> mentine integritatea interna. Aceasta restrictie impusa asupra interfetei obiectelor<br />

concurente poarta <strong>în</strong> literatura <strong>de</strong> specialitate numele <strong>de</strong> constrângere <strong>de</strong> <strong>si</strong>ncronizare.<br />

În majoritatea limbajelor orientate-obiect concurente responsabilitatea<br />

implementarii explicite <strong>de</strong> cod <strong>în</strong> cadrul operatiilor <strong>în</strong> scopul satisfacerii<br />

constrângerilor <strong>de</strong> <strong>si</strong>ncronizare ca<strong>de</strong> <strong>în</strong> sarcina programatorului. Pentru a putea<br />

realiza acest lucru este necesara existenta unor mecanisme sau primitive <strong>de</strong> limbaj<br />

pentru <strong>implementare</strong>a <strong>si</strong>ncronizarii <strong>si</strong> a comunicarii <strong>în</strong>tre operatiile obiectelor. Toate<br />

tipurile <strong>de</strong> primitive care au fost implementate <strong>în</strong> cele peste o suta <strong>de</strong> limbaje<br />

orientate-obiect concurente imperative existente au fost prezentate <strong>în</strong> capitolul<br />

prece<strong>de</strong>nt. Tot <strong>în</strong> capitolul prece<strong>de</strong>nt am aratat faptul ca, <strong>în</strong> anumite cazuri, codul <strong>de</strong><br />

coordonare a interactiunilor concurente nu poate fi mostenit efectiv fara a genera<br />

re<strong>de</strong>finiri netriviale <strong>de</strong> operatii. Acest conflict a fost i<strong>de</strong>ntificat <strong>si</strong> studiat <strong>în</strong> mai multe<br />

57


lucrari <strong>de</strong> specialitate, <strong>în</strong>cepând cu [MAT93], <strong>în</strong> care a fost numit anomalie <strong>de</strong><br />

mostenire.<br />

S-au i<strong>de</strong>ntificat, <strong>de</strong> asemenea, trei cazuri distincte <strong>în</strong> care utilitatea conceptului<br />

<strong>de</strong> mostenire este mult diminuata (<strong>în</strong> unele cazuri particulare chiar anulata):<br />

?? <strong>de</strong>finirea unei noi subclase K' a clasei K nece<strong>si</strong>ta re<strong>de</strong>finirea operatiilor<br />

acesteia (acela<strong>si</strong> lucru este valabil <strong>si</strong> pentru <strong>de</strong>scen<strong>de</strong>ntii clasei K');<br />

?? modificarea unei operatii m a clasei K <strong>în</strong> cadrul ierarhiei <strong>de</strong> mostenire<br />

implica modificarea, fara o motivatie functionala, a anumitor operatii atât<br />

<strong>în</strong> clasa K cât <strong>si</strong> <strong>în</strong> <strong>de</strong>scen<strong>de</strong>ntii sai;<br />

?? <strong>de</strong>finirea unei operatii noi poate forta alte operatii (inclu<strong>si</strong>v cele ce vor fi<br />

<strong>de</strong>finite <strong>în</strong> viitor <strong>în</strong> subclase) sa urmeze un protocol specific care nu era<br />

necesar <strong>în</strong> cazul <strong>în</strong> care respectiva operatie nu ar fi existat. Pastrarearea<br />

<strong>în</strong>capsularii claselor va fi, <strong>în</strong> consecinta, foarte dificila.<br />

Principalele <strong>de</strong>zavantaje induse <strong>de</strong> anomaliile <strong>de</strong> mostenire sunt violarea<br />

<strong>în</strong>capsularii <strong>si</strong> anularea <strong>în</strong>tr-o proportie ridicata a capacitatii mecanismului <strong>de</strong><br />

mostenire. În consecinta cantitatea <strong>de</strong> cod necesara pentru <strong>implementare</strong>a unei<br />

subclase este mult mai mare <strong>de</strong>cât <strong>în</strong> cazul secvential, iar modificarea operatiilor <strong>în</strong><br />

clasele parinte, <strong>în</strong> scopul maririi eficientei, nu are afect <strong>si</strong> asupra <strong>de</strong>cen<strong>de</strong>ntilor<br />

acestora, <strong>de</strong>oarece aceste operatii au fost rescrise. De asemenea, nu se pot realiza<br />

modificari locale, acestea trebuind sa fie realizate la nivelul <strong>în</strong>tregii ierarhii.<br />

O observatie importanta este aceea ca aparitia anomaliilor <strong>de</strong> mostenire<br />

<strong>de</strong>pin<strong>de</strong> <strong>de</strong> primitivele <strong>de</strong> comunicare <strong>si</strong> <strong>si</strong>ncronizare specifice limbajului. Rezulta <strong>de</strong><br />

aici ca problema anomaliilor <strong>de</strong> mostenire este generata <strong>de</strong> conflictele semantice<br />

dintre <strong>de</strong>scrierile <strong>si</strong>ncronizarii <strong>si</strong> ale mostenirii specifice unui limbaj, <strong>si</strong> nu <strong>de</strong> modul<br />

<strong>în</strong> care sunt implementate trasaturile limbajului.<br />

3.2.1. Cla<strong>si</strong>ficarea Matsuoka-Yonezawa<br />

Aceasta cla<strong>si</strong>ficare a fost realizata <strong>si</strong> prezentata <strong>în</strong> [MAT93] <strong>si</strong> ea a stat la baza<br />

<strong>de</strong>monstrarii corectitudinii multor limbaje <strong>de</strong> programare orientate obiect concurente<br />

(corectitudine privita prin prisma implementarii <strong>de</strong> mecanisme <strong>de</strong> initiere <strong>si</strong><br />

interactiune concurenta care sa împiedice aparitia anomaliilor <strong>de</strong> mostenire). Din<br />

pacate, <strong>de</strong><strong>si</strong> cla<strong>si</strong>ficarea Matsuoka-Yonezawa are meritul <strong>de</strong> a fi rodul unei analize<br />

laborioase a conflictelor dintre mostenire <strong>si</strong> concurenta, ea are anumite neajunsuri<br />

58


generate <strong>de</strong> modalitatea <strong>în</strong> care a fost abordata aceasta <strong>analiza</strong>. Studiile efectuate <strong>de</strong><br />

cei doi autori <strong>si</strong> prezentate <strong>în</strong> [MAT93] au i<strong>de</strong>ntificat trei tipuri <strong>de</strong> anomalii <strong>de</strong><br />

mostenire: <strong>de</strong> partitionare a starilor abstracte, <strong>de</strong>terminate <strong>de</strong> istoric <strong>si</strong> <strong>de</strong> modificare<br />

a starilor abstracte.<br />

Aparitia celor trei tipuri <strong>de</strong> anomalii <strong>în</strong> diverse <strong>si</strong>tuatii a fost <strong>de</strong>monstrata<br />

utilizând exemple; dar exemplele nu reprezinta o baza a<strong>de</strong>cvata pentru cla<strong>si</strong>ficare.<br />

Prin urmare, nu exista nici o garantie ca aceasta cla<strong>si</strong>ficare este corecta sau completa.<br />

În particular, o astfel <strong>de</strong> cla<strong>si</strong>ficare nu poate fi folo<strong>si</strong>ta pentru a <strong>de</strong>monstra absenta<br />

anomaliilor <strong>de</strong> mostenire <strong>în</strong> cadrul unui limbaj <strong>de</strong> programare.<br />

Pe <strong>de</strong> alta parte, exemplele studiate nu au fost prezentate <strong>în</strong>tr-un context<br />

general, ci folo<strong>si</strong>nd mecanisme particulare <strong>de</strong> specificare a interactiunilor concurente.<br />

Astfel, mecanismele utilizate au fost: receptionarea explicita <strong>de</strong> mesaje, expre<strong>si</strong>ile <strong>de</strong><br />

cale, functii <strong>de</strong> vitalizare, abstractizari <strong>de</strong> comportament, multimi <strong>de</strong> acceptare <strong>si</strong><br />

meto<strong>de</strong> cu garzi. Însa, asa cum am aratat <strong>în</strong> capitolul prece<strong>de</strong>nt, multimea<br />

mecanismelor <strong>de</strong>zvoltate pâna <strong>în</strong> prezent este mult mai voluminoasa.<br />

Exemplul utilizat pentru caracterizarea celor trei categorii <strong>de</strong> anomalii <strong>de</strong><br />

mostenire a fost cel folo<strong>si</strong>t <strong>si</strong> <strong>în</strong> cadrul sectiunii 2.2, <strong>si</strong> anume <strong>implementare</strong>a unei cozi<br />

cu numar finit <strong>de</strong> elemente (figura 2.1). Matsuoka <strong>si</strong> Yonezawa au folo<strong>si</strong>t, <strong>de</strong><br />

asemenea, conceptul <strong>de</strong> stare abstracta a unui obiect. Pentru a realiza o prezentare<br />

succinta <strong>si</strong> sugestiva a cla<strong>si</strong>ficarii celor doi vom apela din nou la mo<strong>de</strong>larea<br />

comportamentului obiectelor folo<strong>si</strong>nd harti <strong>de</strong> stari, <strong>de</strong>scrise <strong>de</strong> Harel [HAR87].<br />

Pentru o mai buna <strong>în</strong>telegere a celor trei tipuri <strong>de</strong> anomalii am recurs la o varianta<br />

<strong>si</strong>mplificata a acestor harti <strong>de</strong> stari, renuntând la specificarea <strong>de</strong> expre<strong>si</strong>i conditionale<br />

<strong>în</strong> etichetarea tranzitiilor <strong>si</strong> <strong>de</strong> invarianti la nivelul starilor, urmând ca acestea sa fie<br />

tratate <strong>în</strong> <strong>de</strong>taliu <strong>în</strong> cadrul capitolului urmator. Cele trei clase care specializeaza clasa<br />

Coada <strong>si</strong> care au fost utilizate pentru <strong>de</strong>scrierea celor trei categorii <strong>de</strong> anomalii <strong>de</strong><br />

mostenire sunt prezentate <strong>în</strong> figura 3.1. utilizând notatia UML <strong>de</strong> mo<strong>de</strong>lare statica a<br />

aplicatiilor orientate-obiect (Anexa B contone o <strong>de</strong>scriere succinta a acestei notatii).<br />

O prima categorie <strong>de</strong> anomalii <strong>de</strong> mostenire sunt cele <strong>de</strong>terminate <strong>de</strong><br />

partitionarea starilor abstracte. Astfel, sa presupunem ca se doreste specializarea<br />

clasei Coada prin adaugarea unei noi operatii, Extrage2(), care sa permita extragerea<br />

din coada a doua elemente (primele) <strong>si</strong>multan.<br />

59


Figura 3.1. Ierarhia <strong>de</strong> clase folo<strong>si</strong>ta <strong>de</strong> Matsuoka-Yonezawa<br />

pentru cla<strong>si</strong>ficarea anomaliilor <strong>de</strong> mostenire<br />

Mo<strong>de</strong>larea comportamentului unei astfel <strong>de</strong> clase, pe care am numit-o Coada2,<br />

este prezentata <strong>în</strong> figura 3.2, un<strong>de</strong> se poate observa ca starea abstracta Partial,<br />

caracteristica clasei Coada, are <strong>în</strong> acest caz doua substari, Partial2 <strong>si</strong> Unu (practic<br />

starea Partial este <strong>în</strong>locuita <strong>în</strong> mo<strong>de</strong>lul comportamental <strong>de</strong> celelalte doua stari).<br />

În exemplele din [MAT93] se arata ca adaugarea operatiei Extrage2() <strong>în</strong> clasa<br />

Coada2 folo<strong>si</strong>nd, spre exemplu, mecanismul cu multimi <strong>de</strong> acceptare implica automat<br />

re<strong>de</strong>finirea operatiilor clasei Coada, <strong>de</strong>oarece partajarea starii Partial trebuie tratata<br />

<strong>de</strong> catre toate aceste operatii. Pe <strong>de</strong> alta parte, s-a aratat ca mecanismul cu meto<strong>de</strong> cu<br />

garzi nu conduce la aparitia acestui tip <strong>de</strong> anomalie <strong>de</strong> mostenire.<br />

Figura 3.2. Descrierea comportamentului obiectelor clasei Coada2<br />

60


Figura 3.3. Descrierea comportamentului obiectelor clasei HCoada<br />

O a doua categorie semnalata <strong>în</strong> [MAT93] este aceea a anomaliilor <strong>de</strong><br />

mostenire <strong>de</strong>terminate <strong>de</strong> istoric. Exemplul studiat <strong>de</strong> autorii lucrarii este acela al<br />

unei subclase, HCoada, care contine o operatie ExtrageImediat() care poate fi<br />

executata numai daca operatia prece<strong>de</strong>nt acceptata a fost Adauga() (<strong>de</strong>ci operatia<br />

ExtrageImediat() nu va putea fi lansata <strong>în</strong> executie imediat dupa acceptarea unei<br />

operatii Extrage()sau ExtrageImediat()). Aceasta <strong>si</strong>tuatie nece<strong>si</strong>ta adaugarea unei noi<br />

proprietati (<strong>în</strong> cazul utilizarii meto<strong>de</strong>lor cu garzi) sau a unei noi stari (<strong>în</strong> cazul<br />

mecanismului <strong>de</strong> abstractizare a comportamentului sau a multimilor <strong>de</strong> acceptare).<br />

Mo<strong>de</strong>lul comportamentului prezentat <strong>în</strong> figura 3.3 este valabil pentru ambele cazuri.<br />

Pentru multimile <strong>de</strong> acceptare re<strong>de</strong>finirile sunt necesare <strong>de</strong>oarece noua stare<br />

trebuie sa fie luata <strong>în</strong> con<strong>si</strong><strong>de</strong>rare <strong>de</strong> catre toate operatiile. În cazul meto<strong>de</strong>lor cu garzi<br />

sunt necesare re<strong>de</strong>finiri con<strong>si</strong><strong>de</strong>rabile <strong>de</strong>oarece setarea corespunzatoare a valorii noii<br />

proprietati trebuie realizata <strong>în</strong> toate operatiile. Totu<strong>si</strong>, <strong>în</strong> acest ultim caz, nu este<br />

necesara cunoasterea implementarii operatiilor re<strong>de</strong>finite, <strong>de</strong>ci nu are loc o violare a<br />

modularizarii.<br />

Ultima categorie <strong>de</strong> anomalii <strong>de</strong> mostenire este cea <strong>de</strong>terminata <strong>de</strong> modificarea<br />

starilor abstracte. Exemplul dat pentru <strong>de</strong>finirea acestui tip <strong>de</strong> anomalii consta <strong>în</strong><br />

po<strong>si</strong>bilitatea blocarii extragerii <strong>si</strong> adaugarii <strong>de</strong> elemente <strong>în</strong> coada. Astfel starea unei<br />

obiect nu va <strong>de</strong>pin<strong>de</strong> doar <strong>de</strong> numarul elementelor din coada ci <strong>si</strong> <strong>de</strong> valoarea<br />

proprietatii blocat (figurile 3.1 <strong>si</strong> 3.4).<br />

61


Figura 3.4. Descrierea comportamentului obiectelor clasei BCoada<br />

Blocarea <strong>si</strong> <strong>de</strong>blocarea cozii se realizeaza prin intermediul operatiilor<br />

Blocare(), respectiv Deblocare() ale clasei nou create BCoada. Si acest caz a fost<br />

implementat folo<strong>si</strong>nd mecanismele <strong>de</strong> <strong>si</strong>ncronizare amintite. Astfel, pentru multimile<br />

<strong>de</strong> acceptare este necesara adaugarea unei noi stari, ceea ce implica aparitia<br />

anomaliilor <strong>de</strong> mostenire, dupa cum s-a vazut <strong>si</strong> la exemplul anterior. În cazul<br />

meto<strong>de</strong>lor cu garzi este necesara modificarea conditiilor din garzi pentru a fi luata <strong>în</strong><br />

con<strong>si</strong><strong>de</strong>rare noua proprietate blocat, <strong>si</strong> <strong>de</strong>ci este necesara re<strong>de</strong>finirea operatiilor<br />

Adauga() <strong>si</strong> Extrage() fara a modifica <strong>de</strong>loc functionalitatea acestora.<br />

Cla<strong>si</strong>ficarea realizata <strong>de</strong> Matsuoka <strong>si</strong> Yonezawa reprezinta o prima <strong>în</strong>cercare<br />

<strong>de</strong> <strong>de</strong>terminare <strong>si</strong>stematica a cauzelor care conduc la aparitia anomaliilor <strong>de</strong><br />

mostenire. Din pacate aceasta cla<strong>si</strong>ficare nu are un fundament teoretic, ea bazându-se<br />

strict pe testarea cazurilor <strong>în</strong> care multimea <strong>de</strong> stari abstracte a unei clase este<br />

modificata <strong>în</strong> <strong>de</strong>scen<strong>de</strong>ntii sai. Prin urmare, nu exista nici o garantie ca respectiva<br />

cla<strong>si</strong>ficare sa fie completa <strong>si</strong> corecta, realizarea ei <strong>de</strong>pinzând strict <strong>de</strong> "bunul-<strong>si</strong>mt" <strong>si</strong><br />

experienta autorilor.<br />

Mai mult, nu este surprins cazul <strong>în</strong> care se ajunge la o anomalie <strong>de</strong> mosternire<br />

fara ca multimea starilor abstracte sa fie modificata <strong>în</strong> clasa fiu. Astfel, pentru<br />

exemplul <strong>de</strong> mai sus <strong>si</strong> folo<strong>si</strong>nd anumite mecanisme <strong>de</strong> coordonare a interactiunilor<br />

concurente particulare, construirea unei subclase a clasei Coada care sa contina o<br />

operatie ce extrage ultimul element al cozii conduce la re<strong>de</strong>finirea nejustificata din<br />

puct <strong>de</strong> ve<strong>de</strong>re functional a tuturor operatiilor din superclasa (acest lucru poate fi<br />

62


<strong>de</strong>monstrat cu usurinta folo<strong>si</strong>nd, <strong>de</strong> exemplu, oricare dintre primitivele <strong>de</strong> interactiune<br />

concurenta orientate pe operatii).<br />

3.2.2. Cla<strong>si</strong>ficarea Zeng-Schach<br />

Cla<strong>si</strong>ficarea propusa <strong>de</strong> Zeng <strong>si</strong> Schach a fost realizata relativ recent, <strong>în</strong><br />

lucrarea [Zen97b]. Autorii propun aici o <strong>analiza</strong> a modului <strong>în</strong> care functioneaza<br />

mostenirea, mai precis a modului <strong>în</strong> care o subclasa poate specializa superclasa sa fara<br />

a lua <strong>în</strong> con<strong>si</strong><strong>de</strong>rare nici un mecanism <strong>de</strong> interactiune concurenta particular.<br />

Sintactic, o subclasa poate specializa clasele parinte <strong>în</strong> trei moduri distincte:<br />

prin <strong>de</strong>finirea <strong>de</strong> noi proprietati, prin <strong>de</strong>finirea <strong>de</strong> noi operatii sau prin rescrierea<br />

operatiilor mostenite.<br />

De<strong>si</strong> cele trei modalitati <strong>de</strong> specializare sunt ortogonale, adaugarea unei noi<br />

proprietati implica, <strong>în</strong> mod logic, <strong>de</strong>finirea sau re<strong>de</strong>finirea a cel putin unei operatii<br />

care sa actioneze asupra sa. De aceea Zeng <strong>si</strong> Schach con<strong>si</strong><strong>de</strong>ra ca aparitia<br />

anomaliilor <strong>de</strong> mostenire este strâns legata <strong>de</strong> ultimele doua modalitati <strong>de</strong> extin<strong>de</strong>re a<br />

unei superclase. Aceasta abordare este total diferita <strong>de</strong> cea din [MAT93], <strong>de</strong>oarece<br />

anomaliile <strong>de</strong> mostenire nu sunt privite <strong>în</strong> raport cu multimea starilor abstracte ale<br />

unui obiect ci cu operatiile nou <strong>de</strong>finite ale acestuia.<br />

Mai mult, sunt luate <strong>în</strong> con<strong>si</strong><strong>de</strong>rare <strong>si</strong>tuatiile <strong>în</strong> care sunt referite alte operatii<br />

ale unui obiect din cadrul unei operatii nou <strong>de</strong>finite. În tabelul 3.1. sunt prezentate<br />

cazurile <strong>analiza</strong>te <strong>în</strong> [ZEN97b] <strong>si</strong> care au fost con<strong>si</strong><strong>de</strong>rate ca potentiale <strong>si</strong>tuatii <strong>de</strong><br />

generare <strong>de</strong> re<strong>de</strong>finiri netriviale <strong>de</strong> operatii.<br />

Exten<strong>si</strong>i operatie rescriere referinte la oper.<br />

noua operatie super-clasei<br />

E1 nu da nu<br />

E2 nu da da<br />

E3 da nu nu<br />

E4 da nu da<br />

E5 da da nu<br />

E6 da da da<br />

Tabel 3.1. Po<strong>si</strong>bilitati <strong>de</strong> specializare a unei clase<br />

Acest fapt reprezinta unul dintre neajunsurile abordarii, <strong>de</strong>oarece s-a avut <strong>în</strong><br />

ve<strong>de</strong>re doar problema re<strong>de</strong>finirilor netriviale <strong>de</strong> operatii, ignorându-se un alt aspect<br />

caracteristic anomaliilor <strong>de</strong> mostenire, <strong>si</strong> anume acela al violarii <strong>în</strong>capsularii.<br />

63


Un alt neajuns este acela ca <strong>analiza</strong> celor sase cazuri prezentate <strong>în</strong> tabelul 3.1.<br />

ia <strong>în</strong> con<strong>si</strong><strong>de</strong>rare doar concurenta inter-obiect, con<strong>si</strong><strong>de</strong>rându-se ca avem <strong>de</strong>-a face cu<br />

obiecte care <strong>de</strong>tin doar un <strong>si</strong>ngur fir <strong>de</strong> executie activ la un moment dat. Deci nu se<br />

poate afirma ca rezultatele analizei conduc la o cla<strong>si</strong>ficare completa nici <strong>în</strong> acest caz.<br />

Rezultatul final al analizei nu este unul surprinzator, el afirmând existenta a<br />

doua categorii <strong>de</strong> anomalii. O prima categorie, numita categoria anomaliilor <strong>de</strong><br />

rescriere fortata, este <strong>de</strong>terminata <strong>de</strong> nece<strong>si</strong>tatea re<strong>de</strong>finirii uneia sau mai multor<br />

operatii <strong>în</strong>tr-o subclasa <strong>în</strong> urma <strong>de</strong>finirii unei operatii <strong>în</strong> cadrul acesteia. A doua<br />

categorie <strong>de</strong>terminata este aceea a anomaliilor <strong>de</strong> <strong>si</strong>ncronizare care se refera la<br />

impo<strong>si</strong>bilitatea apelarii unei operatii (din cadrul superclasei sau nu) din cauza<br />

constrângerilor <strong>de</strong> <strong>si</strong>ncronizare impuse asupra acesteia.<br />

Anomaliile din prima categorie corespund anomaliilor <strong>de</strong> mostenire din<br />

cla<strong>si</strong>ficarea Matsuoka-Yonezawa. Analiza realizata aici <strong>în</strong>sa nu permite <strong>de</strong>terminarea<br />

celor trei subcategorii pe care le-am mentionat <strong>în</strong> sectiunea prece<strong>de</strong>nta.<br />

Pe <strong>de</strong> alta parte, anomaliile <strong>de</strong> <strong>si</strong>ncronizare nu sunt caracteristice programarii<br />

orientate-obiect concurente. Asa cum afirma chiar autorii, aceste anomalii sunt<br />

prezente <strong>si</strong> <strong>în</strong> medii neorientate obiect, iar rezolvarea lor se reduce la rezolvarea<br />

problemei apelurilor <strong>în</strong>castrate <strong>în</strong> monitoare.<br />

Prin urmare cla<strong>si</strong>ficarea introdusa aici nu aduce nimic nou. În plus, motivele<br />

aparitiei anomaliilor nu sunt foarte clar scoase <strong>în</strong> evi<strong>de</strong>nta, acest lucru datorându-se <strong>în</strong><br />

primul rând abordarii problemei fara a lua <strong>în</strong> con<strong>si</strong><strong>de</strong>rare implementari particulare <strong>de</strong><br />

mecanisme <strong>de</strong> interactiune concurenta.<br />

3.2.3. Anomalii <strong>de</strong> reutilizare<br />

Conceptul <strong>de</strong> anomalie <strong>de</strong> mostenire a fost introdus pentru a <strong>de</strong>scrie conflictele<br />

care apar <strong>în</strong>tre concurenta <strong>si</strong> mecanismul <strong>de</strong> mostenire al programarii orientate-obiect.<br />

În timp <strong>în</strong>sa, asa cum se poate observa <strong>în</strong> diverse articole aparute pe aceasta tema <strong>în</strong><br />

ultimii ani, anomaliile <strong>de</strong> mostenire au fost con<strong>si</strong><strong>de</strong>rate ca reprezentând <strong>si</strong>ngurele<br />

conflicte provenite <strong>în</strong> urma fuzionarii <strong>în</strong>tre conceptele <strong>de</strong> concurenta <strong>si</strong> cele orientate-<br />

obiect. Acest lucru este total eronat, <strong>de</strong>oarece, asa cum vom arata <strong>în</strong> continuare,<br />

anomalii cu un comportament asemanator au loc <strong>si</strong> <strong>în</strong> cazul altor mecanisme<br />

caracteristice programarii orientate-obiect. [ZEN97b] reprezinta una dintre putinele<br />

lucrari <strong>în</strong> care se <strong>în</strong>cearca <strong>de</strong>monstrarea existentei altor anomalii <strong>în</strong>afara celor <strong>de</strong><br />

64


mostenire <strong>în</strong> cadrul programarii orientate-obiect concurente. Din pacate, asa cum am<br />

vazut, studiul realizat <strong>în</strong> aceasta lucrare conduce la concluzii nesatisfacatoare. Totu<strong>si</strong>,<br />

anomaliile <strong>de</strong> rescriere fortata care <strong>în</strong>locuiesc conceptul <strong>de</strong> anomalii <strong>de</strong> mostenire <strong>si</strong><br />

care au fost introduse <strong>în</strong> [ZEN97b] are un caracter mult mai general, chiar daca acest<br />

lucru s-a realizat doar la nivel <strong>de</strong> <strong>de</strong>numire (<strong>si</strong>ngurele tipuri <strong>de</strong> anomalii <strong>de</strong> rescriere<br />

date ca exemplu au fost cele trei amintite <strong>în</strong> [MAT93]).<br />

Între clasele care <strong>de</strong>scriu la un moment dat o anumita problema pot exista<br />

patru tipuri <strong>de</strong> relatii. Un prim tip <strong>de</strong> relatie este aceea <strong>de</strong> mostenire, care permite<br />

reutilizarea structurii <strong>si</strong> functionalitatii unei clase <strong>în</strong> <strong>de</strong>finirea altei clase.<br />

Exista limbaje <strong>de</strong> programare (ca, <strong>de</strong> exemplu, SINA) care nu au implementat<br />

un mecanism pentru <strong>de</strong>scrierea unei astfel <strong>de</strong> relatii. În aceste limbaje generalizarea<br />

sau specializarea unei clase se realizeaza prin intermediul mecanismului <strong>de</strong> <strong>de</strong>legare.<br />

Relatia <strong>de</strong> <strong>de</strong>legare dintre doua clase este tot o relatie <strong>de</strong> reutilizare <strong>si</strong> ea presupune<br />

redirectarea potentiala a mesajelor receptionate <strong>de</strong> catre un obiect spre un asa-numit<br />

obiect <strong>de</strong>legat. Obiectul <strong>de</strong>legat trebuie sa faca parte efectiv din constructia primului<br />

obiect. Relatia <strong>de</strong> <strong>de</strong>legare este o relatie mult mai puternica <strong>de</strong>cât mostenirea,<br />

<strong>de</strong>oarece ea poate <strong>si</strong>mula aceasta relatie <strong>si</strong>, <strong>în</strong> plus, poate mo<strong>de</strong>la o evolutie dinamica<br />

a <strong>si</strong>stemelor (lucru pe care mostenirea, ca relatie statica dintre clase, nu îl poate<br />

realiza).<br />

O a treia relatie po<strong>si</strong>bila <strong>în</strong>tre clasele unui <strong>si</strong>stem este relatia <strong>de</strong> agregare. Ea<br />

implica existenta unei relatii <strong>de</strong> tip parte-<strong>în</strong>treg <strong>în</strong>tre instantele claselor aflate <strong>în</strong><br />

aceasta relatie.<br />

Relatia <strong>de</strong> asociere este cea <strong>de</strong>-a patra relatie po<strong>si</strong>bila <strong>în</strong> care se pot afla doua<br />

clase ale unui <strong>si</strong>stem. Aceasta relatie mai poarta numele <strong>si</strong> <strong>de</strong> relatie <strong>de</strong> utilizare<br />

<strong>de</strong>oarece, la un moment dat, un obiect unei clase se foloseste <strong>de</strong> serviciile oferite <strong>de</strong><br />

catre un obiect al clasei asociate.<br />

Cele patru relatii <strong>de</strong>scrise mai sus reprezinta tot atâtea cai <strong>de</strong> reutilizare a<br />

claselor <strong>de</strong>finite <strong>în</strong>tr-o anumita biblioteca. În cele ce urmeaza vom arata ca, <strong>în</strong>tr-un<br />

context concurent, existenta uneia dintre aceste relatii poate <strong>de</strong>termina <strong>în</strong> anumite<br />

conditii re<strong>de</strong>finiri netriviale <strong>de</strong> operatii precum <strong>si</strong> violari grave ale <strong>în</strong>capsularii. Prin<br />

urmare, au loc efectele con<strong>si</strong><strong>de</strong>rate <strong>în</strong> [MAT93] <strong>în</strong> <strong>de</strong>scrierea anomaliilor <strong>de</strong><br />

mostenire.<br />

65


Relatiile <strong>de</strong> <strong>de</strong>legare, agregare <strong>si</strong> asociere implica, <strong>în</strong> ultima instanta, existenta<br />

unei comunicari <strong>în</strong>tre obiecte, comunicare ce se bazeaza pe accesarea sau apelarea<br />

structurii <strong>si</strong> a operatiilor publice ale unui obiect. Accesul la structura publica a unui<br />

obiect, <strong>si</strong> <strong>de</strong>ci la proprietatile publice ale acestuia poate <strong>de</strong>termina <strong>în</strong>tr-un context<br />

concurent <strong>si</strong> <strong>în</strong> lipsa unui mecanism <strong>de</strong> <strong>si</strong>ncronizare a<strong>de</strong>cvat aducerea obiectului <strong>în</strong>tr-o<br />

stare incon<strong>si</strong>stenta.<br />

Prin urmare, la nivelul operatiilor sau obiectelor care acceseaza proprietatile<br />

publice ale unui obiect aflat <strong>în</strong>tr-o relatie <strong>de</strong> agregare, asociere sau <strong>de</strong>legare vor trebui<br />

folo<strong>si</strong>te mecanisme <strong>de</strong> comunicare <strong>si</strong> <strong>si</strong>ncronizare pentru protejarea con<strong>si</strong>stentei<br />

datelor. Pentru cele mai multe dintre aceste mecanisme (dupa cum s-a <strong>de</strong>monstrat <strong>si</strong><br />

<strong>în</strong> cazul anomaliilor <strong>de</strong> mostenire) acest lucru presupune cunoasterea implementarii<br />

operatiilor (publice sau nu) din obiectul a carei structura se acceseaza. Prin urmare<br />

<strong>în</strong>capsularea claselor poate fi distrusa, iar reutilizarea claselor apartinând unei<br />

biblioteci <strong>de</strong> clase, este <strong>în</strong>greunata <strong>în</strong>ca odata. Mai mult, modificarea claselor din<br />

cadrul unei biblioteci <strong>de</strong> clase (prin modificari sau adaugari <strong>de</strong> operati) implica<br />

modificarea tuturor claselor aflate <strong>în</strong> relatie cu acestea.<br />

Este evi<strong>de</strong>nt faptul ca <strong>în</strong> cazul asocierilor <strong>si</strong> agregarilor anomaliile <strong>de</strong> acest gen<br />

pot fi eliminate prin con<strong>si</strong><strong>de</strong>rarea tuturor proprietatilor unei clase ca fiind private.<br />

Totu<strong>si</strong>, majoritatea limbajelor <strong>de</strong> programare orientate-obiect existente permit<br />

<strong>de</strong>finirea mai multor moduri <strong>de</strong> vizibilitate pentru proprietati. Mai mult, <strong>în</strong> unele<br />

limbaje (cum ar fi, <strong>de</strong> exemplu, C++) se pot <strong>de</strong>fini operatii care sa returneze referinte<br />

ale proprietatilor, ele putând fi modificate <strong>în</strong> aceea<strong>si</strong> maniera ca <strong>si</strong> proprietatile<br />

publice (<strong>si</strong> implicând acelea<strong>si</strong> anomalii).<br />

Datorita asemanarii evi<strong>de</strong>nte dintre aceste tipuri <strong>de</strong> anomalii <strong>si</strong> cel cunoscut <strong>în</strong><br />

literatura <strong>de</strong> specialitate ca anomalie <strong>de</strong> mostenire con<strong>si</strong><strong>de</strong>ram ca este mult mai<br />

naturala tratarea unitara a lor precum <strong>si</strong> ga<strong>si</strong>rea unei <strong>de</strong>numiri generale ce sa le<br />

<strong>de</strong>fineasca. Denumirea propusa <strong>de</strong> noi este aceea <strong>de</strong> anomalie <strong>de</strong> reutilizare.<br />

Vom <strong>de</strong>monstra <strong>în</strong> sectiunea urmatoare ca principiile enuntate <strong>în</strong> capitolul doi<br />

reprezinta conditii necesare pentru evitarea aparitiei anomaliilor <strong>de</strong> reutilizare <strong>si</strong><br />

pastrarea intacta a calitatilor conceptelor introduse atât <strong>de</strong> mecanismele <strong>de</strong> concurenta<br />

cât <strong>si</strong> <strong>de</strong> tehnica orientata-obiect.<br />

66


3.3. Formalizarea anomaliilor <strong>de</strong> mostenire<br />

În [CRN98] a fost propus un <strong>si</strong>stem formal <strong>de</strong> cla<strong>si</strong>ficare a mecanismelor <strong>de</strong><br />

mostenire <strong>în</strong> programarea orientata-obiect concurenta. Acest <strong>si</strong>stem formal reprezinta<br />

o varianta a semanticilor <strong>de</strong>notationale pentru mostenire introduse <strong>de</strong> Cook <strong>si</strong><br />

Palsberg <strong>în</strong> [COO89] <strong>si</strong> porneste <strong>de</strong> la mo<strong>de</strong>larea unei ierarhii <strong>de</strong> mostenire<br />

incrementale. Modul <strong>în</strong> care este mo<strong>de</strong>lata mostenirea <strong>în</strong> acest <strong>si</strong>stem formal permite<br />

tratarea oricarei abordari particulare <strong>de</strong> proiectare a unui limbaj <strong>de</strong> programare<br />

orientat-obiect concurent.<br />

În ierarhia <strong>de</strong> clase din figura 3.1. superclasa Coada este complet reutilizata <strong>de</strong><br />

subclasele sale Coada2, HCoada <strong>si</strong> BCoada, <strong>de</strong>oarece nici una dintre operatiile ei nu<br />

este re<strong>de</strong>finita <strong>în</strong> aceste subclase. Prin urmare volumul <strong>de</strong> cod reutilizat este maxim.<br />

O astfel <strong>de</strong> ierarhie <strong>de</strong> mostenire, <strong>în</strong> care nici o subclasa nu re<strong>de</strong>fineste operatii ale<br />

claselor parinte poarta numele <strong>de</strong> ierarhie <strong>de</strong> mostenire incrementala.<br />

Mostenirea induce <strong>si</strong> alta relatie <strong>în</strong>tre clase: relatia <strong>de</strong> subtipizare. Am <strong>de</strong>finit<br />

tipul ca fiind o multime <strong>de</strong> instante care au aceea<strong>si</strong> interfata (sau comportament extern<br />

observabil). Vom spune ca o clasa implementeaza un tip daca fiecare instanta a clasei<br />

apartine tipului respectiv.<br />

O clasa B <strong>de</strong>rivata dintr-o clasa A va avea <strong>în</strong> componenta sa cel putin<br />

proprietatile <strong>si</strong> operatiile clasei A. Deci, o instanta a clasei B poate fi utilizata <strong>în</strong> orice<br />

context <strong>în</strong> care poate fi utilizata o instanta a clasei A, adica interfata unei instante a<br />

clasei B va inclu<strong>de</strong> operatiile ce compun interfata oricarei instante a clasei A. Aceasta<br />

relatie <strong>de</strong> incluziune <strong>în</strong>tre interfetele a doua obiecte poarta numele <strong>de</strong> relatie <strong>de</strong><br />

subtipizare (<strong>în</strong> particular, instantele clasei B reprezinta subtipuri ale instantelor clasei<br />

A). Relatia <strong>de</strong> subtipizare este o relatie <strong>în</strong>tre comportamentele externe ale instantelor,<br />

<strong>si</strong> ea nu <strong>de</strong>pin<strong>de</strong> <strong>de</strong> structura interna a unei clase cum este cazul relatiei <strong>de</strong> mostenire.<br />

Notând cu ? un tip implementat <strong>de</strong> clasa A <strong>si</strong> cu ? un tip implementat <strong>de</strong> clasa<br />

B vom nota prin ? ? ? faptul ca tipul ? este subtip al lui ?. Prin urmare o instanta<br />

care apartine unui tip ? apartine <strong>de</strong> asemenea tipului ?, iar o clasa care implementeaza<br />

tipul ? implementeaza <strong>de</strong> asemenea <strong>si</strong> tipul ?.<br />

Definitia urmatoare <strong>si</strong> cele doua afirmatii care o preced introduc o legatura<br />

<strong>în</strong>tre relatia <strong>de</strong> subtipizare <strong>si</strong> ierarhia <strong>de</strong> mostenire incrementala.<br />

Definitie 1. Un lant <strong>de</strong> tipuri reprezinta o secventa finita <strong>de</strong> tipuri ? 1 ? ... ? ? n.<br />

67


Afirmatie 1. Orice drum dintr-o ierarhie <strong>de</strong> mostenire incrementala<br />

implementeaza un lant <strong>de</strong> subtipuri.<br />

Afirmatie 2. Fiecare lant <strong>de</strong> subtipuri poate fi implementat <strong>de</strong> o ierarhie <strong>de</strong><br />

mostenire incrementala.<br />

Conform <strong>de</strong>finitiei <strong>de</strong> tip data anterior, <strong>în</strong> care acesta este caracterizat <strong>de</strong> o<br />

multime <strong>de</strong> operatii, afirmatiile 1 <strong>si</strong> 2 au loc pentru orice ierarhie <strong>de</strong> mostenire (nu<br />

neaparat incrementala!), <strong>în</strong> care nu este permisa stergerea <strong>de</strong> operatii. În cazul<br />

programarii orientate-obiect concurente <strong>în</strong>sa, exista o multime con<strong>si</strong>stenta <strong>de</strong> limbaje<br />

sau mo<strong>de</strong>le obiect care fac ca o subclasa dintr-o ierarhie <strong>de</strong> mostenire incrementala sa<br />

fie strâns legata <strong>de</strong> superclasa acesteia printr-o relatie mai puternica <strong>de</strong> subtipizare,<br />

bazata pe acceptarea <strong>de</strong> secvente <strong>de</strong> mesaje, spre <strong>de</strong>osebire <strong>de</strong> relatia bazata pe<br />

multimi <strong>de</strong> operatii. Aceste limbaje sau mo<strong>de</strong>le obiect utilizeaza mecanisme <strong>de</strong><br />

<strong>si</strong>ncronizare orientate pe <strong>în</strong>capsulare. Problema anomaliilor <strong>de</strong> mostenire apare<br />

frecvent <strong>în</strong> cazul acestor limbaje <strong>de</strong>oarece afirmatia 2 nu este <strong>în</strong><strong>de</strong>plinita pentru<br />

aceasta notiune <strong>de</strong> tip.<br />

Obiectele active au cel putin un fir <strong>de</strong> executie propriu. Concurenta inter-<br />

obiect <strong>si</strong> intra-obiect implica nece<strong>si</strong>tatea <strong>si</strong>ncronizarii, fara <strong>de</strong> care starea unui obiect<br />

activ poate <strong>de</strong>veni incon<strong>si</strong>stenta. De aceea programarea orientata-obiect concurenta<br />

introduce notiunea <strong>de</strong> control <strong>de</strong> interfata. Majoritatea mo<strong>de</strong>lelor obiect realizeaza<br />

controlul interfetei prin intermediul unei entitati speciale, pe care le vom numi <strong>în</strong><br />

continuare gestionare <strong>de</strong> mesaje, <strong>si</strong> care se concretizeaza printr-un fir <strong>de</strong> executie<br />

distinct, un mecanism <strong>de</strong> blocare sau un obiect special. Aceste entitati <strong>de</strong>cid care sunt<br />

operatiile permise a fi lansate <strong>în</strong> executie <strong>si</strong> operatiile care trebuie sa fie suspendate<br />

astfel <strong>în</strong>cât obiectul sa se afle <strong>în</strong> orice moment <strong>în</strong>tr-o stare con<strong>si</strong>stenta. Mesajele<br />

receptionate <strong>de</strong> la alte obiecte din <strong>si</strong>stem vor fi retinute <strong>în</strong>tr-o coada <strong>de</strong> mesaje pâna<br />

când entitatea care gestioneaza controlul interfetei le permite sa avanseze. Prin<br />

urmare controlul interfetei impune constrângerile <strong>de</strong> <strong>si</strong>ncronizare.<br />

Vom utiliza notatia pentru reprezentarea unei secvente <strong>de</strong><br />

mesaje acceptate m1, ..., mn. Presupunând ca putem caracteriza un tip prin intermediul<br />

unei multimi <strong>de</strong> secvente <strong>de</strong> mesaje {u1,...,uk}, fiecare instanta apartinând acestui tip<br />

are proprietatea ca cel putin fiecare ui reprezinta o secventa valida a instantei. Daca ?<br />

? ? atunci fiecare instanta a lui ? este <strong>de</strong> asemenea un element al lui ?, <strong>si</strong> <strong>de</strong> aceea<br />

este capabil sa accepte multimea <strong>de</strong> secvente <strong>de</strong> mesaje proprie lui ?. Prin urmare,<br />

68


orice instanta din ? poate fi folo<strong>si</strong>ta <strong>în</strong> locul unei instante din ?, fara nici o modificare<br />

observabila din exterior a comportamentului rezultat.<br />

Sistemele <strong>de</strong> meto<strong>de</strong> ([COO89]) reprezinta formalizari <strong>si</strong>mple ale programarii<br />

orientate-obiect <strong>si</strong> includ <strong>de</strong>scrieri <strong>de</strong> instante, clase <strong>si</strong> operatii (meto<strong>de</strong>) (figura 3.5).<br />

Functia class returneaza clasa unei anumite instante, iar instances returneaza<br />

multimea tuturor instantelor po<strong>si</strong>bile ale unei clase.<br />

Pentru o anumita clasa, functia methods pune <strong>în</strong> corespon<strong>de</strong>nta numele unui<br />

mesaj cu corpul acestuia (codul operatiei asociate) sau cu elementul ne<strong>de</strong>finit ? (<strong>în</strong><br />

cazul <strong>în</strong> care nu exista nici o operatie <strong>de</strong>finita la nivelul clasei asociata mesajului).<br />

Functia M returneaza multimea tuturor operatiilor (meto<strong>de</strong>lor) <strong>de</strong>finite pentru o clasa<br />

anume.<br />

Multimi<br />

Instante: p, q, r ? Instance<br />

Clase: P, Q, R ? Class<br />

Signaturi <strong>de</strong> mesaje: m ? Key<br />

Expre<strong>si</strong>i <strong>de</strong> operatii: e, f ? Exp<br />

class : Instance ? Class<br />

Functii<br />

instances : Class ? ? (Instance)<br />

methods : Class ? Key ? Exp?<br />

M : Class ? ? (Key), M(P) = {m : methods(P,m) ?? }<br />

Figura 3.5. Multimile <strong>si</strong> functiile <strong>si</strong>stemului <strong>de</strong> meto<strong>de</strong> introdus <strong>în</strong> [COO89]<br />

Multimea Exp? reprezinta multimea implementarilor <strong>de</strong> operatii reunita cu<br />

elementul ne<strong>de</strong>finit ? . Înainte <strong>de</strong> a formaliza mecanismul <strong>de</strong> mostenire pe baza<br />

acestui <strong>si</strong>stem <strong>de</strong> meto<strong>de</strong>, vom <strong>de</strong>finit <strong>în</strong> cele ce urmeaza o relatie binara peste<br />

multimea Exp?.<br />

Definitie 2. Fie e, f ? Exp? doua expre<strong>si</strong>i. Spunem ca e este "ne<strong>de</strong>finita sau<br />

egal cu" f, <strong>si</strong> vom nota e f , daca e = ? sau e = f.<br />

Din <strong>de</strong>finitie rezulta ca evi<strong>de</strong>nt faptul ca relatia este ordine partiala.<br />

69


Vom formaliza <strong>în</strong> continuare mecanismul <strong>de</strong> mostenire al unui limbaj oarecare<br />

printr-o relatia <strong>de</strong> tranzitie asupra unei multimi <strong>de</strong> clase. O pereche <strong>de</strong> clase (P, Q) va<br />

forma o tranzitie daca Q poate fi <strong>de</strong>rivata din P prin intermediul mecanismului <strong>de</strong><br />

mostenire. Exprimarea tuturor mecanismelor <strong>de</strong> mostenire prin intermediul relatiilor<br />

<strong>de</strong> tranzitie permite separarea mostenirii <strong>de</strong> alte elemente ale limbajului, <strong>de</strong>ci se va<br />

obtine o ve<strong>de</strong>re generala, uniforma a mostenirii <strong>în</strong> diferite limbaje <strong>de</strong> programarea<br />

orientate-obiect concurente. Astfel, spre <strong>de</strong>osebire <strong>de</strong> <strong>si</strong>stemul formal propus<br />

[COO89] mostenirea nu reprezinta o parte a formalismului <strong>si</strong>stemului <strong>de</strong> meto<strong>de</strong>.<br />

Mecanismul <strong>de</strong> mostenire este surprins prin intermediul unei multimi <strong>de</strong> clase care pot<br />

fi <strong>de</strong>finite <strong>în</strong> limbaj fara a utiliza mostenirea, <strong>în</strong>tre care <strong>în</strong>sa exista o relatie <strong>de</strong><br />

tranzitie.<br />

Definitie 3. Un mecanism <strong>de</strong> mostenire reprezinta o pereche (Class, ? ), un<strong>de</strong><br />

? ? Class ? ? ? Class . Un element (P, ?, Q) din ? se numeste tranzitie. ?<br />

reprezinta multimea entitatilor <strong>si</strong>ntactice care specifica diferentele dintre P <strong>si</strong> Q. Vom<br />

scrie P ? ? ? Q<br />

?<br />

? ?<br />

pentru (P, ?, Q) ? ? . De asemenea, vom utiliza P ? ? ? ? Q<br />

*<br />

?<br />

pentru a nota <strong>în</strong>chi<strong>de</strong>rea reflexiva <strong>si</strong> tranzitiva a ? , adica o secventa <strong>de</strong> tranzitii<br />

individuale.<br />

Relatia <strong>de</strong> tranzitie ? este o multime <strong>de</strong> triplete (P, ?, Q). Tranzitiile<br />

specifica modul <strong>în</strong> care mostenirea poate fi utilizata pentru a <strong>de</strong>riva o noua clasa Q<br />

din clasa P specificând diferentele (adica noile operatii) <strong>în</strong> ?. Tranzitiile pot <strong>si</strong>mula<br />

re<strong>de</strong>finiri, adaugari sau eliminari <strong>de</strong> componente ale claselor. În [COO89] este<br />

prezentat un mo<strong>de</strong>l general <strong>de</strong> mecanism <strong>de</strong> mostenire <strong>în</strong> care este surprinsa inclu<strong>si</strong>v<br />

utilizarea lui self <strong>si</strong> super. Multimile Class <strong>si</strong> ? sunt <strong>de</strong>terminate <strong>de</strong> limbajul <strong>analiza</strong>t.<br />

Deoarece Q ? Class (Q fiind <strong>de</strong>finita fara mostenire), <strong>de</strong>finitia 3 specifica<br />

faptul ca orice clasa ce poate fi <strong>de</strong>finita utilizând mostenirea se poate <strong>de</strong>fini <strong>si</strong> fara<br />

aceasta.<br />

Se va formaliza <strong>în</strong> cele ce urmeaza notiunea <strong>de</strong> ierarhie <strong>de</strong> mostenire<br />

incrementala. Intuitiv, fiecare tranzitie utilizata <strong>în</strong>tr-o astfel <strong>de</strong> ierarhie trebuie sa fie<br />

o tranzitie incrementala, adica aceasta trebuie doar sa <strong>de</strong>fineasca noi operatii fara<br />

re<strong>de</strong>finirea nici uneia dintre operatiile mostenite.<br />

70


Definitie 4. Tranzitia P ? ? ? Q<br />

?<br />

71<br />

este incrementala daca <strong>si</strong> numai daca<br />

methods(P) methods(Q). Submultimea tuturor tranzitiilor incrementale se noteaza<br />

??<br />

? I<br />

.<br />

Se <strong>de</strong>fineste notiunea <strong>de</strong> imp(P) ca fiind o functie care returneaza cel mai<br />

specializat tip implementat <strong>de</strong> clasa P. Aceasta functie este utilizata <strong>în</strong> primul rând<br />

pentru formalizarea afirmatiei 1 prin <strong>de</strong>finirea conceptului <strong>de</strong> conservare a<br />

comportamentului. Definitia anomaliei <strong>de</strong> mostenire va fi obtinuta apoi prin<br />

formalizarea afirmatiei 2.<br />

Sunt utilizate doua rezultate din [MAN74] <strong>si</strong> care au urmatoarea semnificatie:<br />

daca x este limita inferioara pentru Y <strong>si</strong> x ? Y, atunci pY = x. De asemenea, daca pY<br />

exista atunci ea este unica.<br />

Sa presupunem ca notiunea <strong>de</strong> tip este <strong>de</strong>finita, <strong>si</strong> ca Types reprezinta<br />

multimea tuturor tipurilor po<strong>si</strong>bile. Vom con<strong>si</strong><strong>de</strong>ra acum cel mai restrâns tip<br />

implementat <strong>de</strong> catre o clasa.<br />

Definitie 5. Fie ? ? Types . Clasa P implementeaza ? daca <strong>si</strong> numai daca<br />

p ? ? , ? p ? instances(P). Mai mult, imp(P) = p{? : P implementeaza ?}. Spunem<br />

ca un mecanism <strong>de</strong> mostenire (Class, ? ) conserva comportamentul daca <strong>si</strong> numai<br />

daca P ? ? ? I Q ? imp(<br />

Q)<br />

? imp(<br />

P)<br />

?<br />

.<br />

Pentru orice notiune <strong>de</strong> tip este necesara existenta lui imp(P) pentru orice clasa<br />

P. imp(P) reprezinta cel mai restrâns tip implementat <strong>de</strong> P, <strong>si</strong> este o functie, <strong>de</strong>oarece<br />

asa cum s-a aratat mai sus, cea mai mare limita inferioara este unica. Functia imp nu<br />

este injectiva <strong>în</strong> general, <strong>de</strong>oarece <strong>de</strong> obicei exista mai multe implementari diferite ale<br />

aceluia<strong>si</strong> tip. Un mecanism <strong>de</strong> mostenire conserva comportamentul daca <strong>de</strong>-a lungul<br />

oricarui drum din cadrul unei ierarhii <strong>de</strong> mostenire incrementale subclasele sunt legate<br />

<strong>de</strong> superclasele lor prin relatia <strong>de</strong> subtipizare.<br />

Definitie 6. Fie un mecanism <strong>de</strong> mostenire (Class, ? ) <strong>si</strong> P , Q ? Class . Se<br />

<strong>de</strong>finesc urmatoarele multimi:<br />

G P<br />

? { Q:<br />

P ?<br />

*<br />

? ? ?<br />

? ? ?<br />

Q}<br />

*<br />

? ? ?<br />

I ? { Q:<br />

P ? ? ? ? I Q}<br />

P<br />

B P<br />

S P<br />

? { Q:<br />

imp(<br />

Q)<br />

? imp(<br />

P)}<br />

? { ?<br />

? Types : ? ? imp(<br />

P)}


Multimea GP reprezinta multimea tuturor claselor care pot fi obtinute din P<br />

prin aplicarea repetata a mecanismului <strong>de</strong> mostenire. De notat faptul ca GP ? Class ,<br />

<strong>în</strong>sa <strong>în</strong> majoritatea cazurilor GP ? Class <strong>de</strong>oarece multe mecanisme <strong>de</strong> mostenire<br />

permit obtinerea oricarei clase date din P prin re<strong>de</strong>finiri, eliminari <strong>si</strong> adaugari<br />

repetate. Multimea IP este o submultime a lui GP care permite doar tranzitii<br />

incrementale din P. Fie imp(P)=?. Multimea tuturor claselor care implementeaza<br />

subtipurile lui ? este notata prin BP. În general, IP nu este o submultime a lui BP daca<br />

mecanismul <strong>de</strong> mostenire nu conserva comportamentul. Intersectia ( I P ? BP)<br />

reprezinta multimea tuturor claselor care implementeaza subtipurile lui ? <strong>si</strong> care pot fi<br />

obtinute incremental din P. Imaginea multimii BP prin imp este data <strong>de</strong> imp(BP) <strong>si</strong><br />

este o submultime a lui SP, multimea tuturor subtipurilor lui ?. În majoritatea<br />

cazurilor vom avea SP = imp(BP).<br />

Class<br />

GP<br />

IP<br />

BP<br />

imp<br />

72<br />

imp<br />

imp<br />

imp(I P? B P)<br />

S P<br />

Types<br />

imp(Bp)<br />

Figura 3.6. Reprezentarea grafica a multimilor din <strong>de</strong>finitia 7<br />

pentru o clasa particulara P<br />

Definitie 7. Un mecanism <strong>de</strong> mostenire (Class, ? ) este fara anomalii relativ la<br />

Types daca <strong>si</strong> numai daca ? P ? Class,<br />

imp(<br />

I P ? BP)<br />

? imp(<br />

BP)<br />

..<br />

Propozitie 1. Fie P? Class . Mecanismul <strong>de</strong> mostenire (Class, ? ) este fara<br />

anomalii relativ la o <strong>de</strong>finitie data pentru Types daca <strong>si</strong> numai daca ? Q ? Class , daca<br />

imp(Q) ? imp(P) atunci<br />

*<br />

? ? ? ? , R? Class astfel <strong>în</strong>cât P ? ? ? I R<br />

?<br />

<strong>si</strong> imp(R)=imp(Q).<br />

Demonstratie: Presupunem ca mecanismul <strong>de</strong> mostenire este fara anomalii.<br />

Prin urmare Q? BP<br />

. Conform <strong>de</strong>finitiei 8 ? R ? ( IP<br />

? BP)<br />

astfel <strong>în</strong>cât


imp(R)=imp(Q). Prin urmare P ? ? ? I R<br />

?<br />

inversa se <strong>de</strong>monstreaza <strong>în</strong> mod analog. ?<br />

73<br />

pentru un anumit<br />

*<br />

? ? ? . Implicatia<br />

Definitia 7 reprezinta <strong>de</strong>scrierea generala a anomaliei <strong>de</strong> mostenire <strong>în</strong><br />

programarea orientata obiect concurenta. O ver<strong>si</strong>une particulara a acestei <strong>de</strong>finitii<br />

este data <strong>de</strong> o notiune particulara <strong>de</strong> tip. Un mecanism <strong>de</strong> mostenire poate fi fara<br />

anomalii relativ la o ver<strong>si</strong>une particulara <strong>de</strong> tip, <strong>si</strong> <strong>în</strong> acela<strong>si</strong> timp sa contina anomalii<br />

relativ la o alta ver<strong>si</strong>une. Acesta observatie explica incon<strong>si</strong>stentele existente <strong>în</strong><br />

literatura pe aceasta tema. Pâna acum, notiunea <strong>de</strong> tip care <strong>de</strong>termina o anomalie <strong>de</strong><br />

mostenire a fost data doar informal <strong>de</strong> catre cercetatori, prin intermediul exemplelor.<br />

Prin urmare, diferenta dintre aceste notiuni conduce la concluzii diferite cu privire la<br />

aparitia <strong>si</strong> implicatiile anomaliilor <strong>de</strong> mostenire.<br />

Anomaliile <strong>de</strong> mostenire sunt <strong>în</strong> mod obisnuit privite ca fiind generate <strong>de</strong><br />

interferenta dintre mostenire <strong>si</strong> concurenta. Acest mod <strong>de</strong> a ve<strong>de</strong>a lucrurile nu este<br />

<strong>în</strong>sa <strong>si</strong> cel mai general. De exemplu, anomalii <strong>de</strong> mostenire au fost <strong>în</strong>tâlnite <strong>si</strong> <strong>în</strong><br />

cazul limbajelor <strong>de</strong> specificare <strong>în</strong> timp real secventiale. Formalismul prezentat<br />

permite <strong>analiza</strong> anomaliilor <strong>de</strong> mostenire <strong>în</strong> paradigme diferite.<br />

Mai mult, mo<strong>de</strong>larea utilizata pentru formalizarea mostenirii poate fi utilizata<br />

<strong>în</strong> mod analog pentru formalizarea relatiilor <strong>de</strong> agregare sau a mecanismelor <strong>de</strong><br />

<strong>de</strong>legare. Prin urmare anomalii <strong>de</strong> genul celor i<strong>de</strong>ntificate <strong>în</strong> literatura ca fiind<br />

generate <strong>de</strong> conflicte <strong>în</strong>tre concurenta <strong>si</strong> mostenire pot fi generalizate la anomaliile <strong>de</strong><br />

reutilizare i<strong>de</strong>ntificate <strong>în</strong>tr-o maniera informala <strong>în</strong> sectiunea prece<strong>de</strong>nta.<br />

Vom <strong>de</strong>zvolta o taxonomie prin utilizarea a doua notiuni particulare <strong>de</strong> tip din<br />

programarea orientata-obiect concurenta care <strong>de</strong>finesc submultimi ale multimii tuturor<br />

anomaliilor. Scopul principal al acestei sectiuni este acela <strong>de</strong> a a<strong>si</strong>gura faptul ca toate<br />

anomaliile <strong>de</strong> mostenire <strong>de</strong>terminate <strong>în</strong> literatura sunt incluse <strong>în</strong> taxonomie.<br />

Abordarea formala conduce la exemple <strong>de</strong> anomalii care nu au fost discutate pâna <strong>în</strong><br />

prezent, ceea ce <strong>de</strong>monstreaza <strong>în</strong>ca odata <strong>de</strong>zavantajele abordarii informale.<br />

Functiile <strong>si</strong> multimile semantice <strong>de</strong>finite <strong>în</strong> figura 3.7 sunt utilizate pentru<br />

formalizarea comportamentului unei instante. Notiunea <strong>de</strong> comportament con<strong>si</strong><strong>de</strong>rata<br />

aici priveste un obiect ca o "cutie neagra" care accepta sau nu un anumit mesaj, <strong>în</strong><br />

timp ce un observator extern retine toate acceptarile <strong>de</strong> mesaje. Prin urmare,<br />

comportamentul unei instante este dat <strong>de</strong> o multime <strong>de</strong> secvente <strong>de</strong> mesaje.


Functia beh furnizeaza multimea tuturor secventelor <strong>de</strong> mesaje po<strong>si</strong>bile pe care<br />

le poate accepta o instanta. Se presupune ca aceasta multime este <strong>în</strong>chisa la prefixare,<br />

adica având o secventa valida < a, a, b >, se con<strong>si</strong><strong>de</strong>ra vali<strong>de</strong> <strong>si</strong> secventele , <strong>si</strong><br />

< a, a>.<br />

beh : Instance ? ? (Key * )<br />

Semantici <strong>de</strong> urma:<br />

bec : Class ? ? (Key * ), bec(P) = p{ beh(p) : p ? instances(P) }<br />

Semantici <strong>de</strong> stari<br />

state : ? (Key * ) ? Key * ? ? (Key * )<br />

state(?)u = ?<br />

? ? { z : u^<br />

z ? ? }, daca u ? ?<br />

? , in rest<br />

States : ? (Key * ) ? ? (? (Key * ))<br />

States(?) = { state(?)u : u ? ? }<br />

Figura 3.7. Multimi <strong>si</strong> functii semantice pentru<br />

formalizare comportamentului obiectelor concurente<br />

Functia bec returneaza comportamentul unei clase. Dupa cum se observa,<br />

comportamentul unei clase este privit ca <strong>si</strong> comportamentul comun al tuturor<br />

instantelor acesteia. Daca ? este o multime <strong>de</strong> instante atunci notatia pbeh? reprezinta<br />

cea mai mare margine inferioara a comportamentelor instantelor din ?, p{ beh(p) :<br />

p ? ?}. Se va utiliza formalismul <strong>de</strong> urme pentru manipularea secventelor <strong>de</strong> mesaje<br />

<strong>de</strong>finit <strong>în</strong> [HOA85]. Operatia <strong>de</strong> concatenare construieste o urma dintr-o pereche <strong>de</strong><br />

urme u <strong>si</strong> v punându-le împreuna <strong>în</strong> aceasta ordine, rezultatul fiind notat prin u^v.<br />

Capul unei urme u este primul <strong>si</strong>mbol din aceasta, <strong>si</strong> este notat cu u0.<br />

*<br />

Definitie 8. Multimile <strong>de</strong> secvente <strong>de</strong> mesaje ? , ? ?? ( Key ) se afla <strong>în</strong> relatia:<br />

? T ?<br />

daca <strong>si</strong> numai daca ? ? ? <strong>si</strong> ? u ? ?, u = v^z un<strong>de</strong> v ? ? iar z0 (daca exista) nu apare<br />

niciodata <strong>în</strong> ?. Multimea nevida <strong>de</strong> instante ? este un alement al TypesT daca <strong>si</strong> numai<br />

daca ? p ? ?, pbeh? T beh(p). Mai mult, daca q ? Instance astfel <strong>în</strong>cât pbeh? T<br />

beh(q), atunci q ? ?.<br />

74


Definitia 8 afirma faptul ca o multime <strong>de</strong> instante ? reprezinta un tip,<br />

caracterizat <strong>de</strong> pbeh?, daca <strong>si</strong> numai daca fiecare instanta din ? accepta cel putin toate<br />

secventele <strong>de</strong> mesaje din pbeh?. Bine<strong>în</strong>teles, o instanta din ? mai poate accepta <strong>si</strong> ale<br />

secvente, care <strong>în</strong>sa vor <strong>în</strong>cepe cu o urma v din pbeh? urmate <strong>de</strong> un mesaj z0 (ce nu<br />

apare <strong>în</strong> pbeh?) care este acceptat <strong>de</strong> instanta. Prin urmare o instanta din ? se va<br />

comporta i<strong>de</strong>ntic cu pbeh? pâna <strong>în</strong> momentul <strong>în</strong> care va accepta un mesaj nou, dupa<br />

care va avea un comportament distinct (va avea o functionalitate aditionala). Mai<br />

mult, ? reprezinta multimea tuturor instantelor care satisfac proprietatile caracteristice<br />

ale lui ?.<br />

O limitarea a <strong>de</strong>finitiei <strong>de</strong> tip TypeT este aceea ca nu captureaza corespunzator<br />

cazul <strong>în</strong> care instantele unei clase au comportamente diferite. De exemplu, clasa<br />

Coada(n) cu un argument n poate fi utilizata <strong>în</strong> instantierea unei cozi care contine n<br />

elemente. Conform <strong>de</strong>finitiei pentru TypeT <strong>si</strong>ngurul tip implementat <strong>de</strong> aceasta clasa<br />

este tipul caracterizat <strong>de</strong> { < > }, adica tipul continut <strong>de</strong> toate instantele ale tutror<br />

claselor (<strong>de</strong>oarece <strong>în</strong> cazul n = 0 bec returneaza { < > }). În consecinta, informatia<br />

relativa la comportamentul comun al instantelor lui Coada(n) este pierdut. Aceasta<br />

limitare poate fi <strong>în</strong>laturata prin rafinarea <strong>de</strong>finitiei pentru TypesT. În aceasta sectiune<br />

vom utiliza notiune <strong>de</strong> tip specificata <strong>în</strong> <strong>de</strong>finitia 8, concentrându-ne atentia asupra<br />

aspectelor legate <strong>de</strong> taxonomie. Prin urmare vom presupune ca toate instantele unei<br />

clase au acela<strong>si</strong> comportament, adica ? p ? instances(p), beh(p) = bec(P).<br />

Propozitie 2. Fie o relatie care captureaza proprietatile comune ale tuturor<br />

instantelor reletive la un anumit tip. Daca este o preordine atunci pbeh? pbeh?<br />

daca <strong>si</strong> numai daca ? ? ?. În plus, pentru orice clasa P imp(P) = ? exista <strong>si</strong> pbeh? =<br />

bec(P).<br />

Demonstratie: Presupunem ca pbeh? pbeh? <strong>si</strong> fie p ? ?. Avem pbeh?<br />

beh(p). Din tranzitivitatea relatiei obtinem pbeh? beh(p) <strong>si</strong> <strong>de</strong>ci p ? ?.<br />

Presupunem, pentru implicatia inversa, ca ? ? ?, <strong>si</strong> fie o instanta p astfel <strong>în</strong>cât<br />

beh(p) = pbeh?. Din reflexivitatea relatiei rezulta ca p ? ?. Prin urmare, p ? ? <strong>si</strong><br />

pbeh? beh(p). Deoarece beh(p) = pbeh? obtinem pbeh? pbeh?.<br />

Fie o clasa P <strong>si</strong> un tip ? astfel <strong>în</strong>cât pbeh? = bec(P), <strong>si</strong> fie p o instanta a lui P.<br />

Din reflexivitatea relatiei <strong>si</strong> pe baza presupunerii ca bec(P) = beh(p) avem pbeh?<br />

beh(p). Prin urmare orice instanta p a lui P apartine tipului ?, <strong>si</strong> <strong>de</strong>ci P<br />

75


implementeaza tipul ?. Sa presupunem <strong>de</strong> asemenea ca P implementeaza ?. Prin<br />

urmare pbeh? bec(P) <strong>si</strong> <strong>de</strong>oarece pbeh? = bec(P) vom obtine pbeh? pbeh?. Pe baza<br />

rezultatului anterior vom avea ? ? ?. Prin urmare ? este o limita inferioara a multimii<br />

{ ? : P implementeaza ? }, <strong>si</strong> <strong>de</strong>oarece se un element al acestei multimi vom avea ca ?<br />

= imp(P).?<br />

Propozitie 3. Relatia T este preordine.<br />

Demonstratie: Presupunem ca ? T ? <strong>si</strong> ? T ? , un<strong>de</strong> ?, ?, ? ? ? (Key * ).<br />

Atunci, ? ? ? <strong>si</strong> ? u ? ?, u = v^z cu v ? ? <strong>si</strong> z (po<strong>si</strong>bil vid) astfel <strong>în</strong>cât <strong>si</strong>mbolul z0<br />

(daca exista) nu apare niciodata <strong>în</strong> ?. Este evi<strong>de</strong>nt ca ? ? ? .<br />

Fie u ? ? , u = v^z un<strong>de</strong> v ? ? <strong>si</strong> <strong>de</strong>oarece ? T ? avem v = v1^v2 un<strong>de</strong> v1 ? ?.<br />

Rezulta ca u = v1^(v2^z) <strong>si</strong> din contructie primul <strong>si</strong>mbol din v2^z nu apare niciodata <strong>în</strong><br />

?, <strong>de</strong>ci ? T ? . De asemenea, pe baza <strong>de</strong>finitiei, este evi<strong>de</strong>nt ca T este reflexiva. ?<br />

Propozitiile 2 <strong>si</strong> 3 implica faptul ca pentru fiecare clasa cel mai restrâns tip<br />

implementat <strong>de</strong> aceasta este unic. Un astfel <strong>de</strong> tip, notat cu impT(P) este caracterizat<br />

<strong>de</strong> comportamentul clasei P. În acest moment pot fi <strong>analiza</strong>te cazuri concrete <strong>de</strong><br />

anomalii <strong>de</strong> mostenire relative la TypesT. Fie doua clase P <strong>si</strong> Q. Daca cel mai specific<br />

tip implementat <strong>de</strong> Q (impT(Q) ? TypesT) este un subtip al celui mai specific tip<br />

implementat <strong>de</strong> P atunci conform propozitiei 1 trebuie sa existe o clasa R care poate fi<br />

<strong>de</strong>rivata incremental din P <strong>si</strong> care implementeaza impT(Q). În caz contrar are loc o<br />

anomalie <strong>de</strong> mostenire.<br />

Anomalia <strong>de</strong> mostenire indusa <strong>de</strong> TypesT reprezinta doar o ver<strong>si</strong>une a<br />

problemei generale a anomaliilor <strong>de</strong> mostenire <strong>în</strong> programarea orientata-obiect<br />

concurenta. Exista multe alte notiuni <strong>de</strong> tip utile care pot fi <strong>analiza</strong>te (<strong>de</strong> exemplu, un<br />

subtip poate fi <strong>de</strong>finit astfel <strong>în</strong>cât sa restrictioneze po<strong>si</strong>bilele secvente <strong>de</strong> mesaje din<br />

supertip). TypesT induce o anomalie <strong>de</strong> mostenire <strong>de</strong>oarece afirmatia 1 este respectata<br />

cu privire la aceasta notiune <strong>de</strong> tip, <strong>în</strong> timp ce presupunerea ca afirmatia 2 se respecta<br />

<strong>în</strong> raport cu TypesT s-a dovedit a fi falsa.<br />

Vom con<strong>si</strong><strong>de</strong>ra <strong>în</strong> cele ce urmeaza doua submultimi ale multimii <strong>de</strong> anomalii<br />

induse <strong>de</strong> TypesT. Cu scopul <strong>de</strong> a <strong>de</strong>finii formal aceste doua submultimi se va utiliza<br />

o notiune <strong>de</strong> tip mai puternica. Astfel, se va con<strong>si</strong><strong>de</strong>ra un obiect ca fiind o ma<strong>si</strong>na <strong>de</strong><br />

stari care evolueaza <strong>de</strong> la o stare curenta la o noua stare prin acceptarea unui mesaj <strong>si</strong><br />

executarea expre<strong>si</strong>ei <strong>de</strong> metoda corespunzatoare. Prima submultime <strong>de</strong> anomalii este<br />

76


obtinuta prin constrângerea tuturor instantelor ale aceluia<strong>si</strong> tip <strong>de</strong> a evolua prin acela<strong>si</strong><br />

numar <strong>de</strong> stari <strong>de</strong> baza (<strong>de</strong>finitia 10). Prin urmare se con<strong>si</strong><strong>de</strong>ra ca toate instantele<br />

tipului respectiv sunt implementate prin ma<strong>si</strong>ni <strong>de</strong> stari <strong>si</strong>milare. Cea <strong>de</strong>-a doua<br />

submultime <strong>de</strong> anomalii este obtinuta permitând instantelor aceluia<strong>si</strong> tip sa evolueze<br />

<strong>în</strong> stari aditionale, dar numai <strong>în</strong> cazul <strong>în</strong> care aceste stari reprezinta ver<strong>si</strong>uni restrânse<br />

ale starilor <strong>de</strong> baza (<strong>de</strong>finitia 11).<br />

Intuitiv, starea unui obiect este <strong>de</strong>terminata <strong>de</strong> valorile propriilor atribute.<br />

Acest lucru <strong>în</strong>sa nu este observabil din exterior. De aceea vom con<strong>si</strong><strong>de</strong>ra o stare ca<br />

fiind multimea secventelor <strong>de</strong> mesaje care sunt acceptabile la un moment dat. Fie p o<br />

instanta a clasei Coada. Initial, p poate accepta orice secventa din beh(p). Prin<br />

urmare starea initiala a lui p este beh(p). Dupa acceptarea mesajului Adauga,<br />

multimea secventelor <strong>de</strong> mesaje acceptabile se modifica (<strong>de</strong> exemplu secventa<br />

nu era acceptata <strong>în</strong> starea initiala dar acuma da - este secventa corespunzatoare care este acceptata din starea<br />

initiala). Vom spune astfel ca p evolueaza <strong>de</strong> la starea initiala la o noua stare. De<br />

exemplu, secventele <strong>de</strong> mesaje , , < Adauga,<br />

Extrage, Adauga> conduc toate spre accea<strong>si</strong> stare a lui p. Functia state din<br />

semanticile starilor <strong>de</strong>rivate <strong>de</strong>scrise <strong>în</strong> figura 3.7 primeste starea initiala a unei<br />

instante <strong>si</strong> returneaza starea instantei dupa acceptarea secventei <strong>de</strong> mesaje u. Functia<br />

States retunreaza pe baza starii initiale a unei instante, multimea tuturor starilor<br />

instantei (multime ce poate fi infinita).<br />

state(?)u.<br />

Propozitie 4. Fie ?, ? ? ? (Key * ) <strong>si</strong> ? T ?. Atunci, ? u ? ?, state(?)u T<br />

Demonstratie. Fie u ? ?. Deoarece ? ? ?, u ? ? <strong>si</strong> state(?)u ? ? . Fie t ?<br />

state(?)u. Atunci u^t ? ?. Deci t ? state(?)u <strong>si</strong> avem state(?)u ? state(?)u.<br />

Fie z ? state(?)u. Rezulta ca u^z ? ? <strong>si</strong> <strong>de</strong>oarece ? T ?, u^z = (u^z1)^z2 un<strong>de</strong><br />

u^z1? ? <strong>si</strong> primul <strong>si</strong>mbol din z2 nu apare niciodata <strong>în</strong> ?. Prin urmare, z1 ? state(?)u. ?<br />

Pentru a exemplifica propozitia 4 sa con<strong>si</strong><strong>de</strong>ram o instanta, p, a clasei Coada,<br />

<strong>si</strong> o instanta, q, a clasei Coada2. Dupa acceptarea unei secvente <strong>de</strong> mesaje u, p va<br />

ajunge <strong>în</strong>tr-o stare ?, iar q <strong>în</strong>tr-o stare ?. Intuitiv putem spune ca <strong>în</strong>tre cele doua stari<br />

trebuie sa existe o relatie strânsa. Propozitia 4 arata ca orice secventa <strong>de</strong> mesaje<br />

acceptabila din starea ? este <strong>de</strong> asemenea acceptabila <strong>si</strong> din starea ?. Acest lucru<br />

trebuie sa aiba loc <strong>de</strong>oarece Coada2 implementeaza un subtip al tipului implementat<br />

77


<strong>de</strong> Coada, <strong>si</strong> <strong>de</strong>ci trebuie ca instantele acestei clase sa se comporte <strong>în</strong> mod <strong>si</strong>milar cu<br />

instantele clasei Coada. În plus, starea ? poate permite sî altor secvente <strong>de</strong> mesaje sa<br />

fie acceptate, secvente <strong>de</strong> mesaje care vor contine noul mesaj Extrage2(). În general,<br />

dupa acceptarea unei astfel <strong>de</strong> secvente, q poate sa evolueze spre o stare noua, care nu<br />

are legatura cu nici una dintre starile lui p. În cazul clasei Coada2, o instanta a<br />

acesteia nu va ajunge niciodata <strong>în</strong>tr-o stare care nu corespun<strong>de</strong> unei stari ale lui p. În<br />

cazul cla<strong>si</strong> BCoada <strong>în</strong>sa, o instanta poate sa ajunga <strong>în</strong>tr-o astfel <strong>de</strong> stare <strong>în</strong> momentul<br />

acceptarii mesajului Blocare(). În aceasta stare nici unul dintre mesajele Extrage() <strong>si</strong><br />

Adauga() nu sunt acceptate, ceea ce nu se <strong>în</strong>tâmpla <strong>în</strong> nici una dintre starile clasei<br />

Coada.<br />

Definitie 9. Fie ?,? ? ? (Key * ). Atunci,<br />

? f ?<br />

daca <strong>si</strong> numai daca ? T ? <strong>si</strong> ?f : States(?) ? States(?) astfel <strong>în</strong>cât f sa fie bijectie.<br />

Multimea nevida <strong>de</strong> instante ? este un element din Typesf daca <strong>si</strong> numai daca ? p ? ?,<br />

pbeh? f beh(p). În plus, daca q ? Instance <strong>si</strong> pbeh? f beh(q) atunci q ? ?.<br />

Definitia 9 afirma faptul ca o multime <strong>de</strong> instante ale lui ? reprezinta un tip,<br />

caracterizat prin pbeh?, daca <strong>si</strong> numai daca ? este un tip <strong>de</strong>finit <strong>de</strong> <strong>de</strong>finitia 9 <strong>si</strong> fiacare<br />

instanta din ? are acela<strong>si</strong> numar <strong>de</strong> stari. Pe baza propozitiei 4, fiecare stare din pbeh?<br />

este <strong>în</strong> strânsa legatura cu starile unei instante din ?. Deoarece numarul <strong>de</strong> stari este<br />

egal, rezulta ca fiecare stare a unei instante este la rândul sa <strong>în</strong> legatura cu o stare din<br />

pbeh?. Prin urmare, toate instantele tipului ? se au un comportament mo<strong>de</strong>lat <strong>de</strong><br />

ma<strong>si</strong>ni <strong>de</strong> stari <strong>si</strong>milare.<br />

Propozitie 5. f este preordine. Demonstratia este imediata. ?<br />

Propozitie 6. Multimea <strong>de</strong> anomalii relative la notiunea <strong>de</strong> tip Typesf este o<br />

submultime a multimii <strong>de</strong> anomalii induse <strong>de</strong> notiunea <strong>de</strong> tip TypesT. Demonstratia se<br />

afla <strong>în</strong> [CRN98]. ?<br />

Notiunea <strong>de</strong> tip Typesf ne conduce la o submultime a problemei. Exemple <strong>de</strong><br />

limbaje <strong>de</strong> programare orientate-obiect concurente care sufera <strong>de</strong> anomalii <strong>de</strong><br />

mostenire relative la Typesf sunt limbajele cu rutine <strong>de</strong> vitalizare <strong>si</strong> cele care utilizeaza<br />

multimi <strong>de</strong> acceptare. Asa cum am aratat <strong>în</strong> capitolul doi, limbajele cu rutine <strong>de</strong><br />

vitalizare realizeaza specificarea explicita a acceptarii mesajelor <strong>în</strong> cadrul unor functii<br />

speciale. Aceste limbaje genereaza anomalii <strong>de</strong> tipul celor <strong>de</strong>finite <strong>în</strong> <strong>de</strong>finitia 10, din<br />

78


cauza controlului <strong>de</strong> interfata centralizat, care grupeaza toate constrângerile <strong>de</strong><br />

<strong>si</strong>ncronizare <strong>în</strong>tr-o <strong>si</strong>ngura functie. Astfel, adaugarea unei noi operatii <strong>în</strong>tr-o subclasa<br />

<strong>de</strong>termina re<strong>de</strong>finirea functiei <strong>de</strong> vitalizare, <strong>în</strong> caz contrar aceasta operatie neputând sa<br />

fie executata niciodata.<br />

Exista <strong>si</strong> limbaje care nu au un control centralizat al interfetei, dar care sunt<br />

predispuse la anomalii relativ la notiunea <strong>de</strong> tip Typesf. În majoritatea acestor limbaje<br />

controlul <strong>si</strong>ncronizarii se realizeaza utilizând multimi <strong>de</strong> acceptare, specificându-se <strong>de</strong><br />

fiecare data multimea curenta <strong>de</strong> operatii acceptabile specificata <strong>de</strong> codul <strong>de</strong><br />

<strong>si</strong>ncronizare. Multimea <strong>de</strong> operatii acceptabile se modifica pe masura ce obiectul<br />

evolueaza, <strong>si</strong> acest lucru se realizeaza prin specificarea <strong>de</strong> catre fiecare operatie a<br />

urmatoarei multimi <strong>de</strong> acceptare.<br />

Anomaliile <strong>de</strong> partitionare a starilor abstracte din cla<strong>si</strong>ficarea propusa <strong>de</strong><br />

Matsuoka <strong>si</strong> Yonezawa [MAT93] satisfac <strong>de</strong>finitia 9. Prin urmare, aceste anomalii<br />

sunt exemple <strong>de</strong> anomalii relative la notiunea <strong>de</strong> tip Typesf. Anomaliile induse <strong>de</strong><br />

Typesf sunt eliminate <strong>în</strong> multe abordari prin intermediul meto<strong>de</strong>lor cu garzi.<br />

Propozitie 7. Un limbaj <strong>de</strong> programare orientat-obiect concurent care<br />

implementeaza mecanismul <strong>de</strong> <strong>si</strong>ncronizare bazat pe meto<strong>de</strong> cu garzi este fara<br />

anomalii relative la Typesf.<br />

Demonstratie. Demonstratia completa nece<strong>si</strong>ta o formalizare a semanticii<br />

garzilor. Fie clasele P <strong>si</strong> Q astfel <strong>în</strong>cât impf(Q) ? impf(P). Sa presupunem ca<br />

M(P) = {m1, ..., mn} <strong>si</strong> M(Q) = { m1, ..., mk} un<strong>de</strong> n ? k. Putem presupune, fara a se<br />

restrânge generalitatea, ca k = n+1. Sa presupunem <strong>de</strong> asemenea ca ambele clase<br />

utilizeaza meto<strong>de</strong> cu garzi.<br />

Se va construi incremental clasa R din P astfel <strong>în</strong>cât impf(R)=impf(Q).<br />

Deoarece bec(P) f bec(Q) este suficienta construirea unei garzi pentru metoda mn+1<br />

<strong>în</strong> R astfel <strong>în</strong>cât mn+1 sa fie acceptata daca <strong>si</strong> numai daca ea este acceptata <strong>de</strong> garda<br />

acesteia din Q. Ar fi i<strong>de</strong>ala utilizarea garzii din Q pentru <strong>de</strong>finirea meto<strong>de</strong>i din R <strong>în</strong>sa<br />

acest lucru nu poate fi realizat <strong>de</strong>oarece aceasta poate contine proprietati ale clasei Q<br />

care sunt diferite <strong>de</strong> cele din R.<br />

Din aceasta cauza garda pentru metoda mn+1 se va construi astfel: garda are o<br />

multime oarecare <strong>de</strong> instante ale claselor P <strong>si</strong> Q. La receptionarea unui mesaj mn+1<br />

expre<strong>si</strong>a <strong>de</strong> garda trebuie sa <strong>de</strong>termine care secventa <strong>de</strong> mesaje conduce la starea<br />

curenta a obiectului. Aceasta este obtinuta prin <strong>în</strong>cercarea tuturor secventelor <strong>de</strong><br />

79


mesaje po<strong>si</strong>bile <strong>de</strong> lungimi 1, 2, ... În mod evi<strong>de</strong>nt acest proces va putea <strong>de</strong>termina<br />

atât secventa <strong>de</strong> mesaje care a condus la starea curenta cât <strong>si</strong> alte secvente cu acela<strong>si</strong><br />

efect. Prima secventa <strong>de</strong> acest tip va fi aplicata unei instante a clasei Q, urmata <strong>de</strong><br />

mesajul mn+1. Garda clasei R va accepta apelul <strong>de</strong> metoda mn+1 daca <strong>si</strong> numai daca<br />

instanta clasei Q accepta mesajul mn+1. De notat ca evaluarea garzii clasei R nu va<br />

genera efecte secundare asupra proprietatilor lui R. Prin urmare R satisface<br />

proprietatea 1. ?<br />

Se va <strong>de</strong>fini <strong>în</strong> continuare cea <strong>de</strong>-a doua submultime <strong>de</strong> anomalii <strong>de</strong> mostenire.<br />

Definitie 10. Fie ?, ? ? ? (Key * ). Relatia:<br />

? R ?<br />

are loc daca <strong>si</strong> numai daca ? T ? <strong>si</strong> ? s ? States(?), ?s' ? States(?) astfel <strong>în</strong>cât, ? u ?<br />

s u contine un <strong>si</strong>mbol m care nu apare niciodata <strong>în</strong> ? sau u ? s'. Multimea nevida <strong>de</strong><br />

instante ale lui ? este un element al TypesR daca <strong>si</strong> numai daca ? p ? ?, pbeh? R<br />

beh(p). În plus, daca q ? Instance astfel <strong>în</strong>cât pbeh? R beh(q) atunci q ? ?.<br />

Definitia 10 afirma faptul ca o multime <strong>de</strong> instante ? reprezinta un tip,<br />

caracterizat <strong>de</strong> pbeh? daca <strong>si</strong> numai daca ? este un tip caracterizat <strong>de</strong> <strong>de</strong>finitia 8 <strong>si</strong><br />

fiecare stare a unei instante <strong>în</strong> ? reprezinta o restrictie a uneia dintre starile din pbeh?.<br />

Cu alte cuvinte, o instanta din ? poate avea mai multe stari <strong>de</strong>cât pbeh? (care sunt<br />

'activate' <strong>în</strong> momentul aceptarii unuia dintre mesajele noi). Fiecare dintre starile noi<br />

trebuie sa contina urme din una din starile din pbeh? sau urme care implica meto<strong>de</strong><br />

noi.<br />

Anomaliile <strong>de</strong> mostenire <strong>de</strong>terminate <strong>de</strong> istoric <strong>si</strong> cele <strong>de</strong> modificarea starilor<br />

abstracte se <strong>în</strong>cadreaza amândoua <strong>în</strong> <strong>de</strong>finitia 10. Figura 3.8 prezinta pozitia celor<br />

trei anomalii i<strong>de</strong>ntificate <strong>în</strong> cla<strong>si</strong>ficarea Matsuoka-Yonezawa relativ la anomaliile <strong>de</strong><br />

mostenire bazate pe notiunile <strong>de</strong> tip formalizate pâna acum.<br />

Propozitie 8. R este preordine. Demonstratia este imediata. ?<br />

În mod analog cu propozitia 6 se poate arata ca multimea anomaliilor induse<br />

<strong>de</strong> TypesR reprezinta o submultime a multimii anomaliilor induse <strong>de</strong> TypesT,<br />

conducând la ierarhia din figura 3.8.<br />

80


anomalii <strong>de</strong><br />

modificare a starii<br />

anomalii <strong>de</strong><br />

partitionare a starii<br />

anomalii<br />

<strong>de</strong>terminate <strong>de</strong> istoric<br />

T R f<br />

Figura 3.8. Anomalii induse <strong>de</strong> trei <strong>de</strong>finitii <strong>de</strong> tip<br />

Teorema 1. Fie un mecanism <strong>de</strong> mostenire (Class, ? ). Daca (Class, ? )<br />

conserva comportamentul relativ la TypesT atunci acesta nu este fara anomalii relativ<br />

la TypesR.<br />

Demonstratie. Fie Reg ? ? (Key * ) multimea tuturor limbajelor regulare<br />

peste Key. Vom presupune ca Reg ? bec(Class) - <strong>de</strong>ci fiecare limbaj regular poate fi<br />

acceptat <strong>de</strong> instante ale unei clase. Sa presupunem <strong>de</strong> asemenea ca mecanismul <strong>de</strong><br />

mostenire este fara anomalii relativ la TypesR <strong>si</strong> conserva comportamentul <strong>în</strong> raport cu<br />

<strong>de</strong>finitia <strong>de</strong> tip TypesT.<br />

Fie P ? Class astfel <strong>în</strong>cât bec(P)={ m1, m2 } * pentru anumiti m1, m2 ? Key.<br />

Fie u ? bec(P) <strong>si</strong> m ? Key astfel <strong>în</strong>cât m nu apare <strong>în</strong> bec(P). Atunci v = u^ ?<br />

bec(P).<br />

Vom con<strong>si</strong><strong>de</strong>ra acum tipul ? ? TypesR, un<strong>de</strong> pbeh? = bec(P) ? { v, v^ }.<br />

Deoarece bec(P) R pbeh? rezulta ca ? ? impR(P) (v <strong>în</strong>cepe cu u care apartine lui<br />

bec(P)). De asemenea fiecare stare din pbeh? contine urme care contin meto<strong>de</strong>le m, m1<br />

sau m2, <strong>si</strong> fiecare urma care contine m1 <strong>si</strong>/sau m2 reprezinta o urma <strong>în</strong> starea unica a<br />

lui bec(P). Aplicând <strong>în</strong>chi<strong>de</strong>rea, vom avea pbeh? ? Reg.<br />

Prin urmare, ? Q ? Class astfel <strong>în</strong>cât bec(Q) = pbeh?, <strong>si</strong> <strong>de</strong>ci impR(Q) ?<br />

impR(P). Pe baza propozitiei 1 vom avea:<br />

(1) ?? ? ? * , R ? Class a. î. P ? ? ? I R<br />

?<br />

<strong>si</strong> impR(R) = impR(Q) = ?.<br />

Vom presupune <strong>în</strong> continuare ca, având P ? ? ? I Q <strong>si</strong> z ? bec(Q) atunci este<br />

po<strong>si</strong>bila construirea lui P' <strong>si</strong> Q' astfel <strong>în</strong>cât P'? ? ? I Q'<br />

, bec(Q') = state(bec(Q))z <strong>si</strong><br />

bec(P') = state(bec(P))w, cu w ? bec(P). Din presupunerea <strong>de</strong> mai sus avem ca Q' <strong>si</strong><br />

81


P' difera <strong>de</strong> Q respectiv P doar prin starea initiala. Starea unei instante este<br />

<strong>de</strong>terminata <strong>de</strong> valorile proprietatilor sale. Deci, Q' se obtine din Q prin modificarea<br />

valorilor initiale ale anumitor proprietatile. În functie <strong>de</strong> limbaj acest lucru poate<br />

invalida tranzitia incrementala dintre P <strong>si</strong> Q'. Prin urmare, vom impune ca fiind<br />

<strong>în</strong>tot<strong>de</strong>auna po<strong>si</strong>bila modificarea valorilor initiale ale proprietatilor din P (obtinând<br />

P') astfel <strong>în</strong>cât P' ? ? ? I Q'<br />

. Aceasta afirmatie este a<strong>de</strong>varata pentru toate limbajele<br />

<strong>de</strong> programare orientate obiect concurente imperative studiate <strong>în</strong> cadrul capitolului<br />

doi.<br />

Pornind <strong>de</strong> la expre<strong>si</strong>a (1), vom con<strong>si</strong><strong>de</strong>ra v = u^ ? bec(R) <strong>si</strong> vom<br />

construi clasa R' astfel <strong>în</strong>cât bec(R') = state(bec(R))v. Din presupunerea anterioara<br />

'<br />

avem P' ? ? ? I R'<br />

?<br />

<strong>si</strong> bec(P') = state(bec(P))w, cu w ? bec(P). Dar bec(R') = { < >,<br />

} <strong>în</strong> timp ce bec(P') = { m1, m2 } * (P are o <strong>si</strong>ngura stare).<br />

Deci bec(P') T bec(R') <strong>si</strong> impT(R') ?? impT(P'). Prin urmare mecanismul <strong>de</strong><br />

mostenire nu conserva comportamentul.?<br />

Teorema 1 <strong>de</strong>monstreaza faptul ca chiar pentru o submultime a anomaliilor<br />

(indusa <strong>de</strong> TypesR), nu poate fi proiectat un limbaj <strong>de</strong> programare orientat-obiect<br />

concurent fara anomalii <strong>si</strong> care conserva comportamentul. Majoritatea limbajelor <strong>de</strong><br />

programare orientate-obiect concurente conserva comportamentul relativ la TypesT.<br />

Teorema 1 are loc doar pentru limbajele <strong>de</strong> programare care sunt cel putin la fel <strong>de</strong><br />

expre<strong>si</strong>ve ca <strong>si</strong> ma<strong>si</strong>nile cu stari finite.<br />

3.4. Mo<strong>de</strong>larea principiilor <strong>de</strong> proiectare ale limbajelor orientate-obiect<br />

concurente<br />

În cadrul capitolului prece<strong>de</strong>nt am <strong>de</strong>terminat o multime <strong>de</strong> patru principii <strong>de</strong><br />

<strong>proiectarea</strong> ale limbajelor <strong>de</strong> programare orientate-obiect concurente. Aceste patru<br />

principii sunt:<br />

- principiul expre<strong>si</strong>bilitatii <strong>concurentei</strong>, care se refera la:<br />

- concurenta intra-obiect,<br />

- executie <strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> stare,<br />

- executie <strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> istoric,<br />

- principiul codului <strong>de</strong> interactiune orientat pe obiectul apelat,<br />

82


- principiul izolarii codului <strong>de</strong> <strong>si</strong>ncronizare concurenta,<br />

- principiul separarii codului <strong>de</strong> <strong>si</strong>ncronizare concurenta.<br />

Principiile <strong>de</strong> mai sus trebuie sa fie respectate <strong>de</strong> catre mecanismele <strong>de</strong><br />

coordonare a <strong>concurentei</strong> <strong>în</strong>tr-un context orientat-obiect astfel <strong>în</strong>cât avantajele<br />

caracteristice programarii concurente sau ale programarii orientate obiect sa nu se<br />

reduca sau chiar anuleze. Principiile au fost <strong>de</strong>terminate pe baza unor studii informale<br />

privind programarea orientata-obiect <strong>si</strong> programarea concurenta. Am aratat <strong>în</strong>sa ca<br />

nici unul dintre limbajele <strong>de</strong> programare orientate-obiect concurente <strong>de</strong>zvoltate pâna<br />

<strong>în</strong> prezent nu respecta toate aceste principii.<br />

Sistemul formal prezentat <strong>în</strong> sectiunea anterioara este potrivit pentru<br />

mo<strong>de</strong>larea tuturor acestor principii. Mai mult, el are la baza respectarea primului<br />

principiu enuntat, <strong>si</strong> anume acela al localizarii codului <strong>de</strong> gestiune a interactiunilor<br />

<strong>în</strong>tre activitati concurente la nivelul obiectului activ apelat.<br />

Executia <strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> stare <strong>si</strong> cea <strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> istoric au fost <strong>de</strong> asemenea<br />

mo<strong>de</strong>late prin intermediul <strong>de</strong>finitiei 8. Aceasta introduce o notiune particulara <strong>de</strong> tip<br />

prin mo<strong>de</strong>larea comportamentului instantelor claselor concurente având la baza<br />

<strong>si</strong>stemul <strong>de</strong> domenii <strong>si</strong> operatii semantice prezentat <strong>în</strong> figura 3.7. Definitia 8 sta la<br />

baza extin<strong>de</strong>rii unui formalism vizual <strong>de</strong> mo<strong>de</strong>lare a comportamentului obiectelor<br />

active <strong>si</strong> care va fi prezentat <strong>în</strong> cadrul capitolului urmator.<br />

Mo<strong>de</strong>larea <strong>concurentei</strong> interne se realizeaza prin rafinarea multimii <strong>de</strong> mesaje<br />

Key. Vom nota aceasta multime cu Keyintra <strong>si</strong> ea nu va contine doar o multime<br />

<strong>si</strong>mpla <strong>de</strong> <strong>si</strong>gnaturi <strong>de</strong> mesaje, ci pentru fiecare m ? Key, Keyintra va contine o<br />

pereche ms - msf, un<strong>de</strong> ms reprezinta inceputul invocarii mesajului m, iar msf sfâr<strong>si</strong>tul<br />

acestei invocari. Pentru mo<strong>de</strong>larea <strong>concurentei</strong> interne <strong>de</strong>finitia anomaliei <strong>de</strong><br />

mostenire <strong>si</strong> taxonomia anomaliilor <strong>de</strong>finite <strong>în</strong> sectiune prece<strong>de</strong>nta pot fi usor<br />

generalizate, prin introducerea <strong>de</strong> noi operatii semantice behintra, becintra, stateintra <strong>si</strong><br />

State<strong>si</strong>ntra (figura 3.9).<br />

83


eh intra : Instance ? ? (Key intra * )\Inv<br />

Semantici <strong>de</strong> urma:<br />

bec intra : Class ? ? (Key intra * )\Inv, becintra(P) = p{ beh intra(p) : p ?<br />

state intra<br />

Semantici <strong>de</strong> stari<br />

: ? (Key intra * )\Inv ? Keyintra * ? ? (Keyintra * )\Inv<br />

stateintra(?)u = ?<br />

? ? { z : u^<br />

z ? ? }, daca u ?<br />

? , in rest<br />

States intra<br />

: ? (Key intra * )\Inv ? ? (? (Keyintra * )\Inv)<br />

States intra(?) = { state intra(?)u : u ? ? }<br />

Figura 3.9. Multimi <strong>si</strong> functii semantice <strong>de</strong> surprin<strong>de</strong>re a <strong>concurentei</strong> interne<br />

Daca beh reprezenta multimea tuturor secventelor <strong>de</strong> mesaje care pot fi<br />

acceptate <strong>de</strong> catre o instanta, behintra va avea o <strong>de</strong>finitie <strong>si</strong>milara, <strong>în</strong>sa trebuie avuta <strong>în</strong><br />

ve<strong>de</strong>re exclu<strong>de</strong>rea secventele incon<strong>si</strong>stente <strong>de</strong> mesaje (prin care terminarea invocarii<br />

unui mesaje prece<strong>de</strong> startul acesteia). Multimea Inv, pe care o vom numi multime <strong>de</strong><br />

inver<strong>si</strong>uni, este multimea care contine toate aceste secvente. Pentru a caracteriza<br />

aceasta multime vom <strong>de</strong>fini functia:<br />

nr : Keyintra* ? Keyintra ? ,<br />

un<strong>de</strong> nr(, m) reprezinta numarul <strong>de</strong> aparitii al mesajului m <strong>în</strong> secventa<br />

<strong>de</strong> mesaje . Prin urmare multimea Inv poate fi <strong>de</strong>finita astfel:<br />

Inv = {, ? i ? n, ? ms, msf ? Keyintra a.î.<br />

nr(, ms) < nr(, msf)},<br />

adica multime Inv reprezinta multimea tuturor secventelor <strong>de</strong> mesaje pentru care<br />

exista cel putin un mesaj din Keyintra <strong>si</strong> cel putin o subsecventa <strong>în</strong> care numarul <strong>de</strong><br />

aparitii al startului invocarii mesajului este mai mic <strong>de</strong>cât numarul <strong>de</strong> aparitii a<br />

terminarii invocarii mesajului.<br />

<strong>în</strong> relatia:<br />

84<br />

?<br />

Definitie 11. Multimile <strong>de</strong> secvente <strong>de</strong> mesaje ?, ? ? ? (Keyintra * )\Inv se afla<br />

? Tintra ?<br />

daca <strong>si</strong> numai daca ? ? ? <strong>si</strong> ? u ? ?, u = v^z un<strong>de</strong> v ? ? iar z0 (daca exista) nu apare<br />

niciodata <strong>în</strong> ?. Multimea nevida <strong>de</strong> instante ? este un alement al TypesTintra daca <strong>si</strong>


numai daca ? p ? ?, pbehintra? T behintra(p). Mai mult, daca q ? Instance astfel <strong>în</strong>cât<br />

pbehintra? T behintra(q), atunci q ? ?.<br />

Definitia 11 introduce notiunea <strong>de</strong> tip TypesTintra. Aceasta reprezinta o<br />

generalizare a notiunii <strong>de</strong> tip TypesT <strong>si</strong>, prin urmare, ea induce o multime <strong>de</strong> anomalii<br />

<strong>de</strong> mostenire care inclu<strong>de</strong> anomaliile <strong>de</strong> mostenire induse <strong>de</strong> TypesT. Deci, prezenta<br />

<strong>concurentei</strong> intra-obiect nu conduce la ameliorarea anomaliilor <strong>de</strong> mostenire, ci<br />

dimpotriva poate induce anomalii <strong>de</strong> mostenire noi.<br />

Daca principiul expre<strong>si</strong>bilitatii <strong>concurentei</strong> este strict legat <strong>de</strong> puterea <strong>de</strong><br />

specificarea a <strong>concurentei</strong> la nivelul obiectelor active, celelalte trei principii au <strong>în</strong><br />

ve<strong>de</strong>re respectarea proprietatilor mecanismelor specifice programarii orientate-obiect.<br />

Prin urmare respectarea acestor principii poate influenta <strong>si</strong> efectul anomaliilor <strong>de</strong><br />

mostenire. Definitia urmatoare formalizeaza principiile izolarii <strong>si</strong> separarii codului <strong>de</strong><br />

specificare a interactiunilor <strong>în</strong>tre activitati concurente <strong>de</strong> codul care implementeaza<br />

functionalitatea unui obiect activ. Acest lucru poate fi surprins prin <strong>în</strong>locuirea<br />

multimii Key cu multimea Keyc care va contine pentru fiecare mesaj m ? Key o<br />

pereche m f , m c , un<strong>de</strong> methods(m f ) reprezinta codul care implementeaza<br />

functionalitatea mesajului m, iar methods(m c ) reprezinta codul <strong>de</strong> <strong>si</strong>ncronizare.<br />

f c f c<br />

Definitie 12. Daca M(P) = M(Q) = { m m , m , m ,... } <strong>si</strong> ?<br />

85<br />

1 , 1 2 2<br />

c<br />

m i ? Keyc*<br />

methods(P) m = methods(Q) m , spunem ca limbajul respecta principiile izolarii <strong>si</strong><br />

c<br />

i<br />

c<br />

i<br />

separarii codului <strong>de</strong> interactiune concurenta daca <strong>si</strong> numai daca oricare ar fi P <strong>si</strong> Q<br />

avem imp(P) = imp(Q).<br />

Propozitie 9. Fie un limbaj <strong>de</strong> programare orientat-obiect concurent care<br />

respecta principiile izolarii <strong>si</strong> separarii codului <strong>de</strong> interactiune concurenta relativ la<br />

<strong>de</strong>finitia <strong>de</strong> tip TypesT. Pentru un astfel <strong>de</strong> limbaj o anomalie <strong>de</strong> mostenire nu nece<strong>si</strong>ta<br />

re<strong>de</strong>finirea partii functionale a operatiilor.<br />

Demonstratie. Fie clasele P <strong>si</strong> Q pentru care presupunem ca are loc relatia<br />

impT(Q) ? impT(P).<br />

Deoarece are loc o anomalie <strong>de</strong> mostenire rezulta ca<br />

? ?? ? *, R ? Class astfel <strong>în</strong>cât P ? ? ? I R<br />

?<br />

<strong>si</strong> impT(R) = impT(Q).<br />

f c f c f<br />

Fie M(P) = { m m , m , m ,..., m , m<br />

c<br />

f c f c<br />

1 , 1 2 2 n n } <strong>si</strong> M(Q) = { 1 , m1<br />

,..., mn<br />

, mn<br />

,...<br />

m }.<br />

Vom contrui clasa R astfel <strong>în</strong>cât ea sa fie i<strong>de</strong>ntica cu Q mai putin operatiile pentru<br />

care are loc methods(R) m = methods(P) m , un<strong>de</strong> 1 ? i ? n. Pe baza <strong>de</strong>finitiei 12<br />

f<br />

i<br />

f<br />

i


vom avea ca impT(R) = impT(Q). Însa, prin constructie, clasa R nu re<strong>de</strong>fineste cod<br />

functional din P. Prin urmare anomalia <strong>de</strong> mostenire are loc doar la nivelul codului<br />

<strong>de</strong> <strong>de</strong>scriere a constrângerilor <strong>de</strong> <strong>si</strong>ncronizare. ?<br />

Propozitia 9 <strong>de</strong>monstreaza faptul ca specificarea <strong>si</strong> mostenirea separata a<br />

codului <strong>de</strong> <strong>implementare</strong> a constrângerilor <strong>de</strong> <strong>si</strong>ncronizare conduce la ameliorarea<br />

anomaliilor <strong>de</strong> mostenire prin directionarea efectului acesteia doar asupra operatiilor<br />

care implementeaza acest cod. Prin urmare codul <strong>de</strong> <strong>de</strong>scriere a functionalitatii<br />

obiectelor active nu nece<strong>si</strong>ta rescriere. Limbajele <strong>de</strong> programare care implementeaza<br />

o notiune <strong>de</strong> tip TypesT <strong>si</strong> respecta <strong>în</strong>tocmai conditiile <strong>de</strong>finitiei 12 sunt limbajele cu<br />

mecanisme <strong>de</strong> <strong>si</strong>ncronizare cu control reflectiv. Limbajele cu mecanisme <strong>de</strong><br />

<strong>si</strong>ncronizare cu control mixt ofera <strong>în</strong> general suport pentru respectarea <strong>de</strong>finitie 12,<br />

<strong>în</strong>sa ele nu garanteaza respectarea acesteia (<strong>de</strong>finitia 12 poate fi respectata doar<br />

urmând o anumita disciplina <strong>de</strong> programare).<br />

3.5. Concluzii<br />

Rezultatele formalizarii anomaliilor <strong>de</strong> mostenire din sectiunea 3.3.<br />

<strong>de</strong>mostreaza faptul ca nu exista un mo<strong>de</strong>l obiect i<strong>de</strong>al, <strong>în</strong> care sa nu fie prezente<br />

anomalii <strong>de</strong> reutilizare. Efectul acestor anomalii poate fii <strong>în</strong>sa ameliorat.<br />

Respectarea principiile enuntate <strong>în</strong> cadrul capitolului doi <strong>si</strong> mo<strong>de</strong>late formal <strong>în</strong><br />

cadrul acestui capitol conduc la o astfel <strong>de</strong> ameliorare. Din acest punct <strong>de</strong> ve<strong>de</strong>re<br />

principiul separarii codului <strong>de</strong> interactiune concurenta este cel mai important. Astfel<br />

partea care tine exclu<strong>si</strong>v <strong>de</strong> concurenta va putea fi reutilizata separat <strong>de</strong> partea care<br />

<strong>de</strong>scrie functionalitatea. Deoarece separarea acestor notiuni duce la cresterea<br />

po<strong>si</strong>bilitatii <strong>de</strong> reutilizare, am <strong>analiza</strong>t modul <strong>în</strong> care aceasta conduce la reducerea<br />

efectelor anomaliilor <strong>de</strong> mostenire. Trebuie specificat faptul ca nimic nu constrânge<br />

programatorul <strong>în</strong> a nu amesteca codul corespunzator functionalitatii cu cel pentru<br />

<strong>de</strong>scrierea constrângerilor <strong>de</strong> <strong>si</strong>ncronizare. De exemplu, <strong>în</strong> cazul utilizarii<br />

mecanismului <strong>de</strong> meto<strong>de</strong> cu garzi, datorita faptului ca garzile au acces la proprietatile<br />

obiectelor ele <strong>de</strong>pind <strong>în</strong> general <strong>de</strong> <strong>de</strong>taliile <strong>de</strong> <strong>implementare</strong> ale operatiilor. Prin<br />

urmare, re<strong>implementare</strong>a unei operatii poate conduce <strong>si</strong> la re<strong>implementare</strong>a codului<br />

<strong>de</strong> <strong>si</strong>ncronizare. Reciproca este <strong>de</strong> asemenea a<strong>de</strong>varata.<br />

86


Teorema 1 afirma faptul ca daca exista un mecanism <strong>de</strong> mostenire fara<br />

anomalii atunci el nu va conserva comportamentul. Prin urmare, o alta po<strong>si</strong>bila<br />

abordare <strong>de</strong> ameliorare a anomaliilor <strong>de</strong> mostenire este aceea <strong>de</strong> a introduce un astfel<br />

<strong>de</strong> mecanism. Astfel, adaugarea <strong>de</strong> noi operatiie <strong>în</strong> cadrul unei clase nu va conduce <strong>în</strong><br />

mod necesar la crearea <strong>de</strong> subtipuri ale tipului initial. Mecanismele fara conservare a<br />

comportamentului sunt mult mai expre<strong>si</strong>ve <strong>de</strong>cât cele cu conservare a<br />

comportamentului, <strong>si</strong> sunt capabile sa trateze mai multe anomalii <strong>de</strong> mostenire. În<br />

literatura <strong>în</strong>sa sunt foarte putine propuneri <strong>de</strong> astfel <strong>de</strong> mecanisme, <strong>de</strong>oarece ele<br />

implica o multime <strong>de</strong> probleme cum ar fi negarantarea relatiei <strong>de</strong> subtipizare sau<br />

nece<strong>si</strong>tatea unor studii <strong>în</strong> directia tehnicilor <strong>de</strong> <strong>analiza</strong> statica <strong>si</strong> a tehnicilor <strong>de</strong><br />

optimizare <strong>în</strong> ve<strong>de</strong>rea eficientizarii programelor.<br />

O a treia abordare <strong>de</strong> reducere a anomaliilor consta <strong>în</strong> construirea <strong>de</strong> biblioteci<br />

<strong>de</strong> politici generice <strong>de</strong> <strong>si</strong>ncronizare <strong>si</strong> concurenta, <strong>si</strong> ea este <strong>de</strong>rivata din principiul<br />

separarii codului <strong>de</strong> interactiune concurenta. Astfel, <strong>în</strong> locul mostenirii partii <strong>de</strong><br />

specificare <strong>si</strong> coordonare a <strong>concurentei</strong> dintr-o superclasa, o subclasa va avea<br />

po<strong>si</strong>bilitatea instantierii unei politici particulare. Aceasta abordare este utila <strong>în</strong> special<br />

<strong>în</strong> cazul specificarii <strong>concurentei</strong> interne, un<strong>de</strong> exista un numar relativ restrâns <strong>de</strong><br />

politici utilizate (cum ar fi cititori/scriitor, prioritatea cititorilor etc).<br />

În alta ordine <strong>de</strong> i<strong>de</strong>i, faptul ca un mo<strong>de</strong>l obiect este "predispus" la anomalii <strong>de</strong><br />

reutilizare nu implica automat i<strong>de</strong>ea ca aceste anomalii nu vor putea fi evitate. S-a<br />

aratat <strong>în</strong> <strong>de</strong>se rânduri, <strong>în</strong> studiul primitivelor <strong>de</strong> interactiune concurenta, faptul ca<br />

urmarea unei discipline <strong>de</strong> programare poate oferii beneficii pe care <strong>analiza</strong> teoretica a<br />

unui limbaj nu le releva. Prin urmare o alta solutie <strong>de</strong> eliminare a efectului<br />

anomaliilor l-ar putea reprezinta generarea automata <strong>de</strong> cod pe baza unor mo<strong>de</strong>le <strong>de</strong><br />

structura <strong>si</strong> comportament ale obiectelor active.<br />

Instrumentele CASE (Computer Ai<strong>de</strong>d Software Engineering) sunt utilizate tot<br />

mai <strong>de</strong>s <strong>în</strong> <strong>de</strong>zvoltarea <strong>de</strong> <strong>si</strong>steme informatice, datorita multiplelor avantaje pe care le<br />

implica: <strong>în</strong>telegerea mai profunda a specificatiilor, <strong>în</strong>curajarea reutilizabilitatii,<br />

a<strong>si</strong>gurarea corectitudinii codului (pentru codul generat automat), suport pentru lucru<br />

<strong>în</strong> echipa etc ([BOZ94a], [CHI96], [CHi97], [SUC96a], [SUC96b]). Prin urmare, pe<br />

lânga toate aceste avantaje, utilizarea intrumentelor CASE poate <strong>de</strong>termina sca<strong>de</strong>re<br />

procentului <strong>de</strong> anomalii <strong>de</strong> mostenire <strong>în</strong> <strong>de</strong>zvoltarea <strong>de</strong> aplicatii orientate-obiect<br />

concurente.<br />

87


Formalizarea anomaliilor <strong>de</strong> mostenire prin intermediul comportamentului<br />

extern observabil implica o maniera generala <strong>si</strong> eleganta <strong>de</strong> abordare a mo<strong>de</strong>larii<br />

aplicatiilor orientate-obiect concurente. Gradul <strong>de</strong> generalitate al acestora face<br />

po<strong>si</strong>bila <strong>de</strong>zvoltarea <strong>de</strong> mo<strong>de</strong>le a caror <strong>implementare</strong>a se poate realiza <strong>în</strong>tr-o gama<br />

foarte variata <strong>de</strong> limbaje <strong>de</strong> programare. Pe baza acestor argumente <strong>în</strong> cadrul<br />

capitolului patru vom specifica un formalism vizual <strong>de</strong> mo<strong>de</strong>lare a comportamentului<br />

obiectelor active, având ca fundament formalismul hartilor <strong>de</strong> stari.<br />

88


4. Mo<strong>de</strong>larea comportamentului obiectelor active<br />

4.1. Introducere<br />

În cadrul acestui capitol propunem un formalism <strong>de</strong> mo<strong>de</strong>lare a<br />

comportamentului obiectelor active. Acest formalism reprezinta o exten<strong>si</strong>e a<br />

formalismului vizual al hartilor <strong>de</strong> stari ([HAR87]).<br />

În sectiunea a doua vom justifica alegerea hartilor <strong>de</strong> stari ca formalism <strong>de</strong><br />

baza, prin tratarea obiectelor active ca <strong>si</strong> <strong>si</strong>steme reactive.<br />

În cadrul sectiunii a treia, vom <strong>de</strong>scrie formalismul hartilor <strong>de</strong> stari care<br />

<strong>în</strong>globeaza o serie <strong>de</strong> exten<strong>si</strong>i ale ma<strong>si</strong>nilor cu stari finite <strong>si</strong> care a fost utilizat (cu<br />

unele modificari) <strong>în</strong> majoritatea meto<strong>de</strong>lor <strong>si</strong> tehnicilor <strong>de</strong> <strong>analiza</strong> orientata - obiect a<br />

aplicatiilor (OMT [RUM91], Syntropy [COO94], UML [OMG99] etc.) pentru<br />

<strong>de</strong>scrierea comportamentului obiectelor, chiar daca <strong>în</strong> momentul <strong>de</strong>zvoltarii lor hartile<br />

<strong>de</strong> stari nu au fost asociate cu paradigma orientata-obiect.<br />

Asa cum vom arata <strong>în</strong> sectiunea a patra, hartile <strong>de</strong> stari sau diferite exten<strong>si</strong>i ale<br />

acestora au fost utilizate cu predilectie pentru mo<strong>de</strong>larea comportamentului obiectelor<br />

dintr-o anumita clasa. Multe dintre aceste metodologii <strong>în</strong>sa nu reusesc sa <strong>de</strong>fineasca<br />

<strong>în</strong> mod riguros semanticile limbajului propus. Este <strong>si</strong> cazul limbajului <strong>de</strong> mo<strong>de</strong>lare<br />

UML, care <strong>de</strong><strong>si</strong> <strong>de</strong>venit limbajul standard utilizat <strong>în</strong> <strong>analiza</strong> <strong>si</strong> <strong>proiectarea</strong> aplicatiilor<br />

orientate-obiect, contine o seama <strong>de</strong> elemente ambigue, vag specificate, sau chiar<br />

contradictorii. În ceea ce priveste varianta diagramelor <strong>de</strong> tranzitie a starii propusa <strong>de</strong><br />

UML, am realizat <strong>în</strong> cadrul sectiunii a patra o <strong>analiza</strong> critica a acesor tipuri <strong>de</strong><br />

elemente.<br />

89


În scopul <strong>de</strong>zvoltarii unui formalism care sa permita realizarea <strong>de</strong> mo<strong>de</strong>le<br />

executabile (care permit translatarea automata <strong>în</strong> cod sursa), am <strong>de</strong>finit <strong>în</strong> sectiunea a<br />

cincea o exten<strong>si</strong>e a hartilor <strong>de</strong> stari <strong>de</strong>finite <strong>în</strong> UML, numita harta <strong>de</strong> stari scalabila.<br />

Definirea semanticilor acestei variante este precedata <strong>de</strong> <strong>de</strong>finirea unui mo<strong>de</strong>l obiect<br />

suficient <strong>de</strong> general, care este caracteristic tuturor limbajelor <strong>de</strong> programare care<br />

implementeaza primitive <strong>de</strong> interactiune <strong>în</strong>tre activitati concurente bazate pe<br />

<strong>în</strong>capsulare.<br />

4.2. Sisteme reactive<br />

În <strong>analiza</strong> <strong>si</strong>stemelor <strong>de</strong> calcul exista o dihotomie fundamentala care<br />

tranziteaza frontierele dintre <strong>si</strong>stemele secventiale sau paralele, centrale sau<br />

distribuite, imperative sau functionale. Aceasta dihotomie este <strong>în</strong>tre <strong>si</strong>stemele<br />

transformationale <strong>si</strong> cele reactive.<br />

Sistemele tranformationale sunt acele <strong>si</strong>steme care pot fi <strong>de</strong>scrise prin<br />

intermediul unei relatii <strong>în</strong>tre valorile <strong>de</strong> intrare <strong>si</strong> <strong>de</strong> ie<strong>si</strong>re ale acestora. Aceste<br />

<strong>si</strong>steme primesc anumite valori sau semnale <strong>de</strong> intrare pe baza carora vor produce, <strong>în</strong><br />

mod <strong>de</strong>terminist sau nu, valori <strong>de</strong> ie<strong>si</strong>re sau reactii, dupa care executia lor ia sfâr<strong>si</strong>t.<br />

Valorile sau semnalele <strong>de</strong> intrare sunt complet cunoscute <strong>de</strong> catre <strong>si</strong>stem <strong>în</strong> momentul<br />

invocarii sale, iar producerea rezultatelor nece<strong>si</strong>ta o anumita perioada <strong>de</strong> calcul.<br />

Sistemele transformationale au o structura liniara, iar <strong>si</strong>ngurele stari care au relevanta<br />

pentru <strong>de</strong>scrierea acestora sunt starile initiale <strong>si</strong> cele finale (figura 4.1).<br />

SISTEM<br />

TRANSFORMATIONAL<br />

intrari (date) ie<strong>si</strong>ri (rezultate)<br />

90<br />

timp<br />

Figura 4.1. Schema <strong>de</strong> functionare a unui <strong>si</strong>stem transformational<br />

Sistemele <strong>de</strong> achizitie a datelor, <strong>si</strong>stemele <strong>de</strong> compre<strong>si</strong>a a vocii sau procedurile<br />

<strong>si</strong>mple <strong>de</strong> calcul a radicalului sau logaritmului unui numar reprezinta exemple <strong>de</strong><br />

<strong>si</strong>steme transformationale.<br />

Spre <strong>de</strong>osebire <strong>de</strong> <strong>si</strong>stemele tranformationale, <strong>si</strong>temele reactive se<br />

caracterizeaza prin faptul ca interactioneaza continuu cu mediul din care fac parte


(figura 4.2). Aproape toate <strong>si</strong>stemele contin cel putin un sub<strong>si</strong>stem reactiv, <strong>de</strong>oarece<br />

rareori un <strong>si</strong>stem este izolat <strong>de</strong> mediul <strong>în</strong> care activeaza.<br />

SISTEM<br />

REACTIV<br />

91<br />

timp<br />

Figura 4.2. Reprezentarea schematica a unui <strong>si</strong>stem reactiv<br />

<strong>si</strong> a canalelor sale <strong>de</strong> interactiune cu mediul <strong>în</strong>conjurator<br />

Unul dintre cele mai reprezentative exemple <strong>de</strong> <strong>si</strong>steme reactive este <strong>si</strong>stemul<br />

<strong>de</strong> control al luminii <strong>de</strong> trafic. Acest <strong>si</strong>stem nu va avea niciodata intrarile pregatite,<br />

ele so<strong>si</strong>nd <strong>în</strong> secvente infinite <strong>si</strong> ne<strong>de</strong>terminate. Este impo<strong>si</strong>bil <strong>de</strong> proiectat un <strong>si</strong>stem<br />

transformational pentru un astfel <strong>de</strong> control. De fapt, majoritatea <strong>si</strong>stemelor <strong>de</strong><br />

control sunt reactive <strong>si</strong> nu transformationale. De asemenea, ceasurile digitale,<br />

circuitele integrate sau <strong>si</strong>stemele program interactive reprezinta la rândul lor exemple<br />

comune <strong>de</strong> <strong>si</strong>steme reactive.<br />

Deoarece au fost obtinute rezultate notabile <strong>în</strong> formalizarea <strong>si</strong>stemelor<br />

tranformationale, s-a <strong>în</strong>cercat specificarea <strong>si</strong>stemelor reactive prin intermediul<br />

acestora, prin gruparea tuturor canalelor <strong>de</strong> intrare <strong>si</strong> <strong>de</strong> ie<strong>si</strong>re <strong>în</strong> secvente <strong>de</strong> intrare<br />

respectiv <strong>de</strong> ie<strong>si</strong>re. Deoarece comportamentul mediului (caracterizat <strong>de</strong> intrarile<br />

transmise <strong>si</strong>stemului) <strong>de</strong>pind <strong>de</strong> reactiile anterioare ale <strong>si</strong>stemului, o astfel <strong>de</strong> abordare<br />

s-a dovedit a fi nesatisfacatoare. Prin urmare, o relatie <strong>în</strong>tre secventele <strong>de</strong> intrare <strong>si</strong><br />

cele <strong>de</strong> ie<strong>si</strong>re nu este suficienta pentru a <strong>de</strong>scrie un <strong>si</strong>stem reactiv. Acest fenomen este<br />

cunoscut <strong>în</strong> literatura ca paradoxul Brock-Ackermann [BRO81] <strong>si</strong> a fost <strong>de</strong>scris<br />

pentru prima data prin intermediul retelelor <strong>de</strong> fluxuri <strong>de</strong> date. Astfel, pentru o<br />

<strong>de</strong>scriere corecta a unui <strong>si</strong>stem reactiv, alaturi <strong>de</strong> secventele <strong>de</strong> intrare <strong>si</strong> <strong>de</strong> ie<strong>si</strong>re mai<br />

trebuie cunoscute momentele <strong>în</strong> care rezultatele sunt produse. O astfel <strong>de</strong> informatie<br />

presupune inclu<strong>de</strong>rea unei <strong>de</strong>scrieri temporale a evenimentelor <strong>de</strong> intrare <strong>si</strong> ie<strong>si</strong>re sau<br />

o <strong>de</strong>scrierea unei notini mai abstracte <strong>de</strong> timp (<strong>în</strong> cazul <strong>în</strong> care ordinea evenimentelor<br />

<strong>de</strong> ie<strong>si</strong>re este specificata relativ la evenimentele <strong>de</strong> intrare).<br />

Într-un <strong>si</strong>stem reactiv, momentul <strong>în</strong> care o noua valoare <strong>de</strong> intrare este<br />

receptionata este relevant pentru comportamentul sau. Cu alte cuvinte, starea interna<br />

a <strong>si</strong>stemului la receptionarea intrarii este importanta pentru modul <strong>în</strong> care acesta va<br />

reactiona <strong>în</strong> continuare. Prin urmare este necesara acordarea unei atentii sporite


starilor intermediare. Ele nu reprezinta doar puncte <strong>si</strong>mple <strong>în</strong> calea atingerii starii<br />

finale, ci au un <strong>în</strong>teles propriu. Mai mult, <strong>în</strong>tr-un numar con<strong>si</strong><strong>de</strong>rabil <strong>de</strong> <strong>si</strong>steme<br />

reactive nu exista stare finala.<br />

Asa cum am aratat <strong>si</strong> <strong>în</strong> capitolul prece<strong>de</strong>nt <strong>în</strong> cadrul analizei anomaliilor <strong>de</strong><br />

mostenire, obiectele active se <strong>de</strong>osebesc <strong>de</strong> cele pa<strong>si</strong>ve prin faptul ca au un fir <strong>de</strong><br />

executie propriu. În plus, <strong>în</strong> orice moment <strong>de</strong> timp exista o submultime <strong>de</strong> meto<strong>de</strong><br />

acceptabile <strong>în</strong> functie <strong>de</strong> starea interna a obiectului. Acceptarea unei cereri <strong>de</strong> lansare<br />

<strong>în</strong> executie a unei operatii din aceasta submultime <strong>de</strong>termina modificarea sa.<br />

Comportamentul unui obiect activ a fost mo<strong>de</strong>lat formal prin intermediul unor<br />

secvente <strong>de</strong> mesaje (<strong>de</strong>finite prin invocari <strong>de</strong> operatii). Acceptarea unui mesaj este<br />

strâns legata <strong>de</strong> multimea mesajelor acceptate anterior. Bine<strong>în</strong>teles, acceptabilitatea<br />

unui mesaj este data <strong>în</strong> ultima instanta <strong>de</strong> starea obiectului activ la un moment dat,<br />

stare care a fost <strong>de</strong>finita <strong>în</strong> capitolul 2 ca fiind caracterizata <strong>de</strong> multimea valorilor<br />

proprietatilor.<br />

Prin urmare tratarea obiectelor active ca <strong>si</strong> <strong>si</strong>steme reactive reprezinta o<br />

abordare naturala. Pentru mo<strong>de</strong>larea comportamentului unui obiect activ pot fi<br />

utilizate formalismele studiate <strong>în</strong> literatura relativ la mo<strong>de</strong>larea <strong>si</strong>stemelor reactive. În<br />

ultimii zece ani a fost <strong>de</strong>zvoltata o multime con<strong>si</strong>stenta <strong>de</strong> meto<strong>de</strong> <strong>de</strong> <strong>analiza</strong> <strong>si</strong><br />

proiectare care au utilizat astfel <strong>de</strong> formalisme <strong>în</strong> special pentru mo<strong>de</strong>larea aplicatiilor<br />

orientate-obiect secventiale.<br />

Introducerea <strong>concurentei</strong> <strong>în</strong>sa implica o recon<strong>si</strong><strong>de</strong>rare a semanticii<br />

formalismelor vizuale, <strong>în</strong> special a celor utilizate pentru <strong>de</strong>scrierea comportamentului<br />

obiectelor. Mo<strong>de</strong>lele obiect concurente eficiente din punct <strong>de</strong> ve<strong>de</strong>re al respectarii<br />

principiilor prezentate <strong>în</strong> capitolul 2, presupun existenta la nivelul obiectelor active a<br />

unor mecanisme <strong>de</strong> gestionare a invocarilor <strong>de</strong> operatii, a unor cozi <strong>de</strong> asteptare <strong>si</strong>/sau<br />

a unor porturi <strong>de</strong> comunicare <strong>în</strong>tre obiectele active. Toate aceste caracteristici nu sunt<br />

surprinse <strong>în</strong> mo<strong>de</strong>lele meto<strong>de</strong>lor <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare ale aplicatiilor orientate-<br />

obiect existente.<br />

92


4.3. Harti <strong>de</strong> stari<br />

Exista diverse abordari <strong>de</strong> mo<strong>de</strong>lare a comportamentului dinamic al obiectelor<br />

(comportament privit prin prisma relatiilor cauzale dintre actiuni). Practic toate<br />

abordarile se bazeaza <strong>în</strong>tr-un anumit fel pe ma<strong>si</strong>nile cu stari finite, care <strong>de</strong>scriu o<br />

multime <strong>de</strong> stari <strong>în</strong> care se poate afla un <strong>si</strong>stem la un moment dat <strong>si</strong> tranzitiile po<strong>si</strong>bile<br />

<strong>în</strong>tre aceste stari. Pentru fiecare stare, reactiile po<strong>si</strong>bile la intrarile so<strong>si</strong>te <strong>în</strong> momentul<br />

<strong>în</strong> care <strong>si</strong>stemul se afla <strong>în</strong> starea respectiva sunt specificate prin intermediul<br />

tranzitiilor spre alte stari. A fost <strong>de</strong>zvoltat un formalism grafic potrivit pentru<br />

reprezentarea ma<strong>si</strong>nilor cu stari finite, numit diagrama <strong>de</strong> stari. Diagrama <strong>de</strong> stari<br />

traditionala ofera o imagine clara <strong>si</strong> intuitiva a acestui comportament.<br />

4.3.1. Structura hartilor <strong>de</strong> stari<br />

Un element esential al diagramei îl constituie, bine<strong>în</strong>teles, starea <strong>si</strong>stemului la<br />

un moment dat, reprezentata grafic cu ajutorul unui dreptunghi cu colturile rotunjite.<br />

Un al doilea element este tranzitia <strong>în</strong>tre starile unui <strong>si</strong>stem. Ea se reprezinta grafic cu<br />

ajutorul unui arc <strong>de</strong> cerc sau segmente <strong>de</strong> dreapta orientate <strong>si</strong> etichetate care leaga<br />

doua stari. Eticheta unei tranzitii este formata dintr-un nume <strong>de</strong> eveniment urmat<br />

optional <strong>de</strong> o conditie logica. Semantica tranzitiei dintre starea A <strong>si</strong> C prezentata <strong>în</strong><br />

figura 4.3 este urmatoarea: "daca <strong>si</strong>stemul se afla <strong>în</strong> starea A, aparitia unui eveniment<br />

e1 va afea ca efect trecerea <strong>si</strong>stemului <strong>în</strong> starea C <strong>în</strong> cazul <strong>în</strong> care conditia c1 este<br />

verificata".<br />

Figura 4.3. Exemplu <strong>de</strong> ma<strong>si</strong>na cu trei stari <strong>si</strong> tre i tranzitii <strong>în</strong>tre acestea<br />

a caror <strong>de</strong>clansare <strong>de</strong>pin<strong>de</strong> <strong>de</strong> aparitia a doua evenimente<br />

Ma<strong>si</strong>nile cu stari finite traditionale produc <strong>în</strong>sa un <strong>si</strong>ngur rezultat, <strong>si</strong> anume<br />

semnalul produs <strong>în</strong> momentul atingerii starii finale. Exita doua exten<strong>si</strong>i distincte ale<br />

ma<strong>si</strong>nilor <strong>de</strong> stari <strong>în</strong> functie <strong>de</strong> modul <strong>de</strong> tratare a actiunilor:<br />

- mo<strong>de</strong>lul Moore, <strong>în</strong> care actiunile sunt atasate la intrarea <strong>în</strong>tr-o noua stare,<br />

- mo<strong>de</strong>lul Mealy, <strong>în</strong> care actiunile sunt asociate tranzitiilor.<br />

93


De notat ca ma<strong>si</strong>nile cu stari finite <strong>de</strong>finesc relatiile cauzale dintre evenimente<br />

succe<strong>si</strong>ve, ceea ce nu reprezinta acela<strong>si</strong> lucru cu <strong>de</strong>scrierea constrângerilor <strong>de</strong><br />

<strong>si</strong>ncronizare <strong>în</strong>tre actiuni.<br />

Hartile <strong>de</strong> stari [HAR87] reprezinta o exten<strong>si</strong>e a formalismelor mo<strong>de</strong>lelor<br />

Moore <strong>si</strong> Mealy. Acestea au fost introduse pentru prima data <strong>în</strong>tr-un mediu <strong>de</strong><br />

programare <strong>în</strong> 1987 <strong>de</strong> catre compania israeliana AdCAD <strong>în</strong> cadrul produsului<br />

STATEMATE. Acest mediu utiliza trei formalisme grafice pentru <strong>de</strong>scrierea unui<br />

<strong>si</strong>stem: harta <strong>de</strong> activitati (<strong>de</strong>scrie <strong>de</strong>scompunerea <strong>si</strong>stemului <strong>în</strong> unitati functionale <strong>si</strong><br />

interfata dintre acestea), harta <strong>de</strong> module (<strong>de</strong>scrie modulele fizice <strong>în</strong> care aceste unitati<br />

functionale sunt implementate <strong>si</strong> canalele <strong>de</strong> comunicare ce le conecteaza) <strong>si</strong> harta <strong>de</strong><br />

stari (utilizata <strong>în</strong> <strong>de</strong>scrierea comportamentului unei unitati functionale) [iLO87].<br />

Formalismul hartilor <strong>de</strong> stari implementat aici a fost adoptat rapid <strong>de</strong> multe alte<br />

instrumente <strong>de</strong> mo<strong>de</strong>lare, <strong>analiza</strong> <strong>si</strong>/sau proiectare <strong>de</strong> <strong>si</strong>steme informatice, suportând o<br />

serie <strong>de</strong> modificari semantice, exten<strong>si</strong>i sau particularizari. În 1996 David Harel<br />

realizeaza o <strong>de</strong>scriere informala con<strong>si</strong>stenta a formalismului STATEMATE [HAR96].<br />

Din punct <strong>de</strong> ve<strong>de</strong>re semantic, hartile <strong>de</strong> stari reprezinta unul dintre cele mai<br />

utile <strong>si</strong> complete formalisme, ele fiind adoptate <strong>în</strong> diverse forme <strong>si</strong> <strong>în</strong> majoritatea<br />

meto<strong>de</strong>lor <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare orientata-obiect (OMT, Booch, OSE, UML,<br />

OPEN/OML, Syntropy) <strong>si</strong> utilizate <strong>în</strong> <strong>de</strong>scrierea comportamentului la nivel <strong>de</strong> clase.<br />

Ele sunt foarte potrivite <strong>în</strong> special pentru <strong>de</strong>scrierea comportamentului <strong>si</strong>stemelor<br />

reactive, <strong>de</strong><strong>si</strong> au existat <strong>în</strong>cercari <strong>de</strong> <strong>de</strong>zvoltare a unor tehnici <strong>de</strong>rivate din diagramele<br />

<strong>de</strong> stari pentru <strong>de</strong>scrierea <strong>si</strong>stemelor transformationale, cum ar fi <strong>proiectarea</strong> <strong>de</strong><br />

organigrame.<br />

Etichetele tranzitiilor <strong>de</strong>scrise <strong>în</strong> cadrul hartilor <strong>de</strong> stari sunt formate din trei<br />

componente optionale distincte:<br />

?? un <strong>de</strong>clansator care <strong>de</strong>termina executarea tranzitiei. Acest <strong>de</strong>clansator este<br />

<strong>de</strong> fapt un eveniment sau o multime <strong>de</strong> evenimente care au loc la un<br />

moment dat <strong>si</strong> care sunt receptionate <strong>de</strong> <strong>si</strong>stem,<br />

?? o conditie logica (garda) care specifica cazurile <strong>în</strong> care tranzitia va fi<br />

realizata atunci când are loc evenimentul din <strong>de</strong>clansator,<br />

?? o actiune care este realizata atunci când tranzitia are loc, <strong>si</strong> care consta <strong>de</strong><br />

fapt <strong>în</strong> generarea unei multimi <strong>de</strong> evenimente.<br />

94


Un element important care a fost introdus <strong>în</strong> hartile <strong>de</strong> stari <strong>si</strong> care nu se<br />

regasea <strong>în</strong> diagramele <strong>de</strong> stari traditionale este cel <strong>de</strong> structura. Lipsa unei modalitati<br />

<strong>de</strong> structurare <strong>si</strong> <strong>de</strong> <strong>în</strong>capsulare a informatiei <strong>de</strong>termina cresterea nejustificata a<br />

dimen<strong>si</strong>unilor <strong>si</strong> a complexitatii diagramelor <strong>de</strong> stari. Hartile <strong>de</strong> stari <strong>în</strong>sa permit<br />

structurarea diagramelor utilizând stari ierarhice.<br />

Astfel, hartile <strong>de</strong> stari au extins ma<strong>si</strong>nile cu stari finite cu trei noi trasaturi:<br />

adâncime, ortogonalitate <strong>si</strong> distributie <strong>de</strong> evenimente (broadcast).<br />

1. Adâncimea. Aceasta trasatura se refera la po<strong>si</strong>bilitatea rafinarii <strong>si</strong><br />

ierarhizarii starilor. Astfel, pentru fiecare stare pot fi <strong>de</strong>finite o multime <strong>de</strong> substari<br />

împreuna cu tranzitii <strong>în</strong>tre acestea. Conceptul <strong>de</strong> adâncime permite gestionarea<br />

complexitatii prin contruirea unei ierarhii <strong>de</strong> harti <strong>de</strong> stari <strong>în</strong>cuibarite (figura 4.4). O<br />

stare care contine substari este <strong>în</strong>tâlnita <strong>în</strong> literatura sub numele <strong>de</strong> stare compusa,<br />

OR-stare sau stare abstracta, iar un <strong>si</strong>stem care se afla <strong>în</strong>tr-o astfel <strong>de</strong> stare se va afla<br />

<strong>în</strong> una <strong>si</strong> numai una dintre substarile acesteia. Prin urmare o harta <strong>de</strong> stari poate fi<br />

reprezentata sub forma unui arbore ale carui noduri intermediare sunt reprezentate <strong>de</strong><br />

starile compuse, iar nodurile frunza reprezinta starile <strong>si</strong>mple, concrete ale <strong>si</strong>stemului.<br />

În unele ver<strong>si</strong>uni ale hartilor <strong>de</strong> stari ierarhizarea este utilizata la eliminarea<br />

ne<strong>de</strong>terminismului prin stabilirea unor prioritati <strong>de</strong> <strong>de</strong>clansare a tranzitiilor.<br />

Figura 4.4. Starea D este rafinata <strong>în</strong> substarile A <strong>si</strong> B (daca <strong>si</strong>stemul se afla <strong>în</strong> starea<br />

D atunci, <strong>în</strong> mod obligatoriu, el se va afla <strong>în</strong> una <strong>si</strong> numai una dintre starile A sau B)<br />

2. Ortogonalitatea. Unul dintre neajunsurile ma<strong>si</strong>nilor cu stari finite<br />

conventionale este acela al exploziei exponentiale <strong>de</strong> stari generate <strong>de</strong> combinarea<br />

tuturor starilor in<strong>de</strong>pen<strong>de</strong>nte ale unui <strong>si</strong>stem. Prin utilizarea starilor ortogonale acest<br />

neajuns este <strong>în</strong>laturat. Astfel doua componente in<strong>de</strong>pen<strong>de</strong>nte ale <strong>si</strong>stemului pot fi<br />

mo<strong>de</strong>late împreuna <strong>în</strong>tr-o asa numita stare ortogonala (cunoscuta <strong>în</strong> literatura <strong>si</strong> sub<br />

<strong>de</strong>numirea <strong>de</strong> AND-stare), fiind separate prin intermediul unei linii punctate. Astfel,<br />

un <strong>si</strong>stem care se afla <strong>în</strong>tr-o stare ortogonala, ea se va afla <strong>în</strong> câte o stare din fiecare<br />

componenta ortogonala a acesteia. Aceasta trasatura ofera po<strong>si</strong>bilitatea combinarii<br />

95


hartilor <strong>de</strong> stari astfel <strong>în</strong>cât sa poata fi mo<strong>de</strong>lata <strong>si</strong>tuatia <strong>în</strong> care un <strong>si</strong>stem se afla <strong>în</strong><br />

doua sau mai multe stari <strong>în</strong> acela<strong>si</strong> timp. Ortogonalitatea reprezinta o alta trasatura <strong>de</strong><br />

tratare a complexitatii prin construirea <strong>de</strong>scrierii unui <strong>si</strong>stem combinând mai multe<br />

harti <strong>de</strong> stari (figura 4.5).<br />

Figura 4.5. Reprezentarea ma<strong>si</strong>nilor <strong>de</strong> stari ortogonale.<br />

Sistemul aflat <strong>în</strong> starea D se va afla <strong>în</strong> câte o stare din fiecare componenta ortogonala<br />

(oricare din combinatzille <strong>de</strong> stari din {A, B} ? {E, F})<br />

3. Distributia evenimetelor. În general componentele ortogonale nu sunt<br />

complet in<strong>de</strong>pen<strong>de</strong>nte. Este necesara uneori sa se specifice o anumita influenta<br />

mutuala sau o comunicare <strong>în</strong>tre acestea. Dupa cum am aratat, <strong>în</strong> formalismul ma<strong>si</strong>nii<br />

Mealy unei tranzitii îi era asociata o anumita ie<strong>si</strong>re (rezultat). Asa cu am aratat,<br />

hartile <strong>de</strong> stari permit specificarea pentru o tranzitie, alaturi <strong>de</strong> evenimentele <strong>si</strong><br />

conditiile care o <strong>de</strong>clanseaza, a unei multimi <strong>de</strong> evenimente care au loc ca efect al<br />

<strong>de</strong>clansarii tranzitiei. De asemenea, fiecarei stari îi sunt asociate multimi <strong>de</strong><br />

evenimente care au loc atunci când <strong>si</strong>stemul intra (reprezentate <strong>de</strong> functia entry()),<br />

respectiv iese (functia exit()) dintr-o stare. Atât evenimentele asociate tranzitiilor cât<br />

<strong>si</strong> cele corespunzatoare functiilor entry() <strong>si</strong> exit() sunt transmise <strong>în</strong>tregului <strong>si</strong>stem.<br />

Aceasta trasatura permite comunicarea <strong>în</strong>tre harti <strong>de</strong> stari ortogonale <strong>de</strong> obicei<br />

in<strong>de</strong>pen<strong>de</strong>nte. Aceasta proprietate <strong>în</strong>sa <strong>în</strong>tra <strong>în</strong> conflict cu paradigma orientata-obiect<br />

<strong>în</strong> care comunicare dintre obiecte este bazata strict pe transmiterea <strong>de</strong> mesaje punct-<br />

la-punct.<br />

Prin urmare, o harta <strong>de</strong> stari poate fi <strong>de</strong>scrisa <strong>si</strong>ntetic astfel:<br />

harta <strong>de</strong> stari = ma<strong>si</strong>na cu stari finite + adâncime + ortogonalitate + distributie.<br />

O serie <strong>de</strong> abordari ale diagramelor <strong>de</strong> stari permit ca <strong>de</strong>clansatorul unei<br />

tranzitii sa fie format dintr-o propozitie logica <strong>de</strong> evenimente, <strong>si</strong> ele poarta numele <strong>de</strong><br />

evenimente compuse [BEE94]. De exemplu, un <strong>de</strong>clansator "¬a? b" specifica faptul<br />

96


ca tranzitia etichetata astfel se <strong>de</strong>clanseaza daca are loc evenimentul b <strong>si</strong> nu are loc<br />

evenimentul a. Utilizarea <strong>în</strong> <strong>de</strong>scrierea <strong>de</strong>clansatorului a evenimentelor care nu au loc<br />

la un moment dat sunt utilizate <strong>de</strong> obicei pentru a elimina anumite cazuri <strong>de</strong><br />

ne<strong>de</strong>terminism <strong>în</strong> hartile <strong>de</strong> stari (Esterel [BER92]).<br />

Prin urmare, entitatea <strong>de</strong> observare a unui <strong>si</strong>stem reactiv este evenimentul.<br />

Mediul transmite evenimente <strong>si</strong>stemului <strong>în</strong> scopul realizarii unor calcule, iar <strong>si</strong>stemul<br />

raspun<strong>de</strong> la rândul sau generând evenimente <strong>în</strong>spre mediu. De asemenea,<br />

evenimentele reprezinta elementul <strong>de</strong> comunicare <strong>în</strong>tre diferite parti ale <strong>si</strong>stemului.<br />

Deoarece se doreste specificarea <strong>si</strong>stemelor reactive la un nivel <strong>de</strong> abstractizare ridicat<br />

<strong>si</strong> <strong>în</strong>tr-o maniera discreta, evenimentele sunt <strong>în</strong>telese ca semnale discrete, care apar la<br />

un anumit moment <strong>de</strong> timp. Evenimentele nu au durata: ele doar apar la un anumit<br />

moment <strong>de</strong> timp sau nu apar <strong>de</strong>loc. Prin urmare, conctructia <strong>de</strong> program care va<br />

generea evenimente trebuie la rândul sau sa nu aiba durata. Evenimentele sunt<br />

generate la tranzitiile dintr-o stare <strong>în</strong> alta. Prin urmare aceste tranzitii vor avea un<br />

caracter discret, ne-intreruptibil.<br />

4.3.2. Timp <strong>de</strong> executie<br />

În anumite abordari toate tranzitiile dintre stari sunt con<strong>si</strong><strong>de</strong>rate instantanee,<br />

doar stationarea <strong>în</strong>tr-o anumita stare având durata. Când se face o rafinare a<br />

specificatiilor, <strong>de</strong>scrierea starii <strong>de</strong>vine mult mai <strong>de</strong>taliata, <strong>în</strong>sa tranzitiile vor ramâne<br />

instantanee. Aceasta abordare este utila <strong>si</strong> din punct <strong>de</strong> ve<strong>de</strong>re al <strong>de</strong>terminarii, <strong>în</strong><br />

orice moment <strong>de</strong> timp, a starii <strong>în</strong> care se afla <strong>si</strong>stemul. Deoarece se lucreaza pe un<br />

domeniu discret, momentul <strong>de</strong> timp <strong>de</strong> dupa modificare succe<strong>de</strong> imediat momentul<br />

dinaintea modificarii, neexistând perioa<strong>de</strong> <strong>de</strong> timp <strong>în</strong>tre aceste doua momente.<br />

Bine<strong>în</strong>teles acest lucru este doar o abstractizare a realitatii, <strong>în</strong>sa hartile <strong>de</strong> stari<br />

reprezinta un limbaj <strong>de</strong> specificare <strong>de</strong> nivel <strong>în</strong>alt pentru care o astfel <strong>de</strong> abstractizare<br />

este potrivita.<br />

Durata <strong>în</strong> timp a reactiei <strong>si</strong>stemului este o alta problema care cunoaste diferite<br />

abordari. Aceasta problema este la rândul sau caracteristica <strong>si</strong>stemelor reactive,<br />

<strong>de</strong>oarece <strong>în</strong> cazul <strong>si</strong>stemelor tranformationale este relevant doar daca este produs<br />

rezultatul nu <strong>si</strong> când are loc acest fapt. Pentru <strong>si</strong>stemele reactive cunoasterea faptului<br />

ca un eveniment a fost sau nu produs nu este suficient. Rectiile pot interfera cu<br />

aparitii <strong>de</strong> evenimente ulterioare, <strong>si</strong> prin urmare momentul <strong>în</strong> care acestea au loc este<br />

97


foarte important. Chiar <strong>si</strong> <strong>în</strong> cazul <strong>în</strong> care timpul nu se cuantifica explicit, este<br />

necesara cunoasterea momentului <strong>în</strong> care reactia apare relativ la evenimentele din<br />

secventa <strong>de</strong> intrare (acest element sta <strong>de</strong> fapt la baza paradoxului Brock-Ackermann<br />

prezentat anterior).<br />

O abordare a acestei probleme este aceea <strong>de</strong> a specifica pentru fiecare <strong>si</strong>tuatie<br />

o cantitate concreta <strong>de</strong> timp. Aceasta abordare nu este potrivita nivelului <strong>de</strong><br />

abstractizare al hartilor <strong>de</strong> stari, <strong>de</strong>oarece este <strong>de</strong>pen<strong>de</strong>nta <strong>de</strong> <strong>implementare</strong> <strong>si</strong> forteaza<br />

cuantificarea din start a timpului. O alta abordare consta <strong>în</strong> fixarea timpului <strong>de</strong> reactie<br />

la o unitate <strong>de</strong> timp (pentru un domeniu discret <strong>de</strong> timp). Acest lucru este <strong>si</strong>mplu, <strong>în</strong>sa<br />

ramâne slab abstractizat, <strong>de</strong>oarece este dificila rafinarea specificatiilor fara<br />

modificarea <strong>în</strong>telesului acestora la nivel <strong>în</strong>alt. În [HUI91] s-a aratat ca problemele<br />

cauzate <strong>de</strong> o astfel <strong>de</strong> abordare sunt asemanatoare cu anomaliile tipice limbajelor <strong>de</strong><br />

programare <strong>de</strong> nivel coborât: o modificare locala a mai multor instructiuni afecteaza<br />

comportamentul <strong>în</strong>tregului program (modificare nereprezentând o corectie, ci doar o<br />

rafinare a unei actiuni). De exemplu, o tranzitie etichetata <strong>în</strong>trebare/raspuns poate fi<br />

rafinata <strong>în</strong> doua tranzitii etichetate intrebare/consultare <strong>si</strong> consultare/raspuns. În<br />

acest caz lungimea <strong>si</strong>ntactica a calculului este modificata. Prin urmare un timp <strong>de</strong><br />

executie fix pentru entitati <strong>si</strong>ntactice (tranzitii, instructiuni etc) nu este suficient <strong>de</strong><br />

flexibil.<br />

Abordarea aceasta are <strong>si</strong> un alt <strong>de</strong>zavantaj: impunerea unei durate fixe pentru o<br />

reactie implica, <strong>în</strong> practica, introducerea <strong>de</strong> intârzieri explicite artificiale pentru a<br />

corespun<strong>de</strong> intocmai specificatiilor.<br />

O a treia abordare este aceea <strong>de</strong> a con<strong>si</strong><strong>de</strong>ra ca executia unei reactii dureaza o<br />

perioada <strong>de</strong> timp strict pozitiva, urmând a constata durata exacta <strong>în</strong>tr-o faza ulterioara.<br />

O astfel <strong>de</strong> abordare introduce <strong>în</strong>sa ne<strong>de</strong>terminismul la nivelul hartilor <strong>de</strong> stari <strong>si</strong> face<br />

dificila sau chiar impo<strong>si</strong>bila <strong>de</strong>monstrarea anumitor proprietati <strong>în</strong> fazele timpurii ale<br />

<strong>de</strong>zvoltarii.<br />

Prin urmare, din <strong>analiza</strong> celor trei abordari mentionate, rezulta concluzia ca<br />

timpul <strong>de</strong> executie al reactiilor trebuie sa fie caraterizate <strong>de</strong> urmatoarele proprietati:<br />

?? trebuie sa fie precis, <strong>în</strong>sa sa nu <strong>de</strong>pinda <strong>de</strong> <strong>implementare</strong>,<br />

?? sa fie cât <strong>de</strong> scurt po<strong>si</strong>bil, pentru a nu <strong>de</strong>termina <strong>în</strong>târzieri artificiale,<br />

?? trebuie sa aiba un grad ridicat <strong>de</strong> abstractizare, astfel <strong>în</strong>cât "cronometrarea"<br />

sa fie ortogonala cu comportamentul functional.<br />

98


Singura solutie care <strong>în</strong>truneste toate proprietatile <strong>de</strong> mai sus este sa<br />

con<strong>si</strong><strong>de</strong>ram ca timpul <strong>de</strong> reactie este egal cu 0. Aceasta este <strong>în</strong> esenta ipoteza <strong>de</strong><br />

<strong>si</strong>ncronizare <strong>de</strong>numita astfel <strong>de</strong> Gerard Berry <strong>în</strong> [BER92]. Bine<strong>în</strong>teles ca acest fapt<br />

nu este unul firesc din punct <strong>de</strong> ve<strong>de</strong>re al implementarii, <strong>de</strong>oarece orice calcul real<br />

nece<strong>si</strong>ta o anumita perioada <strong>de</strong> timp pentru a fi dus la bun sfâr<strong>si</strong>t, chiar daca aceasta<br />

perioada este extrem <strong>de</strong> scurta. Aceasta solutie <strong>în</strong>sa are <strong>si</strong> un alt <strong>în</strong>teles, <strong>si</strong> anume<br />

acela ca o reactie are loc <strong>în</strong>ainte <strong>de</strong> a fi receptionate urmatoarele semnale <strong>de</strong> intrare.<br />

Prin urmare o reactie nu este con<strong>si</strong><strong>de</strong>rata a fi "nelimitat" <strong>de</strong> rapida ci "suficient" <strong>de</strong><br />

rapida. Aceasta interpretare nu mai pare nerealista, <strong>de</strong>oarece <strong>în</strong> foarte multe cazuri<br />

frecventa evenimentelor externe este mica relativ la timpul <strong>de</strong> raspuns al <strong>si</strong>stemului.<br />

Mai mult, chiar <strong>si</strong> <strong>în</strong> cazul <strong>în</strong> care vor apare probleme <strong>de</strong> <strong>implementare</strong>, este foarte<br />

po<strong>si</strong>bil ca acestea sa nu influenteze rezultatele proiectantilor <strong>si</strong> a programatorilor <strong>în</strong><br />

primele faze ale <strong>de</strong>zvoltarii <strong>de</strong> aplicatii.<br />

4.3.3. Pseudostari<br />

Tot <strong>în</strong> [HAR87] a fost introdus conceptul <strong>de</strong> stare initiala (implicita) prin<br />

intermediul careia se este specificata substarea activa <strong>în</strong> momentul <strong>în</strong> care <strong>si</strong>stemul<br />

intra <strong>în</strong> starea sa parinte (figura 4.6). Reprezentarea grafica a starii initiale este data<br />

printr-un cerc plin. De asemenea, starea initiala poate fi prezenta <strong>si</strong> la nivelul<br />

diagramei <strong>de</strong> stari, caz <strong>în</strong> care se specifica starea <strong>în</strong> care va intra <strong>si</strong>stemul <strong>în</strong> momentul<br />

crearii sale.<br />

Figura 4.6. Specificarea (sub)starilor initiale (<strong>în</strong> configuratia <strong>de</strong> mai sus,<br />

intrarea <strong>si</strong>stemului <strong>în</strong> starea D va <strong>de</strong>termina implicit activarea substarii A)<br />

Starea initiala este numita <strong>si</strong> pseudostare (<strong>si</strong>stemul nu se va afla niciodata <strong>în</strong><br />

starea respectiva ci va efectua o tranzitie <strong>în</strong> plus pentru a intra <strong>în</strong>tr-o stare concreta).<br />

Alte pseudostari introduse <strong>în</strong> timp <strong>si</strong> utilizate <strong>în</strong> majoritatea variantelor <strong>de</strong> harti <strong>de</strong><br />

stari sunt starile <strong>de</strong> ie<strong>si</strong>re <strong>si</strong> starile istoric. Tranzitia <strong>în</strong>tr-o stare <strong>de</strong> ie<strong>si</strong>re semnifica<br />

<strong>în</strong>cheierea ciclului <strong>de</strong> viata al <strong>si</strong>stemului <strong>si</strong> (<strong>în</strong> unele abordari) distrugerea acestuia.<br />

99


100<br />

H<br />

a) b) c)<br />

Figura 4.7. Pseudostari <strong>de</strong> intrare (a), <strong>de</strong> ie<strong>si</strong>re (b) <strong>si</strong> istoric (c)<br />

Pseudostarea istoric se poate afla pozitionata doar ca <strong>si</strong> substare a unei stari<br />

compuse <strong>si</strong> o tranzitie spre acea stare semnifica intrarea <strong>si</strong>stemului <strong>în</strong> ultima substare<br />

activa a starii compuse respective. Notatiile utilizate pentru <strong>si</strong>mbolizarea acestor<br />

pseudostari sunt date <strong>în</strong> figura 4.7.<br />

4.4. Utilizarea hartilor <strong>de</strong> stari <strong>în</strong> mo<strong>de</strong>larea obiectelor active<br />

De<strong>si</strong>, asa cum am aratat, diagramele <strong>de</strong> tranzitie a starilor au fost proiectate<br />

initial pentru mo<strong>de</strong>larea comportamentului <strong>si</strong>stemelor reactive, ele au fost foarte<br />

natural incluse <strong>în</strong> cadrul meto<strong>de</strong>lor <strong>de</strong> mo<strong>de</strong>lare vizuala orientate-obiect.<br />

Acceptarea generala a diagramelor <strong>de</strong> stari pentru mo<strong>de</strong>larea dinamica a<br />

obiectelor din cadrul unei aplicatii s-a datorat <strong>în</strong> principal urmatoarelor aspecte:<br />

?? diagramele <strong>de</strong> stari permit <strong>de</strong>scrierea lizibila a comportamentului la un<br />

nivel ridicat <strong>de</strong> abstractizare,<br />

?? permit efectuarea <strong>de</strong> verificari la nivel semantic,<br />

?? codul generat din diagramele <strong>de</strong> stari a<strong>si</strong>gura pastrarea con<strong>si</strong>stentei<br />

obiectelor <strong>în</strong> timpul executiei <strong>si</strong>stemului; extin<strong>de</strong>rea diagramelor <strong>de</strong> stari<br />

cu adnotari formale duce la cresterea semnificativa a procentului <strong>de</strong> cod<br />

generat pentru aplicatia mo<strong>de</strong>lata;<br />

?? permit realizarea <strong>de</strong> <strong>si</strong>mulari grafice a functionarii <strong>si</strong>stemului <strong>si</strong><br />

<strong>în</strong>curajeaza prototipizarea,<br />

?? <strong>în</strong> ceea ce priveste aspectele legate <strong>de</strong> concurenta, permit o <strong>de</strong>criere<br />

intuitiva <strong>si</strong> precisa a <strong>si</strong>ncronizarii mesajelor dintre obiecte.<br />

În cele ce urmeaza sunt prezentate <strong>si</strong>ntetic patru dintre cele mai importante<br />

exten<strong>si</strong>i sau variante ale hartilor <strong>de</strong> stari utilizate <strong>în</strong> mo<strong>de</strong>larea obiectelor active:<br />

Objectcharts, OSA, Objchart <strong>si</strong> diagramele <strong>de</strong> tranzitie a starilor din UML. Deoarece<br />

UML (v. Anexa B) reprezinta limbajul <strong>de</strong> mo<strong>de</strong>lare care s-a impus ca standard <strong>în</strong><br />

<strong>analiza</strong> <strong>si</strong> <strong>proiectarea</strong> orientata-obiect a aplicatiilor, se va in<strong>si</strong>sta mai mult asupra sa.<br />

Analiza critica ce <strong>în</strong>soteste aceasta <strong>de</strong>scriere se constituie <strong>în</strong>tr-un argument pentru


econ<strong>si</strong><strong>de</strong>rarea hartilor <strong>de</strong> stari <strong>în</strong> mo<strong>de</strong>larea obiectelor active <strong>si</strong> are rolul <strong>de</strong> a<br />

introduce modificarile semantice care sunt propuse <strong>în</strong> sectiunea urmatoare. Validarea<br />

aspectelor privind con<strong>si</strong>stenta <strong>si</strong> executabilitatea variantei <strong>de</strong> harti <strong>de</strong> stari propuse<br />

aici se va realiza prin <strong>implementare</strong>a unui instrument <strong>de</strong> mo<strong>de</strong>lare <strong>si</strong> <strong>si</strong>mulare a<br />

aplicatiilor orientate-obiect concurente, numit ActiveCASE, <strong>si</strong> care va fi prezentat <strong>în</strong><br />

capitolul 5.<br />

Objectcharts. În [COL92] a fost prezentata o notatie pentru specificarea<br />

comportamentului obiectelor, numita Objectcharts (harti <strong>de</strong> obiecte). Hartile <strong>de</strong><br />

obiecte au la baza hartile <strong>de</strong> stari <strong>de</strong>scrise <strong>de</strong> Harel dar nu adopta mecanismul <strong>de</strong><br />

distributie a evenimentelor, <strong>si</strong> integreaza tranzitiile cu invocarea mesajelor (dupa<br />

mo<strong>de</strong>lul cerere-raspuns) din mo<strong>de</strong>lul orientat obiect. Hartile <strong>de</strong> obiecte furnizeaza o<br />

notatie grafica la care se aduga <strong>de</strong>talii prin intermediul specificarilor formale ale<br />

tranzitiilor <strong>si</strong> ale invariantilor (<strong>de</strong> stare).<br />

Un aspect interesant privitor la aceste harti <strong>de</strong> obiecte este ca mo<strong>de</strong>lul permite<br />

<strong>de</strong>scrierea comportamentului <strong>si</strong>stemului prin <strong>de</strong>scrierea interactiunilor dintre obiecte.<br />

O prima restrictie a acestui mo<strong>de</strong>l este aceea ca numarul <strong>de</strong> obiecte al <strong>si</strong>stemului este<br />

fix (nu poate fi adaugat sau distrus nici un obiect <strong>în</strong> timpul rularii). Alte restrictii sunt<br />

legate <strong>de</strong> inexistenta specificarii unei modalitati <strong>de</strong> mostenire a hartilor <strong>de</strong> obiecte sau<br />

<strong>de</strong> impo<strong>si</strong>bilitatea transmiterii <strong>de</strong> mesaje spre alte obiecte <strong>în</strong> timpul executiei unei<br />

operatii.<br />

OSA. În OSA (Object-oriented Systems Analy<strong>si</strong>s <strong>de</strong>scrisa <strong>în</strong> [BER94]) pentru<br />

mo<strong>de</strong>larea comportamentului dinamic al <strong>si</strong>stemelor se foloseste o notatie numita retea<br />

<strong>de</strong> stari. Retelele <strong>de</strong> stari reprezinta o exten<strong>si</strong>e a diagramelor <strong>de</strong> tranzitie a starilor.<br />

Una dintre principalele exten<strong>si</strong>i este aceea ca o tranzitie este formata dintr-o conditie<br />

<strong>si</strong> o actiune, iar ea va fi <strong>de</strong>clansata doar atunci când conditia asociata ei este<br />

satisfacuta. De asemenea, tranzitia nu este con<strong>si</strong><strong>de</strong>rata ca fiind atomica, ea fiind<br />

realizata <strong>în</strong>tr-o anumita perioada <strong>de</strong> timp (<strong>în</strong> care este executata actiunea care îi este<br />

asociata). Mo<strong>de</strong>lul permite specializarea retelelor <strong>de</strong> stari <strong>în</strong> subclase.<br />

O tranzitie poate avea mai multe stari <strong>de</strong> pornire <strong>si</strong> stari tinta. Acest lucru<br />

ofera po<strong>si</strong>bilitatea <strong>de</strong>finirii <strong>si</strong>ncronizarilor (<strong>de</strong> exemplu, o tranzitie poate avea loc doar<br />

atunci când obiectul se afla <strong>în</strong> toate starile <strong>de</strong> pornire). De asemenea poate fi<br />

101


mo<strong>de</strong>lata concurenta intra-obiect permitând ca dupa efectuarea unei tranzitii obiectul<br />

sa se afle <strong>în</strong> mai multe stari din care ulterior pot avea loc in<strong>de</strong>pen<strong>de</strong>nt noi tranzitii.<br />

Mo<strong>de</strong>lul ofera po<strong>si</strong>bilitatea tratarii exceptiilor <strong>si</strong> specificarea <strong>de</strong> constrângeri <strong>de</strong> timp-<br />

real.<br />

Mo<strong>de</strong>lul OSA are o putere <strong>de</strong>osebita <strong>de</strong> <strong>analiza</strong>, dar din pacate nu este foarte<br />

clar <strong>de</strong>finita modalitatea <strong>de</strong> tranzitie <strong>de</strong> la un mo<strong>de</strong>l <strong>de</strong> <strong>analiza</strong> la un mo<strong>de</strong>l <strong>de</strong><br />

proiectare <strong>si</strong>, eventual, la <strong>implementare</strong>.<br />

ObjChart. ObjChart reprezinta un set <strong>de</strong> notatii vizuale pentru <strong>de</strong>scrierea obiectelor <strong>si</strong><br />

al comportamentului reactiv al acestora [GAN93]. Aici un <strong>si</strong>stem este privit ca fiind<br />

format dintr-o colectie <strong>de</strong> obiecte care comunica a<strong>si</strong>ncron <strong>si</strong> care sunt reprezentate<br />

<strong>în</strong>tr-o ierarhie <strong>de</strong> tip parte-intreg (mostenirea nu este mo<strong>de</strong>lata). La rândul sau,<br />

fiecare obiect din <strong>si</strong>stem <strong>de</strong>tine o ma<strong>si</strong>na finita <strong>de</strong> stari care îi <strong>de</strong>fineste<br />

comportamentul reactiv relativ la mesajele receptionate. Mesajele obtinute <strong>de</strong> catre<br />

un obiect reprezinta evenimente care <strong>de</strong>clanseaza tranzitii <strong>de</strong> stari. Fiecare tranzitie<br />

este asociata cu o actiune care transmite unul sau mai multe mesaje a<strong>si</strong>ncrone<br />

obiectului <strong>în</strong>su<strong>si</strong> sau componentelor sale. Relatiile dintre obiecte pot fi exprimate atât<br />

prin utilizarea <strong>de</strong> invarianti functionali asupra proprietatilor cât <strong>si</strong> prin specificarea<br />

<strong>de</strong>pen<strong>de</strong>ntelor comportamentale dintre obiecte prin intermediul ma<strong>si</strong>nilor cu stari<br />

finite.<br />

Caracteristica ce <strong>de</strong>osebeste ObjChart <strong>de</strong> celelalte meto<strong>de</strong> este aceea ca<br />

mo<strong>de</strong>lele construite aici sunt executabile, adaugarea unei noi specificatii putând fi<br />

testata imediat. Fiecare obiect contine o <strong>si</strong>ngura ma<strong>si</strong>na <strong>de</strong> stari. De<strong>si</strong> proprietatea <strong>de</strong><br />

ortogonalitate nu este mo<strong>de</strong>lata, prevenire cresterii explo<strong>si</strong>ve a numarului <strong>de</strong> stari se<br />

realizeaza prin compunerea obiectelor. De<strong>si</strong> comportamentul fiecarui obiect este<br />

controlat (sau mo<strong>de</strong>lat) <strong>de</strong> o ma<strong>si</strong>na <strong>de</strong> stari <strong>de</strong>terminista, orice obiect are un<br />

comportament ne<strong>de</strong>terminist datorita <strong>concurentei</strong> interne. Avantajul formalismului<br />

ObjChart este acela ca face referire la o multime minimala <strong>de</strong> notatii, acestea având o<br />

semantica precisa. Minimalitatea <strong>si</strong> precizia confera mo<strong>de</strong>lelor ObjChar coerenta <strong>si</strong><br />

executabilitate.<br />

102


UML (Unified Mo<strong>de</strong>ling Language). UML este un limbaj <strong>de</strong> mo<strong>de</strong>lare <strong>de</strong> generatia<br />

a treia care <strong>de</strong>fineste semanticile metamo<strong>de</strong>lului obiect <strong>si</strong> furnizeaza o notatie grafica<br />

pentru specificarea structurii <strong>si</strong> a comportamentului obiectelor.<br />

UML este un limbaj executabil, facând po<strong>si</strong>bila generarea automata <strong>de</strong> <strong>si</strong>steme<br />

executabile pe baza mo<strong>de</strong>lelor realizate. Executabilitatea reprezinta o trasatura<br />

importanta a unui limbaj <strong>de</strong>oarece contribuie la reducerea efortului <strong>de</strong> translatare a<br />

mo<strong>de</strong>lelor abstracte <strong>în</strong> cod sursa, permite parcurgerea rapida a "distantei" dintre<br />

mo<strong>de</strong>larea unui concept <strong>si</strong> validarea acestuia <strong>si</strong> <strong>în</strong>curajeazeaza explorarea spatiului<br />

solutiilor unei anumite probleme.<br />

În UML diagramele <strong>de</strong> tranzitie a starilor sunt utilizate pentru mo<strong>de</strong>larea<br />

comportamentului atât a claselor cât <strong>si</strong> a activitatilor [OMG99], [DOU99]. În cele ce<br />

urmeaza vom con<strong>si</strong><strong>de</strong>ra tratarea acestora numai din perspectiva claselor in<strong>si</strong>stând <strong>în</strong><br />

special pe aspectele legate <strong>de</strong> concurenta. În UML clasele pot fi asociate cu una sau<br />

mai multe diagrame <strong>de</strong> tranzitie a starilor. În documentatia UML se arata ca <strong>în</strong><br />

majoritatea cazurilor va fi suficienta specificarea unei <strong>si</strong>ngure ma<strong>si</strong>ni <strong>de</strong> stari pentru<br />

<strong>de</strong>scrierea comportamentului unei clase (sau, mai general, al unui element din<br />

mo<strong>de</strong>lul intern) fara a se preciza care ar fi cazurile <strong>în</strong> care este benefica specificarea<br />

mai multor astfel <strong>de</strong> ma<strong>si</strong>ni (probabil ca <strong>în</strong>tr-o faza timpurie <strong>de</strong> <strong>analiza</strong>, când <strong>de</strong>cizia<br />

stabilirii unui anumit mo<strong>de</strong>l este amânata).<br />

Un eveniment general este <strong>de</strong>scris <strong>în</strong> UML ca reprezentând specificarea unui<br />

“inci<strong>de</strong>nt” semnificativ care poate fi localizat <strong>în</strong> timp <strong>si</strong> spatiu. Fiecare tranzitie are<br />

asociat un eveniment care o <strong>de</strong>clanseaza. Declansarea unei tranzitii implica<br />

executarea unei anumite operatii <strong>de</strong>finite la nivelul clasei mo<strong>de</strong>late care trateaza<br />

evenimentul receptionat.<br />

Alaturi <strong>de</strong> pseudostarile <strong>de</strong> ie<strong>si</strong>re, <strong>de</strong> intrare <strong>si</strong> istoric, UML mai introduce alte<br />

trei pseudostari fara semnificatie semantica, având ca rol cresterea lizibilitatii<br />

diagramei: starile ramificatie (branch - pentru reprezentarea a doua sau mai multe<br />

tranzitii dintr-o stare sursa comuna, <strong>de</strong>clansate <strong>de</strong> acela<strong>si</strong> eveniment, dar cu garzi<br />

diferite), fork <strong>si</strong> join (pentru tranzitii <strong>în</strong> <strong>si</strong> din stari aflate <strong>în</strong> componente ortogonale) -<br />

figura 4.8. De asemenea pseudostarile istoric au doua variante: superficiale <strong>si</strong><br />

profun<strong>de</strong>. Pseudostarile istoric profun<strong>de</strong> activeaza recur<strong>si</strong>v ultima substare activata a<br />

ultimei stari compuse active.<br />

103


O stare compusa poate contine cel mult o pseudo-stare istoric (<strong>în</strong> variantele<br />

sale superficiala <strong>si</strong> profunda), iar o pseudo-stare istoric poate fi sursa pentru cel mult<br />

o tranzitie. Acela<strong>si</strong> lucru este valabil <strong>si</strong> pentru starea initiala, restrictie impusa <strong>de</strong><br />

i<strong>de</strong>ea ca dintr-o stare initiala nu poate pleca <strong>de</strong>cât o <strong>si</strong>ngura tranzitie. Acest fapt <strong>în</strong>sa<br />

nu este natural, <strong>de</strong>oarece astfel nu poate fi permisa mo<strong>de</strong>larea activarii implicite a<br />

unei substari <strong>în</strong> raport cu o multime <strong>de</strong> conditii complementare.<br />

Figura 4.8. Pseudostarile ramificatie (a), fork (b) <strong>si</strong> join (c)<br />

Se con<strong>si</strong><strong>de</strong>ra ca evenimentele sunt stocate <strong>în</strong>tr-o coada <strong>de</strong> asteptare pe masura<br />

ce ele apar. De asemenea se presupune ca exista un gestionar al acestor evenimente.<br />

Acest gestionar a<strong>si</strong>gura faptul ca tratarea unui eveniment <strong>de</strong> catre o ma<strong>si</strong>na <strong>de</strong> stari va<br />

avea loc dupa ce prece<strong>de</strong>ntul eveniment a fost complet tratat. O tratare completa se<br />

refera la modificarea starii obiectului (daca este cazul) <strong>si</strong> la <strong>în</strong>cheierea executiei<br />

tuturor actiunilor lansate ca efect al tratarii respectivului eveniment (actiuni care fac<br />

parte din secventele entry() <strong>si</strong> exit() ale starilor, respectiv secventele atasate<br />

tranzitiilor). În cazul unei stari compuse concurente, terminarea tratarii unui<br />

eveniment presupune <strong>în</strong>cheierea tratarii sale <strong>în</strong> cadrul fiecarei componente concurente<br />

ale acesteia (o altfel <strong>de</strong> abordare ar duce la complicarea nejustificata a implementarii<br />

unei ma<strong>si</strong>ni <strong>de</strong> stari). Acest <strong>si</strong>stem propus <strong>de</strong> UML pentru tratarea evenimentelor<br />

contribuie la pastrarea con<strong>si</strong>stentei interne a obiectelor (evenimentul este tratat <strong>de</strong><br />

catre un obiect care se afla <strong>în</strong>tr-o configuratie stabila, bine <strong>de</strong>finita <strong>de</strong> stari), <strong>în</strong>sa nu<br />

104


ofera suport pentru mo<strong>de</strong>larea <strong>concurentei</strong> interne (cazul obiectelor secventiale<br />

concurente!).<br />

În cadrul documentului <strong>de</strong> specificare al UML apar <strong>în</strong> mai multe rânduri,<br />

disparat, fraze care sugereaza ca un eveniment poate <strong>de</strong>clansa mai multe tranzitii care<br />

nu se afla <strong>în</strong> componente concurente! Acest aspect este tratat cu superficialitate,<br />

facându-se referire doar la modalitatea <strong>de</strong> alegere a tranzitiei care se va <strong>de</strong>clansa<br />

efectiv dintre cele po<strong>si</strong>bile. Astfel, <strong>în</strong> cazul <strong>în</strong> care un eveniment poate <strong>de</strong>clansa mai<br />

multe tranzitii <strong>în</strong> cadrul acelea<strong>si</strong> regiuni (secventiale) va fi <strong>de</strong>clansata o <strong>si</strong>ngura<br />

tranzitie (cea cu prioritatea cea mai mare, <strong>în</strong> cazul <strong>în</strong> care sunt specificate prioritati,<br />

sau este aleasa o tranzitie <strong>în</strong> mod ne<strong>de</strong>terminist <strong>în</strong> caz contrar).<br />

Con<strong>si</strong><strong>de</strong>ram ca trebuie evitate <strong>si</strong>tuatiile ne<strong>de</strong>terministe <strong>în</strong> mo<strong>de</strong>larea<br />

comportamentului <strong>de</strong>oarece este afectata atât <strong>în</strong>telegerea mo<strong>de</strong>lului cât <strong>si</strong> verificarea<br />

automata a acestuia (din nou facem referire aici la cazul utilizarii unui instrument <strong>de</strong><br />

mo<strong>de</strong>lare). Prin urmare UML nu impune restrictii <strong>de</strong> eliminare a ne<strong>de</strong>terminismului,<br />

asa cum se <strong>în</strong>tâmpla <strong>de</strong> exemplu <strong>în</strong> Syntropy [COO94] un<strong>de</strong> pentru doua tranzitii<br />

plecate din aceea<strong>si</strong> stare <strong>si</strong> <strong>de</strong>clansate <strong>de</strong> acela<strong>si</strong> eveniment se impune ca expre<strong>si</strong>ile<br />

garzilor sa fie complementare. De asemenea se lasa la latitudinea proiectantului ca<br />

reprezentarea unor astfel <strong>de</strong> tranzitii sa fie facute folo<strong>si</strong>nd tranzitii <strong>si</strong>mple sau cu prin<br />

pseudostari <strong>de</strong> ramificatie. O solutie <strong>si</strong>mpla <strong>si</strong> <strong>în</strong> acela<strong>si</strong> timp naturala consta <strong>în</strong><br />

evitarea trasarii mai multor tranzitii <strong>de</strong>clansate <strong>de</strong> acela<strong>si</strong> eveniment dintr-o anumita<br />

stare prin utilizarea exclu<strong>si</strong>va pentru acest scop a pseudostarilor ramificatie, ale carei<br />

ramuri vor fi etichetate cu expre<strong>si</strong>i booleene complementare.<br />

Un alt element <strong>de</strong> noutate introdus este notiunea <strong>de</strong> tranzitie <strong>de</strong> completare<br />

(sau terminare). O astfel <strong>de</strong> tranzitie este neetichetata cu un nume <strong>de</strong> eveniment<br />

(eventual ea poate avea o garda). Daca <strong>în</strong> urma tratarii unui anumit eveniment un<br />

obiect se afla <strong>în</strong>tr-o configuratie <strong>de</strong> stari ce permite <strong>de</strong>clansarea <strong>de</strong> tranzitii <strong>de</strong><br />

terminare atunci spunem ca obiectul respectiv a atins o configuratie instabila.<br />

eveniment <strong>de</strong> terminare<br />

105<br />

tranzitie <strong>de</strong> terminare<br />

Figura 4.9. Exemplu <strong>de</strong> utilizare a unei tranzitii <strong>de</strong> terminare


Tratarea urmatorului eveniment se va realiza <strong>în</strong> acest caz doar dupa efectuarea<br />

unui numar corespunzator <strong>de</strong> pa<strong>si</strong>, pâna când se atinge o configuratie stabila (<strong>în</strong><br />

exemplul din figura 4.9 obiectul va atinge o configuratie instabila imediat dupa<br />

tratarea evenimentului e; <strong>în</strong> aceasta faza se realizeaza un nou pas <strong>de</strong> trecere a<br />

obiectului <strong>în</strong> starea C, <strong>în</strong>ainte <strong>de</strong> tratarea urmatorului eveniment din coada). În cazul<br />

unei proiectari incorecte se poate ajunge <strong>în</strong> <strong>si</strong>tuatia <strong>în</strong> care nu se atinge niciodata o<br />

configuratie stabila. Pentru a pre<strong>în</strong>tâmpina astfel <strong>de</strong> <strong>si</strong>tuatii UML propune stabilirea<br />

initiala a unui numar maxim <strong>de</strong> pa<strong>si</strong> care sa poata fi efectuati dupa <strong>în</strong>cheierea tratarii<br />

unui eveniment. La interpretarea urmatorului eveniment, componenta instabila nu va<br />

participa.<br />

Figura 4.10. Activarea starilor <strong>în</strong> cazul unei tranzitii (e1) <strong>în</strong> cadrul unei stari compuse (B)<br />

a) intrare implicita – C va fi starea activa, b) intrare explicita – stare activa D<br />

c) intrare prin istoric – daca se intra pentru prima data <strong>în</strong> B <strong>de</strong> la crearea obiectului<br />

starea activa va fi C, altfel stare activa este ultima sub-stare activa a starii B (C sau D)<br />

Asa cum am vazut <strong>în</strong>tr-una din subsectiunile anterioare, starile pot fi active sau<br />

inactive. O stare <strong>de</strong>vine activata <strong>în</strong> urma <strong>de</strong>clansarii unei tranzitii a carei <strong>de</strong>stinatie<br />

este respectiva stare. În cazul starilor compuse, daca acestea nu sunt concurente<br />

106


atunci o <strong>si</strong>gura substare a sa poate fi activa la un moment dat. În cazul <strong>concurentei</strong><br />

vor fi active toate subregiunile starii compuse.<br />

În diagramele <strong>de</strong> stari din UML exista trei modalitati prin care o sub-stare<br />

<strong>de</strong>vine activa <strong>în</strong> cazul unei tranzitii <strong>în</strong>tr-o stare compusa: implicit, explicit <strong>si</strong> prin<br />

intermediul pseudostarii istoric. În figura 4.10 sunt reprezentate grafic toate aceste<br />

cazuri, cu remarca suplimentara ca <strong>în</strong> cazul <strong>în</strong> care sub-starile sunt la rândul lor stari<br />

compuse, activarea se va face analog recur<strong>si</strong>v. Indiferent <strong>de</strong> modalitatea <strong>în</strong> care se<br />

realizeaza tranzitia <strong>în</strong> cadrul unei stari compuse se va executa secventa <strong>de</strong> actiuni<br />

entry() specificata pentru aceasta stare. Un caz <strong>de</strong>osebit este cel <strong>în</strong> care starea<br />

compusa contine mai multe componente concurente (ortogonale). În acest caz se va<br />

utiliza o tranzitie complexa cu ajutorul pseudostarii fork, <strong>si</strong> fiecare regiune<br />

(componenta) concurenta <strong>în</strong> care va intra o astfel <strong>de</strong> tranzitie va activa o substare a sa<br />

dupa mo<strong>de</strong>lul starilor compuse prezentat anterior. Pentru regiunile <strong>în</strong> care nu intra<br />

nici o tranzitie se va activa starea implicita (care este <strong>de</strong>stinatie a unei tranzitii<br />

initiale).<br />

Se <strong>de</strong>fineste tranzitia <strong>de</strong> terminare ca fiind o tranzitie a carei sursa este o stare<br />

<strong>si</strong>mpla sau stare compusa <strong>si</strong> care este neetichetata. O astfel <strong>de</strong> tranzitie este activata<br />

atunci când starea sursa a atins o stare finala. De asemenea, se <strong>de</strong>fineste termenul <strong>de</strong><br />

tranzitie <strong>de</strong> nivel <strong>în</strong>alt ca fiind acea tranzitie a carei sursa este o stare compusa.<br />

neetichetate:<br />

Sun mai multe cazuri distincte <strong>în</strong> care putem avea <strong>în</strong>tr-un mo<strong>de</strong>l tranzitii<br />

- tranzitii din stari initiale care nu apartin starii compuse <strong>de</strong> la nivelul unu<br />

(optional poate apare ca eticheta o expre<strong>si</strong>e booleana),<br />

- tranzitii <strong>de</strong> terminare,<br />

- tranzitii spre stari finale aflate <strong>în</strong> cadrul starii compuse <strong>de</strong> nivel unu care<br />

sugereaza <strong>si</strong>mpla distrugere a obiectului prin apelul <strong>de</strong>structorului<br />

(optional – pot apare ca etichete nume <strong>de</strong> evenimente care <strong>de</strong>termina<br />

distrugerea obiectului),<br />

- tranzitii care ies din pseudostarile istoric <strong>si</strong> fork <strong>si</strong> care intra <strong>în</strong><br />

pseudostarea join.<br />

Ie<strong>si</strong>rea din cadrul unei stari compuse este tratata foarte pe scurt <strong>în</strong><br />

documentatia UML, nein<strong>si</strong>stându-se prea mult cu explicatii pe marginea tranzitiilor <strong>de</strong><br />

terminare.<br />

107


Fiecare subregiune a unei stari compuse concurente poate avea stari initiale <strong>si</strong><br />

stari finale. O tranzitie spre o stare compusa este echivalenta cu o tranzitie spre starea<br />

<strong>de</strong> intrarea a starii compuse. O tranzitie spre o stare finala reprezinta <strong>în</strong>cheierea<br />

activitatii <strong>în</strong> regiunea parinte, iar <strong>în</strong>cheierea activitatii tuturor regiunilor concurente<br />

semnifica <strong>în</strong>cheierea activitatii <strong>în</strong> starea compusa parinte <strong>si</strong> <strong>de</strong>clanseaza un<br />

"eveniment <strong>de</strong> <strong>în</strong>cheiere a activitatii" spre aceasta. Aparitia unui astfel <strong>de</strong> eveniment<br />

<strong>în</strong> cadrul starii compuse <strong>de</strong> la nivelul cel mai exterior reprezinta distrugerea obiectului<br />

(apelarea <strong>de</strong>structorului acestuia).<br />

UML permite realizarea tranzitiilor <strong>în</strong>tre regiuni concurente fara <strong>în</strong>sa a se<br />

explica sensul unei astfel <strong>de</strong> reprezentari. Foarte probabil ca astfel <strong>de</strong> tranzitii nu î<strong>si</strong><br />

au sensul <strong>si</strong> sunt incon<strong>si</strong>stente cu faptul ca un <strong>si</strong>stem aflat <strong>în</strong>tr-o stare compusa cu mai<br />

multe regiuni ortogonale se va afla <strong>de</strong> fapt <strong>în</strong> câte o stare din cadrul fiecarei<br />

componente ortogonale.<br />

În momentul creerii unui obiect se realizeaza o tranzitie din starea initiala a<br />

starii compuse <strong>de</strong> la nivelul cel mai <strong>de</strong> sus. Rafinarea unei stari <strong>în</strong> substari concurente<br />

se realizeaza prin împartirea starii <strong>în</strong> mai multe subregiuni care pot avea, optional,<br />

nume.<br />

În [OMG99] se specifica faptul ca un eveniment care nu <strong>de</strong>clanseaza nici o<br />

tranzitie este ignorat. Acest lucru conduce la presupunerea implicita (nu se face nici o<br />

precizare explicita <strong>în</strong> acest sens) ca <strong>în</strong> cadrul unei diagrame <strong>de</strong> stari vor fi trasate<br />

tranzitii pentru toate evenimentele po<strong>si</strong>bile. O astfel <strong>de</strong> abordare este incomoda<br />

<strong>de</strong>oarece reprezentarea grafica a tranzitiilor <strong>de</strong>clansate <strong>de</strong> apelul unui observator <strong>de</strong><br />

exemplu, conduce la <strong>în</strong>carcarea nejustificata a diagramei <strong>de</strong> stari cu câte o<br />

autotranzitie pentru fiecare stare..<br />

O alta <strong>în</strong>trebare care nu î<strong>si</strong> gaseste raspunsul <strong>în</strong> documentele UML este “Ce se<br />

<strong>în</strong>tâmpla atunci când apare un eveniment al carei nume se afla <strong>în</strong> eticheta a cel putin<br />

unei tranzitii din diagrama dar nici una dintre acestea nu poate fi <strong>de</strong>clansata?” Este<br />

acest eveniment retinut, <strong>în</strong>tr-o coada <strong>de</strong> asteptare, <strong>în</strong> ve<strong>de</strong>rea unei tratari ulterioare sau<br />

este ignorat?<br />

În alta ordine <strong>de</strong> i<strong>de</strong>i unei tranzitii îi este asociata o secventa <strong>de</strong> actiuni care se<br />

executa <strong>în</strong> momentul <strong>de</strong>clansarii tranzitiei respective. Poate aparea <strong>în</strong>sa urmatoarea<br />

problema <strong>în</strong> cazul claselor secventiale: ce se <strong>în</strong>tâmpla atunci când exista o tranzitie<br />

<strong>de</strong>clansata <strong>de</strong> un eveniment <strong>de</strong> apelare al unei meto<strong>de</strong> cu garda, iar conditia asociata<br />

108


acesteia se verifica <strong>în</strong>sa garda meto<strong>de</strong>i nu? Specificatiile date <strong>de</strong> UML pot duce la<br />

mai multe raspunsuri, unele dintre ele contradictorii. Spre exemplu ar putea exista<br />

po<strong>si</strong>bilitatea ca tranzitia sa se efectueze, sa fie executata secventa <strong>de</strong> actiuni <strong>în</strong>sa<br />

executia meto<strong>de</strong>i cu garda sa nu se realizeze. În acest caz exista din nou doua<br />

alternative: evenimentul <strong>de</strong> apel <strong>de</strong> operatie este repus <strong>în</strong> coada <strong>de</strong> evenimente sau nu.<br />

Aceste ambiguitati sunt generate <strong>în</strong> mare parte <strong>de</strong> efortul creatorilor UML <strong>de</strong> a<br />

nu intra <strong>în</strong> prea multe <strong>de</strong>talii <strong>si</strong> <strong>de</strong> a nu impune constrângeri <strong>si</strong> restrictii care ar putea<br />

sa reduca din flexibilitatea mo<strong>de</strong>lului (<strong>în</strong> unele cazuri chiar este precizat faptul ca<br />

anumite elemente sunt lasate intentionat la latitudinea proiectantului). Din pacate<br />

acest fapt, la care se adauga <strong>si</strong> absenta unei bune <strong>si</strong>stematizari a informatiilor (<strong>de</strong><br />

exemplu sunt <strong>de</strong>scrise aspecte semantice la prezentarea notatiei), conduc <strong>în</strong> multe<br />

cazuri la abordari gre<strong>si</strong>te <strong>de</strong> mo<strong>de</strong>lare.<br />

4.5. Harti <strong>de</strong> stari scalabile<br />

4.5.1. Mo<strong>de</strong>lul obiect<br />

În cadrul acestei sectiuni vom <strong>de</strong>fini o exten<strong>si</strong>e a hartilor <strong>de</strong> stari pentru<br />

mo<strong>de</strong>larea comportamentului obiectelor active corespunzatoare mo<strong>de</strong>lelor obiect<br />

omogene. Asa cum am aratat <strong>în</strong> capitolul 2, obiectele active din aceasta categorie<br />

<strong>de</strong>tin, alaturi <strong>de</strong> proprietati <strong>si</strong> operatii, un mecanism <strong>de</strong> coordonare <strong>si</strong> planificare a<br />

mesajelor receptionate. Acest mecanism are rolul <strong>de</strong> a proteja con<strong>si</strong>stenta starii<br />

interne a obiectelor <strong>de</strong> accesul concurent al operatiilor la proprietatile acestora.<br />

Protectia se realizeaza implicit, <strong>în</strong> cazul mecanismelor cu control extern (mecan<strong>si</strong>me<br />

<strong>de</strong> tip monitor) sau explicit, prin intermediul constrângerilor <strong>de</strong> <strong>si</strong>ncronizare, <strong>în</strong> cazul<br />

mecanismelor cu control mixt sau reflectiv (meto<strong>de</strong> cu garzi, abstractizarea<br />

comportamentului, multimi <strong>de</strong> operatii acceptabile etc).<br />

109


gestionar <strong>de</strong><br />

interfata<br />

.<br />

.<br />

.<br />

110<br />

Obiect activ<br />

Proprietati<br />

Operatii<br />

Constrângeri <strong>de</strong><br />

<strong>si</strong>ncronizare<br />

coada <strong>de</strong> mesaje<br />

Figura 4.11. Structura unui obiect activ general<br />

În figura 4.11 am reprezentat grafic structura unui obiect activ. Gestionarul <strong>de</strong><br />

interfata reprezinta o entitate speciala <strong>si</strong>tuata la nivelul fiecarui obiect activ. Aceasta<br />

entitate realizeaza controlul <strong>si</strong> planificarea mesajelor receptionate <strong>si</strong> se concretizeaza<br />

la nivelul unui limbaj <strong>de</strong> programare particular printr-un fir <strong>de</strong> executie distinct, un<br />

mecanism <strong>de</strong> blocare sau un obiect <strong>de</strong> <strong>si</strong>ne statator <strong>în</strong>capsulat <strong>în</strong> cadrul obiectelor<br />

active. Gestionarul <strong>de</strong> interfata controleaza tratarea mesajelor prin executia a<strong>si</strong>ncrona<br />

a operatiilor asociate acestora pe baza valorilor proprietatilor (care <strong>de</strong>finesc starea<br />

obiectului), a constrângerilor <strong>de</strong> <strong>si</strong>ncronizare <strong>si</strong>/sau a operatiilor aflate <strong>în</strong> executie la<br />

un moment dat. Planificarea mesajelor este realizata cu ajutorul unei structuri<br />

speciale, numita coada <strong>de</strong> mesaje, care retine toate mesajele receptionate <strong>si</strong> netratate<br />

<strong>de</strong> catre gestionar. Gestionarul <strong>de</strong> interfata, coada <strong>de</strong> mesaje, proprietatile <strong>si</strong><br />

contrângerile <strong>de</strong> <strong>si</strong>ncronizare nu sunt vizibile <strong>în</strong> exterior, <strong>de</strong> catre celelealte obiecte<br />

active care compun un <strong>si</strong>stem. De asemenea, doar un subset <strong>de</strong> operatii care compun<br />

interfata obiectului activ vor fi vizibile, <strong>si</strong> ele pot fi apelate prin intermediul<br />

transmiterii <strong>de</strong> mesaje.<br />

Vom con<strong>si</strong><strong>de</strong>ra ca toate elementele care fac parte din structura unui obiect<br />

activ vor putea fi mostenite sau re<strong>de</strong>finite separat <strong>în</strong> subclase.<br />

Mo<strong>de</strong>lul obiect general <strong>de</strong>scris respecta cele patru principii <strong>de</strong> proiectare<br />

enuntate <strong>în</strong> capitolul doi.


4.5.2. Definirea hartilor <strong>de</strong> stari scalabile<br />

Vom <strong>de</strong>fini hartile <strong>de</strong> stari scalabile <strong>în</strong>tr-o maniera incrementala, pornind <strong>de</strong> la<br />

ma<strong>si</strong>ni <strong>de</strong> stari (pe care le vom numi harti <strong>de</strong> stari scalabile <strong>de</strong> grad 0) <strong>si</strong> adaugând<br />

elemente corespunzatoare tratarii notiunilor <strong>de</strong> adâncime, ortogonalitate, istoric etc.<br />

Pentru fiecare dintre hartile <strong>de</strong> stari intermediare vom <strong>de</strong>fini notiunile <strong>de</strong> configuratie<br />

<strong>si</strong> executie. Abordarea <strong>de</strong> <strong>de</strong>finire va fi una compozitionala, <strong>în</strong> care executia unei<br />

harti <strong>de</strong> stari va reprezenta o compunere a executiei componentelor sale.<br />

Hartile <strong>de</strong> stari scalabile reprezinta o abordare originala <strong>de</strong> mo<strong>de</strong>lare a<br />

obiectelor active, <strong>si</strong> are la baza mo<strong>de</strong>larea utilizata <strong>în</strong> teoria automatelor [MOL97].<br />

Ele sunt strâns legate <strong>de</strong> notiuni ca mesaj, operatie, proprietate sau constrângere <strong>de</strong><br />

<strong>si</strong>ncronizare proprii programarii orientate-obiect concurente. De aceea hartile <strong>de</strong> stari<br />

scalabile sunt o specializare <strong>în</strong>tr-un context orientat-obiect a hartilor <strong>de</strong> stari utilizate<br />

<strong>în</strong> mo<strong>de</strong>larea <strong>si</strong>stemelor reactive <strong>si</strong>, <strong>în</strong> acela<strong>si</strong> timp, extind hartile <strong>de</strong> stari UML cu<br />

elemente specifice mo<strong>de</strong>lul omogen <strong>de</strong> obiecte prezentat <strong>în</strong> subsectiunea 4.5.1.<br />

Harti <strong>de</strong> stari scalabile <strong>de</strong> grad 0 (HSS 0 )<br />

un<strong>de</strong>:<br />

Definitie 1. Definim hartile <strong>de</strong> stari scalabile <strong>de</strong> grad 0 ca fiind tuplul:<br />

HSS 0 = (M, S, s0, SF, T; sa, C),<br />

- M reprezinta o multime finita <strong>de</strong> mesaje. Vom con<strong>si</strong><strong>de</strong>ra, fara a restrânge<br />

din generalitate, ca <strong>si</strong>gnaturile mesajelor nu contin parametrii.<br />

Generalizarea unei harti <strong>de</strong> stari luând <strong>în</strong> con<strong>si</strong><strong>de</strong>rare parametrii <strong>de</strong> mesaje<br />

este imediata, <strong>si</strong> nu afecteaza semantica executiei. Vom nota cu ? mesajul<br />

vid.<br />

- S - multime finita, nevida <strong>de</strong> stari,<br />

- s0 ? S - starea initiala,<br />

- SF – multime finita <strong>de</strong> stari finale. Aceasta poate fi vida, caz <strong>în</strong> care<br />

obiectele mo<strong>de</strong>late nu se vor putea autodistruge,<br />

- T ? S ? M ? (S ? SF) – multime finita <strong>de</strong> tranzitii. O tranzitie (s’, m, s’’)<br />

? T semnifica faptul ca, <strong>în</strong> cazul <strong>în</strong> care un obiect se afla <strong>în</strong> starea sursa s’<br />

<strong>si</strong> receptioneaza mesajul m atunci, dupa tratarea mesajului m (dupa<br />

terminarea executiei operatiei atasate) obiectul se va afla <strong>în</strong> starea<br />

<strong>de</strong>stinatie s’’.<br />

111


- sa ? S - starea activa a hartii <strong>de</strong> stari la un moment dat,<br />

- C ? M*– secventa finita <strong>de</strong> mesaje care mo<strong>de</strong>leaza coada <strong>de</strong> mesaje a unui<br />

obiect activ. Vom nota cu m0^Cr secventa finita <strong>de</strong> mesaje C un<strong>de</strong> m0<br />

reprezinta primul mesaj al secventei, iar Cr restul secventei (<strong>si</strong>mbolul ^<br />

reprezinta operatia <strong>de</strong> concatenare). Acesta va apartine multimii <strong>de</strong> mesaje<br />

M sau va fi mesajul vid, <strong>în</strong> cazul <strong>în</strong> care C este o secventa <strong>de</strong> 0 mesaje.<br />

În figura 4.12 este prezentat un exemplu <strong>de</strong> ma<strong>si</strong>na <strong>de</strong> stari HSS 0 împreuna cu<br />

reprezentarea sa vizuala, care mo<strong>de</strong>leaza comportamentul obiectelor unei clase<br />

particulare, numita Sticla.<br />

specificare vizuala<br />

a starii initiale<br />

HSS 0<br />

Sticla = (M, S, T, s0, SF; C)<br />

M = { Umple, Goleste, Sparge, Capacitate}<br />

S = { Goala, Plina}<br />

T = {(Goala, Umple, Plina),<br />

(Goala, Sparge, F),<br />

(Plina, Goleste, Goala),<br />

(Plina, Sparge, F)}<br />

s0 = Goala<br />

S F = { F }<br />

112<br />

tranzitie<br />

stare<br />

F - stare finala<br />

Figura 4.12. Reprezentarea grafica a hartilor <strong>de</strong> stari HSS 0<br />

Primele 5 elemente ale hartii <strong>de</strong> stari HSS 0 reprezinta componenta statica a<br />

acesteia <strong>si</strong> ele <strong>de</strong>scriu structura hartii <strong>de</strong> stari. Pentru toate obiectele clasei pentru<br />

care s-a <strong>de</strong>finit o harta <strong>de</strong> stari HSS 0 particulara, aceste 5 elemente sunt comune, iar<br />

ele nu se modifica <strong>în</strong> timpul executiei obiectelor. Componenta dinamica este formata<br />

din coada <strong>de</strong> mesaje C. Coada <strong>de</strong> mesaje nu caracterizeaza comportamentul<br />

obiectelor unei clase, ea fiind <strong>în</strong>sa utilizata <strong>în</strong> executia acestora.<br />

Un obiect activ se poate afla la un moment dat <strong>în</strong> una <strong>si</strong> numai una din starile<br />

multimii S <strong>în</strong>tr-o harta <strong>de</strong> stari HSS 0 .<br />

Definitie 2. Vom numi configuratie a hartii <strong>de</strong> stari HSS 0 tuplul:


(sa, m0^Cr) ? S ? M*,<br />

un<strong>de</strong> sa reprezinta starea activa iar m0 primul mesaj aflat <strong>în</strong> coada C la un moment dat.<br />

Configuratie initiala a unei harti <strong>de</strong> stari este data <strong>de</strong> tuplul (s0, ? ).<br />

Executia unui obiect activ mo<strong>de</strong>lat printr-o harta <strong>de</strong> stari HSS 0 presupune<br />

interpretarea succe<strong>si</strong>va a mesajelor existente <strong>în</strong> coada <strong>de</strong> mesaje. Interpretarea unui<br />

mesaj poate avea ca efect modificarea configuratiei hartii <strong>de</strong> stari sau returnarea<br />

mesajului <strong>în</strong> coada <strong>de</strong> mesaje. Vom <strong>de</strong>fini <strong>în</strong> cele ce urmeaza notiunile <strong>de</strong><br />

interpretare a unei configuratii, respectiv executie a unei harti <strong>de</strong> stari HSS 0 .<br />

functia:<br />

Definitie 3. Se numeste interpretare a configuratiei unei harti <strong>de</strong> stari HSS 0<br />

? 0 : S ? M* ? S? SF ? M*,<br />

? 0 ? ( s',<br />

C'r<br />

), daca ? ( sa<br />

, m0,<br />

s')<br />

? T<br />

?<br />

(sa,m0^Cr) = ? ( sa<br />

, C'r<br />

), daca ? s1,<br />

s2<br />

? S : ( s1,<br />

m0,<br />

s2<br />

) ? T .<br />

? ( sa<br />

, C'r<br />

^m0),<br />

in rest<br />

Coada <strong>de</strong> mesaje C poate suferi modificari <strong>în</strong> paralel cu interpretarea unei<br />

configuratii, astfel ca <strong>în</strong> <strong>de</strong>finitia functiei ? data mai sus este po<strong>si</strong>bil ca Cr ? C’r (<strong>de</strong><br />

obicei C’r = Cr^R, un<strong>de</strong> R ? M* reprezinta o secventa <strong>de</strong> mesaje receptionate <strong>de</strong> catre<br />

obiect <strong>în</strong> timpul interpretarii).<br />

Notiunea <strong>de</strong> interpretare a configuratiei mo<strong>de</strong>leaza functionalitatea<br />

gestionarului <strong>de</strong> interfata din cadrul unui obiect activ. Astfel, un mesaj este acceptat,<br />

iar operatia atasata acestuia este executata, <strong>în</strong> cazul <strong>în</strong> care mesajul eticheteaza o<br />

tranzitie ce pleaca din starea activa sau daca acesta nu apare <strong>în</strong> eticheta nici unei<br />

tranzitii a hartii <strong>de</strong> stari. În caz contrar mesajul este reintrodus <strong>în</strong> coada <strong>de</strong> mesaje. În<br />

cazul <strong>în</strong> care <strong>în</strong> cadrul hartii <strong>de</strong> stari exista mai multe tranzitii etichetate cu acela<strong>si</strong><br />

mesaj <strong>si</strong> a caror stare sursa coinci<strong>de</strong> cu starea activa, alegerea unei tranzitii pentru<br />

interpretare se realizeaza <strong>în</strong>tr-o maniera ne<strong>de</strong>terminista. Pentru eliminarea<br />

ne<strong>de</strong>terminismului se pot atasa tranzitiilor prioritati.<br />

Definitia 4. Se numeste executie a unei harti <strong>de</strong> stari HSS 0 o secventa finita<br />

sau infinita <strong>de</strong> interpretari succe<strong>si</strong>ve a configuratiei hartii <strong>de</strong> stari, pornind <strong>de</strong> la<br />

configuratia initiala a acesteia, <strong>si</strong> o vom nota:<br />

(s0, ? ) ? ? ?<br />

? 0<br />

(s1, m1^Cr1) ? ? ?<br />

? 0<br />

113<br />

... ? ? ?<br />

? 0<br />

(sk, mk^Crk) ? ? ?<br />

? 0<br />

... ,


un<strong>de</strong> s0, s1, ..., sk,.. ? S, m1, ..., mk,... ? M <strong>si</strong> Cr1,..., Crk,... ? M*. Executia este finita daca<br />

starea activa <strong>de</strong>vine o stare finala.<br />

urmatoarea:<br />

O executie po<strong>si</strong>bila a unui obiect al clasei Sticla, <strong>de</strong>finita <strong>în</strong> figura 4.12, este<br />

(Goala, ? ) ? ? ?<br />

? 0<br />

(Goala, ) ? ? ?<br />

? 0<br />

(Plina, ) ? ? ?<br />

? 0<br />

(Plina, ) ? ? ?<br />

? 0<br />

(Plina, ) ? ? ?<br />

? 0<br />

114<br />

(F, ).<br />

Coada <strong>de</strong> mesaje C surprinsa <strong>în</strong> <strong>de</strong>finitia hartii <strong>de</strong> stari HSS 0 reprezinta un caz<br />

particular, ales pentru reducerea complexitatii <strong>de</strong>scrierii interpretarii <strong>si</strong> executiei<br />

hartilor <strong>de</strong> stari. Cazurile generale <strong>în</strong> care mecanismele <strong>de</strong> coordonare <strong>si</strong> <strong>si</strong>ncronizare<br />

a <strong>concurentei</strong> permit atasarea <strong>de</strong> prioritati mesajelor, sau care au politici diferite <strong>de</strong><br />

alegere a mesajelor tratabile, pot fi mo<strong>de</strong>late <strong>în</strong>locuind coada <strong>de</strong> mesaje C cu perechea<br />

(C’, pol), un<strong>de</strong> C’ ? M* iar pol este o functie pol : M* ? M care caracterizeaza<br />

politica <strong>de</strong> alegere a unui mesaj din multimea mesajelor receptionate, mo<strong>de</strong>lata <strong>de</strong> C’.<br />

În acest caz vom <strong>în</strong>locui <strong>în</strong> expre<strong>si</strong>ile anterioare care <strong>de</strong>finesc configuratia <strong>si</strong> executia<br />

hartii <strong>de</strong> stari HSS 0 mesajul m0 cu pol(C’).<br />

Harti <strong>de</strong> stari scalabile <strong>de</strong> grad 1 (HSS 1 )<br />

Vom atasa hartilor <strong>de</strong> stari HSS 0 proprietatile <strong>de</strong> adâncime <strong>si</strong> ortogonalitate,<br />

introduse <strong>în</strong> [HAR87]. Deoarece un obiect se va putea afla <strong>în</strong> mai multe stari <strong>si</strong>mple<br />

la un moment dat, stari care se afla <strong>în</strong> componente ortogonale distincte ale unei stari<br />

compuse, se vor modifica <strong>si</strong> <strong>de</strong>finitiile configuratiei, a functiei <strong>de</strong> interpretare a<br />

configuratiei <strong>si</strong> a executiei.<br />

Notiunile <strong>de</strong> adâncime <strong>si</strong> ortogonalitate sunt mo<strong>de</strong>late <strong>în</strong> HSS 1 prin<br />

intermediul unui arbore eterogen, al carui radacina este o stare iar nivelele<br />

intermediare <strong>de</strong> ordin impar sunt ocupate <strong>de</strong> stari, iar cele <strong>de</strong> grad par <strong>de</strong> componente<br />

ortogonale (figura 4.13). Vom con<strong>si</strong><strong>de</strong>ra ca fiecare stare are cel putin o componenta<br />

ortogonala, iar fiecare componenta ortogonala are zero sau sau mai multe sub-stari.<br />

Cele trei tipuri <strong>de</strong> stari introduse <strong>în</strong> [HAR87] vor pute fi mo<strong>de</strong>late <strong>în</strong> mod unitar<br />

astfel:


un<strong>de</strong>:<br />

- o stare <strong>si</strong>mpla este o stare care are o <strong>si</strong>ngura componenta ortogonala,<br />

iar aceasta este vida.<br />

- starea compusa (XOR – stare) are o <strong>si</strong>ngura componenta ortogonala,<br />

nevida.<br />

- starea ortogonala (AND-stare) are mai multe componente ortogonale<br />

nevi<strong>de</strong>.<br />

Definitie 5. Definim hartile <strong>de</strong> stari scalabile <strong>de</strong> grad 1 ca fiind tuplul:<br />

HSS 1 = (M, S, O, sR, SF, (stSucc, stInit, ortSucc), T; Sa, C),<br />

- M este o multime finita <strong>de</strong> mesaje care pot fi receptionate <strong>de</strong> catre<br />

obiectele clasei mo<strong>de</strong>late <strong>de</strong> harta <strong>de</strong> stari,<br />

- S este multimea finita a starilor,<br />

- O este o multime finita <strong>de</strong> componente ortogonale,<br />

- sR ? S este starea radacina a ierarhiei <strong>de</strong> stari,<br />

- SF – multimea finita a starilor finale. Penru a pastra con<strong>si</strong>stenta mo<strong>de</strong>lului<br />

vom impune ca toate starile finale sa se afle <strong>în</strong> componente ortogonale ale<br />

starii radacina sR, adica ? sf ? SF, stPred(ortPred(sf)) = sR. Vom elimina<br />

astfel tranzitiile <strong>de</strong> terminare specificate <strong>în</strong> UML, fara <strong>în</strong>sa a restrânge<br />

puterea <strong>de</strong> mo<strong>de</strong>lare a hartilor <strong>de</strong> stari.<br />

- functii <strong>de</strong> <strong>de</strong>finire a ierarhiei <strong>de</strong> stari <strong>si</strong> componente ortogonale:<br />

- stSucc : O ? ? (S? SF), un<strong>de</strong> stSucc(o) = {s1, s2, ... , sn} reprezinta<br />

multimea substarilor componentei ortogonale o, cu restrictia ca ? o1,<br />

o2 ? O vom avea stSucc(o1) ? stSucc(o2) = ? ;<br />

- stInit : O\{o : stSucc(o)=? } ? S, stInit(o) = s0 ? stSucc(o), sub-<br />

starea initiala a componentei ortogonale o (functia se aplica doar<br />

pentru componentele ortogonale nevi<strong>de</strong>);<br />

- ortSucc : S ? ? (O) \ {? }, un<strong>de</strong> ortSucc(s) = {o1, o2, ... , om}<br />

reprezinta multimea componentelor ortogonale ale starii s, cu<br />

restrictia ca ? s1, s2 ? S vom avea ortSucc(s1) ? ortSucc(s2) = ? (o<br />

stare are cel putin o componenta ortogonala);<br />

- T ? ? (S\{sR}) ? M ? ? (S\{sR}) multime finita <strong>de</strong> tranzitii. O tranzitie<br />

({s1’, ..., <strong>si</strong>’}, m, { s1’’, ..., sj’’}) ? T semnifica faptul ca, <strong>în</strong> cazul <strong>în</strong> care un<br />

115


obiect se afla <strong>în</strong> starile sursa s1’, ..., <strong>si</strong>’ ? S\{sR} (fiecare dintre acestea<br />

aflate <strong>în</strong> componentele ortogonale distincte ale unei stari) <strong>si</strong> receptioneaza<br />

mesajul m atunci, dupa tratarea mesajului m obiectul se va afla <strong>în</strong> starile<br />

<strong>de</strong>stinatie s1’’, ..., sj’’ ? S\{sR} (la rândul lor apartinând unui numar j <strong>de</strong><br />

componente ortogonale distincte ale unei stari). Starea radacina nu poate<br />

fi nici sursa nici <strong>de</strong>stinatie a unei tranzitii, iar multimea starilor sursa <strong>si</strong><br />

multimea starilor <strong>de</strong>stinatie nu contin stari care sa se includa.<br />

- Sa ? S? SF - multimea starilor active ale hartii <strong>de</strong> stari la un moment dat,<br />

care are proprietatea ca ? sa ? Sa, ortSucc(sa) = ? .<br />

- C ? M*– secventa finita <strong>de</strong> mesaje care mo<strong>de</strong>leaza coada <strong>de</strong> mesaje a unui<br />

obiect activ.<br />

HSS 1<br />

Sticla = (M, S, O, sR, SF, (stSucc, stInit, ortSucc ), T; C)<br />

M = { Umple, Goleste, Sparge, Capacitate}<br />

S = { Sticla, Normal, Goala, Plina}<br />

O = { o1, o2, o3, o4 }<br />

s R = Sticla<br />

S F = { F }<br />

116<br />

starea initiala<br />

pentru o1<br />

starea initiala<br />

pentru o2<br />

o2<br />

o1<br />

o3 o4<br />

stSucc : { o1, o2, o3, o4 } ? ? ({ Sticla, Normal, Goala, Plina, F}),<br />

stSucc(o1) = {Normal, F}, stSucc(o2) = {Goala, Plina},<br />

stSucc(o 3) = ? , stSucc (o 4) =? ;<br />

stInit : { o1, o2 } ? { Sticla, Normal, Goala, Plina},<br />

stInit(o1) = Normal, stInit(o2) = Goala,<br />

ortSucc : { Sticla, Normal, Goala, Plina } ? ? ({ o1, o2, o3, o4 }) \ {? },<br />

ortSucc (Sticla) = {o1 }, ortSucc (Normal) = {o2 },<br />

ortSucc (Goala) = {o3 }, ortSucc (Plina) = {o4 },<br />

T = {({Goala}, Umple , {Plina}), ({Plina}, Goleste, {Goala}),<br />

({Normal}, Sparge, {F}) }<br />

Figura 4.13. Reprezentarea grafica a hartilor <strong>de</strong> stari HSS 1<br />

Pe baza functiilor stSucc <strong>si</strong> ortSucc putem <strong>de</strong>fini alte doua functii care<br />

<strong>de</strong>termina parintii directi ai unei stari sau componente ortogonale.


Definitie 6. Fie stPred : O ? S , un<strong>de</strong> stPred(o) = s ? S daca o ? ortSucc(s) <strong>si</strong><br />

reprezinta reprezinta starea parinte a componentei ortogonale o ? O. De asemenea,<br />

<strong>de</strong>finim functia ortPred : S? SF \{sR} ? O, un<strong>de</strong> pentru o stare s ? S? SF \{sR},<br />

ortPred(s) = o ? O daca s ? stSucc(o), <strong>si</strong> reprezinta componenta ortogonala <strong>în</strong> care<br />

este inclusa starea s.<br />

Faptul ca multimile rezultat ale functiilor stSucc <strong>si</strong> ortSucc sunt disjuncte doua<br />

câte doua, asa cum se specifica <strong>în</strong> <strong>de</strong>finitia 5, a<strong>si</strong>gura faptul ca functiile stPred <strong>si</strong><br />

ortPred sunt bine <strong>de</strong>finite.<br />

Deoarece <strong>de</strong>scrierea unei tranzitii <strong>în</strong> cadrul <strong>de</strong>finitiei hartii <strong>de</strong> stari HSS 1 este<br />

realizata <strong>în</strong>tr-o maniera informala, <strong>în</strong> cele ce urmeaza vom specifica formal conceptul<br />

<strong>de</strong> tranzitie valida. Pentru a realiza acest lucru vom <strong>de</strong>fini relatia <strong>de</strong> <strong>în</strong>cuibarire dinte<br />

starile <strong>si</strong> componentele ortogonale ale unei harti <strong>de</strong> stari.<br />

Definitie 7. Doua elemente so1, so2 ? S? O se afla <strong>în</strong> relatia <strong>de</strong> <strong>în</strong>cuibarire,<br />

notata prin so1 so2, daca <strong>si</strong> numai daca una din afirmatiile urmatoare este a<strong>de</strong>varata:<br />

a) so1=so2,<br />

b) so1 ? S ? so2? S ? ? n ?<br />

c) so1 ? O ? so2? O ? ? n ?<br />

+<br />

a. î. so2<br />

st Pr ed ( ort Pr ed (... so1...))<br />

117<br />

? ,<br />

n<br />

+<br />

a. î. so2<br />

ort Pr ed ( st Pr ed (... so1...))<br />

n<br />

ori<br />

? ,<br />

d) so1 ? S ? so2? O ? ? n ? a. î. so ? ort ed(<br />

st Pr ed(...<br />

ort Pred<br />

( so )...)) ,<br />

2<br />

ori<br />

Pr 1<br />

e) so1 ? O ? so2? S ? ? n ? a. î. so ? st ed ( ort Pr ed (... st Pred<br />

( so )...)) .<br />

<strong>în</strong>cuibaririi.<br />

so<br />

2<br />

2<br />

n ori<br />

Pr 1<br />

Propozitie 1. Relatia <strong>de</strong> <strong>în</strong>cuibarire este ordine partiala peste multimea S? O.<br />

Demonstratie. Reflexivitatea este a<strong>si</strong>gurata <strong>de</strong> conditia a) a <strong>de</strong>finitiei<br />

Fie so1, so2, so3 ? S, <strong>si</strong> so1 so2 <strong>si</strong> so2 so3. Rezulta ca ? n ?<br />

? st ed ( ort Pr ed (... so ...)) <strong>si</strong> ? m ?<br />

Pr 1<br />

n<br />

ori<br />

Prin urmare ? r= n + m ?<br />

n ori<br />

+ a. î.<br />

+<br />

a. î. so3<br />

st Pr ed(<br />

ort Pred<br />

(... so2...))<br />

? .<br />

m ori<br />

+<br />

, a.î. so3<br />

st Pr ed(<br />

ort Pred<br />

(... so1...))<br />

adica relatie <strong>de</strong> <strong>în</strong>cuibarire este tranzitiva peste S.<br />

? , <strong>de</strong>ci so1 so3,<br />

r ? m?<br />

n ori


În mo<strong>de</strong> analog se <strong>de</strong>monstreaza tranzitivitatea <strong>si</strong> <strong>în</strong> celelalte sapte cazuri <strong>în</strong><br />

care so1, so2, so3 sunt fie stari fie componente ortogonale.<br />

Vom <strong>de</strong>monstra <strong>în</strong> continuare faptul ca relatia <strong>de</strong> <strong>în</strong>cuibarire este anti<strong>si</strong>metrica<br />

pentru so1, so2 ? S.<br />

Vom presupunem asadar ca so1 so2 <strong>si</strong> so2 so1. Acest lucru implica faptul<br />

ca so1 = so2 sau ? n, m ?<br />

so<br />

2<br />

+ a. î.:<br />

? st ed ( ort Pr ed (... so ...)) <strong>si</strong> so ? st ed ( ort Pred<br />

(... so ...)) .<br />

Pr 1<br />

n<br />

ori<br />

118<br />

1<br />

Pr 2<br />

m ori<br />

Vom presupune ca so1 ? so2. Prin urmare ? r= n + m ?<br />

so<br />

1<br />

? st ed ( ort Pr ed (... so ..)) .<br />

Pr 1<br />

r ori<br />

+ a. î.:<br />

Din <strong>de</strong>finitia hartii <strong>de</strong> stari HSS 1 rezulta ca egalitatea anterioara are loc doar <strong>în</strong><br />

cazul <strong>în</strong> care r=0. Am presupus <strong>în</strong>sa ca r ?<br />

+ . Rezulta ca<br />

so1 so2 ? so2 so1 ? so1 = so2.<br />

Deci relatia <strong>de</strong> <strong>în</strong>cuibarire este anti<strong>si</strong>metrica peste multimea S. Pentru celelalte<br />

trei cazuri (so1, so2 ? O, so1 ? O <strong>si</strong> so2 ? S, so1 ? S <strong>si</strong> so2 ? O) <strong>de</strong>monstratia se<br />

realizeaza <strong>în</strong> mod analog. Prin urmare relatia (S? O, ) este reflexiva, tranzitiva <strong>si</strong><br />

anti<strong>si</strong>metrica, <strong>de</strong>ci este o relatie <strong>de</strong> ordine partiala. ?<br />

Definitie 8. Pentru o stare sau componenta ortogonala so ? S? O se <strong>de</strong>fineste<br />

multimea tuturor pre<strong>de</strong>cesorilor sai ca fiind:<br />

PREDso = { so' : so' ? S? O , so so' }.<br />

Propozitie 2. Oricare ar fi so ? S? O, (PREDso, ) este ordine totala.<br />

Demonstratie. Conform propozitiei 1, relatia (PREDso, ) este ordine<br />

partiala. Fie so', so'' ? PREDso ? S. Rezulta, conform <strong>de</strong>finitiei multimii<br />

succesorilor, ca:<br />

? n' ?<br />

? n'' ?<br />

+ a. î. ...))<br />

so'<br />

? st Pr ed(<br />

ord Pr ed(...<br />

so <strong>si</strong><br />

n'<br />

ori<br />

+<br />

a. î. so''<br />

st Pr ed ( ort Pr ed(...<br />

so...))<br />

? .<br />

n''<br />

ori<br />

Vom presupune <strong>în</strong> continuare ca n' > n''. Rezulta ca :<br />

? n'' ?<br />

+<br />

a. î. so''<br />

st Pr ed ( ort Pr ed(...<br />

so'...))<br />

? ,<br />

n '?<br />

n''<br />

ori


<strong>si</strong> <strong>de</strong>ci so' so''. În mod analog se <strong>de</strong>monstreaza existenta relatiei <strong>de</strong> <strong>în</strong>cuibarire <strong>si</strong><br />

<strong>în</strong>tre celelalte trei po<strong>si</strong>bile tipuri <strong>de</strong> perechi <strong>de</strong> elemente ale multimii PREDso.<br />

Prin urmare ? so', so'' ? PREDso so' so'' sau so'' so' , <strong>de</strong>ci relatia <strong>de</strong><br />

<strong>în</strong>cuibarire peste multimea PREDso este ordine totala. ?<br />

Deoarece (PREDso, ) este ordine totala, iar multimea PREDso este finita,<br />

rezulta ca exista o cea mai mare limita inferioara pentru PREDso <strong>si</strong> aceasta apartine lui<br />

PREDso. Vom nota aceasta limita inferioara prin pPREDso. Vom <strong>de</strong>monstra <strong>în</strong><br />

continuare ca pPREDso reprezinta parintele direct al elementului so.<br />

Propozitie 3. Fie so ? S? O. Este a<strong>de</strong>varata una din urmatoare afirmatii:<br />

a) so ? S ? ortPred(so) = p PREDso,<br />

b) so ? O ? stPred(so) = p PREDso.<br />

Demonstratie. a) Fie so ? S. Este evi<strong>de</strong>nt faptul ca so ortPred(so), iar pe<br />

baza <strong>de</strong>finitiei multimii PREDso vom avea ca ortPred(so) ? PREDso.<br />

Fie un element oarecare so' ? PREDso. Din <strong>de</strong>finitia 8 avem ca so so'.<br />

Daca so' reprezinta o componenta ortogonala, atunci ? n ? a. î.<br />

so'<br />

? ort Pr ed ( st Pr ed (... ort Pr ed(<br />

so)...))<br />

,<br />

n ori<br />

<strong>de</strong> un<strong>de</strong> rezulta ca ortPred(so) so'. În mod analog se <strong>de</strong>monstreaza ca are loc<br />

relatia <strong>de</strong> <strong>în</strong>cuibarire <strong>în</strong>tre ortPred(so) <strong>si</strong> so' pentru cazul <strong>în</strong> care so' este o stare.<br />

Deoarece so' a fost un element al multimii PREDso ales aleator, rezulta ca<br />

Rezulta ca ortPred(so) = p PREDso.<br />

? so' ? PREDso , ortPred(so) so'.<br />

Afirmatia b) se <strong>de</strong>monstreaza <strong>în</strong> mod analog. ?<br />

Definitie 9. Fie doua stari sau componente ortogonale so', so'' ? S. Spunem<br />

ca so' <strong>si</strong> so'' sunt ortogonale daca ele nu se afla <strong>în</strong> relatia <strong>de</strong> <strong>în</strong>cuibarire <strong>si</strong><br />

p (PREDso' ? PREDso'') ? S.<br />

Cu alte cuvinte, doua sau mai multe stari sunt ortogonale daca ele nu se contin<br />

reciproc <strong>si</strong> cel mai apropiat parinte comun este o stare.<br />

Definitie 10. Fie t = ({s'i ? S : i = 1..n}, m, {s''j ? S : j = 1..m}) ? T o tranzitie.<br />

Tranzitia t este valida daca sunt a<strong>de</strong>varate urmatoarele afirmatii:<br />

119


a) Ps' = p<br />

b) Ps'' = p<br />

i?<br />

n<br />

1<br />

j?<br />

m<br />

1<br />

PRED ? S, (starile sursa sunt ortogonale),<br />

s'i PRED ? S, (starile <strong>de</strong>stinatie sunt ortogonale),<br />

s''j<br />

c) Ps' <strong>si</strong> Ps'' nu se includ reciproc <strong>si</strong> p (PREDPs' ? PREDPs'') ? O. (starile<br />

sursa <strong>si</strong> starile <strong>de</strong>stinatie nu sunt ortogonale).<br />

Vom numi domt = p (PREDPs' ? PREDPs'') ? O domeniul tranzitiei t.<br />

Prin urmare domeniul unei tranzitii reprezinta cea mai mica componenta<br />

ortogonala care contine toate starile sursa <strong>si</strong> <strong>de</strong>stinatie ale acesteia.<br />

Pentru exemplul ilustrat <strong>în</strong> figura 4.13, un obiect al clasei Sticla care se afla <strong>în</strong><br />

starea Plina, se afla <strong>în</strong> acela<strong>si</strong> timp, conform ierarhiei construite, <strong>si</strong> <strong>în</strong> starile Normal<br />

<strong>si</strong> Sticla. Prin urmare, conform <strong>de</strong>finitiei 2 toate aceste stari reprezinta stari active ale<br />

hartii <strong>de</strong> stari. Pentru a putea <strong>de</strong>fini <strong>în</strong> mod unic configuratia unei harti <strong>de</strong> stari HSS 1<br />

la un moment dat vom extin<strong>de</strong> notiunea <strong>de</strong> stare activa luând <strong>în</strong> con<strong>si</strong><strong>de</strong>rare notiunile<br />

<strong>de</strong> adâncime <strong>si</strong> ortogonalitate.<br />

Asa cu rezulta din <strong>de</strong>fintia 5, o stare activa a hartii <strong>de</strong> stari HSS 1 reprezinta o<br />

stare <strong>în</strong> care se poate afla un obiect la un moment dat, <strong>si</strong> care are proprietatea ca este<br />

stare <strong>si</strong>mpla (cu o <strong>si</strong>ngura componenta ortogonala vida). Conform <strong>de</strong>finitiei 5, pentru<br />

exemplul din figura 4.13 <strong>si</strong>ngurele stari care pot fi stari active pentru un obiect al<br />

clasei Sticla sunt Goala, Plina <strong>si</strong> F.<br />

Definitie 11. Numim stare pseudo-activa o stare compusa care contine o sub-<br />

stare activa. Vom nota cu Spa multimea tuturor starilor pseudo-active ale unui obiect<br />

mo<strong>de</strong>lat printr-o harta <strong>de</strong> stari HSS 1 .<br />

O harta <strong>de</strong> stari HSS 1 poate avea mai multe stari active, fiecare dintre acestea<br />

aflate <strong>în</strong> componente ortogonale distincte ale unei stari pseudo-active. În mod evi<strong>de</strong>nt<br />

starea radacina sR este stare pseudo-activa pe toata perioada ciclului <strong>de</strong> viata al unui<br />

obiect.<br />

Intrarea unui obiect <strong>în</strong>tr-o stare compusa va <strong>de</strong>termina activarea substarilor<br />

initiale ale acesteia. Vom <strong>de</strong>fini <strong>în</strong> continuare o functie recur<strong>si</strong>va care va fi utilizata <strong>în</strong><br />

<strong>de</strong>terminarea starilor ce se vor activa la intrarea <strong>în</strong>tr-o stare compusa.<br />

120


Definitie 12. Vom numi functie <strong>de</strong> activare functia care va asocia fiecarei stari<br />

s multimea sub-starilor <strong>si</strong>mple sau finale ale acesteia care se vor activa implicit <strong>în</strong><br />

momentul <strong>în</strong> care un obiect va intra <strong>în</strong> starea s. Vom nota aceasta functie:<br />

activ : S ? SF ? ? (S ? SF),<br />

? { s},<br />

daca(<br />

s ? S,<br />

ortSucc(<br />

s)<br />

? { o},<br />

stSucc(<br />

o)<br />

? ? ) sau s ? SF<br />

?<br />

activ ( s)<br />

? ? activ(<br />

stInit(<br />

o)),<br />

in rest<br />

.<br />

? o?<br />

ortSucc(<br />

s)<br />

Vom <strong>de</strong>fini <strong>de</strong> asemenea functia <strong>de</strong> activare globala, Activ : ? (S ? SF) ? ? (S ? SF)<br />

Activ(S') =<br />

s?<br />

S'<br />

activ(<br />

s)<br />

.<br />

Definiti 13. Numim configuratie a unei harti <strong>de</strong> stari HSS 1 tuplul ( Sa, m0^Cr),<br />

un<strong>de</strong> Sa ? S reprezinta multimea starilor active, iar m0^Cr ? M* reprezinta continutul<br />

cozii <strong>de</strong> mesaje C la un moment dat. Configuratia initiala a unei harti <strong>de</strong> stari este<br />

(active(sR), ? ).<br />

functia:<br />

Definitie 14. Se numeste interpretare a configuratiei unei harti <strong>de</strong> stari HSS 1<br />

? 1 : ? (S) ? M* ? ? (S? SF) ? M*,<br />

? 1 ? ( Activ(<br />

S''<br />

), C'<br />

r ), daca ( S',<br />

m0,<br />

S'<br />

')<br />

? T <strong>si</strong> S'?<br />

?<br />

(Sa,m0^Cr) = ? ( S a,<br />

C'r<br />

), daca ? S1,<br />

S2<br />

? S : ( S1,<br />

m0,<br />

S2<br />

) ? T<br />

? ( Sa<br />

, C'<br />

r ^m0),<br />

in rest<br />

Definitia 15. Se numeste executie a unei harti <strong>de</strong> stari HSS 1 o secventa finita<br />

sau infinita <strong>de</strong> interpretari succe<strong>si</strong>ve a configuratiei hartii <strong>de</strong> stari, pornind <strong>de</strong> la<br />

configuratia initiala a acesteia, <strong>si</strong> o vom nota:<br />

(active(sR), ? ) ? ? ?<br />

? 1<br />

(S1, m1^Cr1) ? ? ?<br />

? 1<br />

121<br />

... ? ? ?<br />

? 1<br />

S<br />

a<br />

?<br />

(Sk, mk^Crk) ? ? ?<br />

? 1<br />

un<strong>de</strong> S1, ..., Sk,.. ? S, m1, ..., mk,... ? M <strong>si</strong> Cr1,..., Crk,... ? M*. Executia este finita daca<br />

multimea starilor active <strong>de</strong>tine o stare finala.<br />

urmatoarea:<br />

O executie po<strong>si</strong>bila a unui obiect al clasei Sticla, <strong>de</strong>finita <strong>în</strong> figura 4.13, este<br />

({Goala}, ? ) ? ? ?<br />

? 1<br />

({Goala}, ) ? ? ?<br />

? 1<br />

({Goala}, ) ? ? ?<br />

? 1<br />

({Plina}, ) ? ? ?<br />

? 1<br />

S<br />

pa<br />

.<br />

... ,


({Plina}, ) ? ? ?<br />

? 1<br />

({F},? ).<br />

Harti <strong>de</strong> stari scalabile <strong>de</strong> grad 2 (HSS 2 )<br />

122<br />

({Goala},) ? ? ?<br />

? 1<br />

Hartile <strong>de</strong> stari HSS 1 nu permit <strong>de</strong>clansarea <strong>în</strong> paralel a mai multor tranzitii.<br />

Prin urmare hartile HSS 1 nu pot fi utilizate <strong>în</strong> mo<strong>de</strong>larea <strong>concurentei</strong> interne a<br />

obiectelor active. De asemenea, hartile <strong>de</strong> stari scalabile <strong>de</strong> grad 1 nu permit<br />

mo<strong>de</strong>larea <strong>si</strong>ncronizarilor conditionale sau a constrângerilor <strong>de</strong> <strong>si</strong>ncronizare.<br />

Vom extin<strong>de</strong> <strong>în</strong> cele ce urmeaza hartile <strong>de</strong> stari HSS 1 cu noi elemente care sa<br />

permita specificarea invariantilor pentru stari, a conditiilor <strong>de</strong> <strong>de</strong>clansare a tranzitiilor<br />

precum <strong>si</strong> pentru tratarea concurenta a mai multr mesaje din coada <strong>de</strong> mesaje.<br />

un<strong>de</strong>:<br />

Definitie 16. Definim hartile <strong>de</strong> stari scalabile <strong>de</strong> grad 2 ca fiind tuplul:<br />

HSS 2 =(M, S, O, P, E, sR, SF, (stSucc, stInit, ortSucc,), inv, T; eval, par, Sa, C)<br />

- M, S, O, sR, SF, (stSucc, stInit, ortSucc), Sa, C au semnificatiile <strong>de</strong>scrise <strong>în</strong><br />

<strong>de</strong>finitia 5,<br />

- P reprezinta o multime finita <strong>de</strong> proprietati,<br />

- E multime finita <strong>de</strong> expre<strong>si</strong>i logice ai caror operanzi includ constante<br />

numerice <strong>si</strong> booleene, <strong>si</strong>ruri <strong>de</strong> caractere <strong>si</strong> proprietati. Operatorii utilizati<br />

<strong>în</strong> aceste expre<strong>si</strong>i sunt cei caracteristici tipurilor <strong>de</strong> operanzi la care se<br />

adauga operatorii logici ? (negatie), ? (conjunctie) <strong>si</strong> ? (disjunctie).<br />

- inv reprezinta o functie inv : S ? E, care asociaza fiecarei stari o expre<strong>si</strong>e<br />

logica. Aceaste expre<strong>si</strong>i logice poarta numele <strong>de</strong> invarianti <strong>de</strong> stare <strong>si</strong> ele<br />

sunt evaluate ca a<strong>de</strong>varate atunci când un obiect se va afla <strong>în</strong> starile<br />

asociate.<br />

- T ? ? (S\{sR}) ? M ? E ? ? (S\{sR}) este o multime finita <strong>de</strong> tranzitii<br />

vali<strong>de</strong>. O tranzitie ({s1’, ..., <strong>si</strong>’}, m, e, { s1’’, ..., sj’’}) ? T are semnificatia<br />

specificata <strong>în</strong> <strong>de</strong>finitia 5 iar expre<strong>si</strong>a e reprezenta conditia <strong>de</strong> <strong>de</strong>clansare a<br />

tranzitiei.<br />

- eval reprezinta o functie <strong>de</strong> evaluare a expre<strong>si</strong>ilor logice, eval : E ? ,<br />

un<strong>de</strong> pentru e? E, eval(e) reprezinta valoarea <strong>de</strong> a<strong>de</strong>var a expre<strong>si</strong>e e la un<br />

moment dat. Deoarece valoarea unei expre<strong>si</strong>i <strong>de</strong>pin<strong>de</strong> <strong>de</strong> valorile


proprietatilor care o compun, functia eval face parte din componenta<br />

dinamica a hartii <strong>de</strong> stari, fiind utilizata <strong>în</strong> faza <strong>de</strong> executie a acesteia.<br />

- par : M* ? ? (M) este tot o functie care face parte din componenta<br />

dinamica, <strong>si</strong> ea impune politica <strong>de</strong> alegere a unei multimi <strong>de</strong> mesaje din<br />

coada <strong>de</strong> mesaje <strong>în</strong> raport cu configuratia hartii <strong>de</strong> stari.<br />

Functia par caracterizeaza algoritmul <strong>de</strong> alegere al unei multimi <strong>de</strong> mesaje.<br />

Specificarea unei astfel <strong>de</strong> functii nu este importanta <strong>în</strong> aceasta faza <strong>de</strong> formalizare a<br />

executiei hartilor <strong>de</strong> stari. Ea este impusa <strong>de</strong> mecanismele particulare implementate<br />

<strong>în</strong> diverse limbaje <strong>de</strong> programare orientate-obiect concurente. Vom impune doar ca<br />

multimea mesajelor returnate <strong>de</strong> aceasta functie sa contina numarul maxim <strong>de</strong> mesaje<br />

care pot fi tratate concurent la un moment dat.<br />

Figura 4.14. Reprezentarea grafica a hartilor <strong>de</strong> stari HSS 2<br />

Pentru a <strong>de</strong>fini interpretarea unei configuratii prin tratarea paralela a mai<br />

multor mesaje vor trebui <strong>de</strong>terminate tranzitiile care nu se influenteaza reciproc <strong>si</strong><br />

care pot fi <strong>de</strong>clansate <strong>în</strong> paralel. Astfel <strong>de</strong> tranzitii vor avea starile sursa <strong>si</strong> <strong>de</strong>stinatie<br />

123


incluse <strong>în</strong> componente ortogonale distincte <strong>si</strong> le vom numi tranzitii in<strong>de</strong>pen<strong>de</strong>nte. De<br />

exemplu, pentru harta <strong>de</strong> stari din figura 4.14, tranzitiile etichetate cu ScoateEticheta<br />

<strong>si</strong> Goleste vor putea fi <strong>de</strong>clansate concurent, fara a se afecta reciproc.<br />

Definitie 17. Doua tranzitii t', t'' ? T sunt in<strong>de</strong>pen<strong>de</strong>nte daca <strong>si</strong> numai daca<br />

domeniile lor sunt ortogonale, adica p (PREDdom '<br />

124<br />

t ? PRED dom t ''<br />

) ? S.<br />

Definiti 18. Numim configuratie a unei harti <strong>de</strong> stari HSS 2 tuplul ( Sa, par(C),<br />

Cr), un<strong>de</strong> Sa ? S reprezinta multimea starilor active, par(C) multimea mesajelor din<br />

coada <strong>de</strong> mesaje ce urmeaza a fi tratate <strong>în</strong> paralel, iar Cr ? M* reprezinta "restul"<br />

cozii <strong>de</strong> mesaje C <strong>în</strong> urma extragerii mesajelor din par(C). Configuratia initiala a<br />

unei harti <strong>de</strong> stari este (active(sR), ? ).<br />

functia:<br />

Definitie 19. Se numeste interpretare a configuratiei unei harti <strong>de</strong> stari HSS 2<br />

? 2 : ? (S) ?? (M) ? M* ? ? (S? SF) ? M*,<br />

? 2 (Sa,{m1,...,mn},Cr) =<br />

i?<br />

1<br />

?<br />

? ( Activ(<br />

Si<br />

''),<br />

C'<br />

r ), daca ? i ? { 1,..,<br />

n}<br />

? ( Si<br />

',<br />

mi,<br />

ei,<br />

Si<br />

'')<br />

? T in<strong>de</strong>pen<strong>de</strong>nte,<br />

?<br />

n<br />

= ?<br />

Si<br />

'?<br />

Sa<br />

? S pa <strong>si</strong> eval(<br />

ei<br />

) ? true<br />

.<br />

? ( Sa<br />

, C'r<br />

), daca ? i ? { 1,..,<br />

n}<br />

? S1,<br />

S 2 ? S,<br />

e ? E : ( S1,<br />

mi,<br />

e,<br />

S2<br />

) ? T<br />

?<br />

? ( Sa<br />

, C'r<br />

^m1<br />

^...^mn<br />

), in rest<br />

Definitia 20. Se numeste executie a unei harti <strong>de</strong> stari HSS 2 o secventa finita<br />

sau infinita <strong>de</strong> interpretari succe<strong>si</strong>ve a configuratiei hartii <strong>de</strong> stari, pornind <strong>de</strong> la<br />

configuratia initiala a acesteia, <strong>si</strong> o vom nota:<br />

(active(sR), ? , ? ) ? ? ?<br />

? 2<br />

(S1, par(C),Cr1) ? ? ?<br />

? 2<br />

... ? ? ?<br />

? 2<br />

(Sk, par(C),Crk) ? ? ?<br />

? 2<br />

un<strong>de</strong> S1, ..., Sk,.. ? S, <strong>si</strong> Cr1,..., Crk,... ? M*. Executia este finita daca multimea starilor<br />

active <strong>de</strong>tine o stare finala.<br />

Figura 4.15. reprezinta <strong>de</strong>scrierea hartii <strong>de</strong> starii HSS 2 pentru clasa Sticla a<br />

carei structura a fost <strong>de</strong>scrisa <strong>în</strong> figura 4.14. O executie po<strong>si</strong>bila a acestei harti <strong>de</strong> stari<br />

este urmatoarea:<br />

({Goala}, ? ) ? ? ?<br />

? 1<br />

({Goala}, ) ? ? ?<br />

? 1<br />

({Goala}, ) ? ? ?<br />

? 1<br />

({Plina}, ) ? ? ?<br />

? 1<br />

...


({Plina}, ) ? ? ?<br />

? 1<br />

({F},? ).<br />

125<br />

({Goala},) ? ? ?<br />

? 1<br />

HSS 2<br />

Sticla = (M, S, O, P, E, sR, SF, (stSucc, stInit, ortSucc,), inv, T; eval, par, C)<br />

M = { Umple, Goleste, Sparge, Capacitate, AdaugaEticheta, ScoateEticheta}<br />

S = { Sticla, Normal, Goala, Plina, FaraEticheta, CuEticheta}<br />

O = { o1, o2, o3, o4, o5, o6, o7 }<br />

P = {capacitate, continut, eticheta}<br />

E = {e1=(0? continut ? continut ? capacitate), e2=(continut < capacitate),<br />

e3 = (continut = capacitate), e4 = (continut + 5 < capacitate),<br />

e5 = (continut + 5 ? capacitate), e6 = (eticheta),<br />

e7 = (? eticheta), e8 = ( true )}<br />

sR = Sticla<br />

S F = { F }<br />

stSucc : { oi, i=1..7 } ? ? ({ Sticla, Normal, Goala, Plina, F}),<br />

stSucc(o 1) = {Normal, F}, stSucc(o 2) = {Goala, Plina},<br />

stSucc(o3) = {FaraEticheta, CuEticheta},<br />

stSucc(o 4) = stSucc(o 5) = stSucc(o 6) = stSucc(o 7) =? ;<br />

stInit : { o1, o2, o3} ? { Sticla, Normal, Goala, Plina, CuEticheta, FaraEticheta},<br />

stInit(o1) = Normal, stInit(o2) = Goala, stInit(o3) = FaraEticheta,<br />

ortSucc : { Sticla, Normal, Goala, Plina } ? ? ({ o i, i=1..7 }) \ {? },<br />

ortSucc (Sticla) = {o 1 }, ortSucc (Normal) = { o 2 , o 3 },<br />

ortSucc (Goala) = {o4 }, ortSucc (Plina) = {o5 },<br />

ortSucc (FaraEticheta) = {o 6 }, ortSucc (CuEticheta) = {o 7 },<br />

inv : S ? E,<br />

inv(Sticla) = e 1, inv(Normal) = e 8, inv(Goala) = e 2,<br />

inv(Plina) = e3, inv(CuEticheta) = e6, inv(FaraEticheta) = e7,<br />

T = {({Goala}, Umple , e 4, {Goala}), ({Goala}, Umple, e 5, {Plina}),<br />

({Plina}, Goleste, {Goala}),<br />

({FaraEticheta}, AdaugaEticheta, e8, { CuEticheta }),<br />

({CuEticheta }, ScoateEticheta, e 8, { FaraEticheta }),<br />

({Normal}, Sparge, e8, {F}) }<br />

Figura 4.15. Exemplu <strong>de</strong> harta <strong>de</strong> stari HSS 2<br />

4.5.3. Executabilitatea hartilor <strong>de</strong> stari scalabile<br />

Ciclul <strong>de</strong> viata a unei aplicatii are mai multe etape distincte: <strong>de</strong> specificare,<br />

<strong>analiza</strong>, proiectare, <strong>implementare</strong>, testare <strong>si</strong> <strong>în</strong>tretinere.<br />

În cadrul acestei sectiuni ne-am preocupat <strong>în</strong> principal <strong>de</strong> trecerea <strong>de</strong> la un<br />

mo<strong>de</strong>l abstract al unei aplicatii, rezultat <strong>în</strong> urma etapelor <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare, la<br />

mo<strong>de</strong>lul <strong>de</strong> <strong>implementare</strong> al acesteia. Acest lucru a fost realizat prin <strong>de</strong>finirea<br />

riguroasa a notiunii <strong>de</strong> executie a hartii <strong>de</strong> stari scalabile.<br />

Implementarea unui prototip al unei aplicatii pe baza unui mo<strong>de</strong>l nece<strong>si</strong>ta o<br />

perioada relativ mare <strong>de</strong> timp. Aceasta <strong>de</strong>oarece <strong>de</strong>zvoltatorul este pus <strong>în</strong> <strong>si</strong>tuatia <strong>de</strong> a<br />

exprima <strong>în</strong>tr-un limbaj <strong>de</strong> programare conceptele abstracte care compun mo<strong>de</strong>lul. De


exemplu, <strong>în</strong> cazul hartilor <strong>de</strong> stari <strong>de</strong>zvoltatorul î<strong>si</strong> va pune problema modalitatii <strong>de</strong><br />

codificare a unei stari, a unui eveniment sau a conditiilor <strong>de</strong> activare a unei tranzitii.<br />

Prin urmare translatarea unui mo<strong>de</strong>l <strong>în</strong>tr-un limbaj <strong>de</strong> programare poate dura<br />

mai multe zile sau chiar saptamâni. Un mo<strong>de</strong>l se numeste executabil daca aceasta<br />

translatare se poate efectua automat. Automatizarea procesului <strong>de</strong> translatare poate<br />

conduce la po<strong>si</strong>bilitatea executarii unui prototip aproape imediat dupa ce mo<strong>de</strong>lul<br />

acestuia a fost <strong>de</strong>finitivat.<br />

Exista la ora actuala o serie <strong>de</strong> instrumente CASE care genereaza cod din<br />

mo<strong>de</strong>lele construite. Generarea <strong>de</strong> cod implica existenta unei modalitati <strong>de</strong><br />

translatarea automata a elementelor mo<strong>de</strong>lelor <strong>în</strong> diferite limbaje <strong>de</strong> programare<br />

particulare. Acest lucru presupune o <strong>de</strong>scriere riguroasa a semanticii fiecarui element<br />

ce compune un astfel <strong>de</strong> mo<strong>de</strong>l. În particular, <strong>în</strong> [BOR95] <strong>si</strong> [DOU99] sunt <strong>de</strong>scrise<br />

doua modalitati <strong>de</strong> translatare a ma<strong>si</strong>nilor <strong>de</strong> stari finite, respectiv a hartilor <strong>de</strong> stari<br />

UML <strong>în</strong>tr-un limbaj <strong>de</strong> programare orientat-obiect. Ambele meto<strong>de</strong> iau <strong>în</strong> con<strong>si</strong><strong>de</strong>rare<br />

existenta <strong>în</strong> cadrul aplicatiei mo<strong>de</strong>late a mai multor fire <strong>de</strong> executie care ruleaza <strong>în</strong><br />

paralel. Rezultatul translatarii diagramelor <strong>de</strong> stari <strong>în</strong>sa nu corespun<strong>de</strong> unui mo<strong>de</strong>l<br />

obiect care sa respecte principiile enuntate <strong>în</strong> cadrul capitolului doi.<br />

Asa cum am aratat <strong>în</strong> capitolul prece<strong>de</strong>nt, anomaliile existente la nivelul<br />

limbajelor <strong>de</strong> programarea orientate-obiect concurente nu pot fi <strong>în</strong> totalitate eliminate.<br />

În cazul multor limbaje <strong>de</strong> programare orientate-obiect concurente <strong>în</strong>sa efectul acestor<br />

anomalii poate fi diminuat daca se respecta anumite discipline <strong>de</strong> programare.<br />

Generarea automata <strong>de</strong> cod poate impune o astfel <strong>de</strong> disciplina, iar efortul<br />

<strong>de</strong>zvolttorilor <strong>de</strong> aplicatii este mult scazut. Prin urmare se impune <strong>de</strong>finirea unei<br />

semantici distince pentru hartile <strong>de</strong> stari astfel <strong>în</strong>cât aceastea sa poata mo<strong>de</strong>la cât mai<br />

multe mo<strong>de</strong>le <strong>de</strong> concurenta existente <strong>în</strong> literatura.<br />

Puterea <strong>de</strong> mo<strong>de</strong>lare, precum <strong>si</strong> faptul ca reprezinta un formalism grafic,<br />

vizual au <strong>de</strong>terminat introducerea hartilor <strong>de</strong> stari, dupa cum am aratat <strong>si</strong> <strong>în</strong> sectiune<br />

prece<strong>de</strong>nta, <strong>în</strong>tr-o varietate <strong>de</strong> meto<strong>de</strong> <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare <strong>de</strong> aplicatii. Caracterul<br />

general al acestor diagrame a facut ca ele se fie utilizate atât <strong>în</strong> mo<strong>de</strong>larea aplicatiilor<br />

structurate cât <strong>si</strong> a celor orientate-obiect <strong>de</strong>opotriva.<br />

Sistemul formal construit <strong>si</strong> prezentat <strong>în</strong> capitolul 3 (bazat pe domenii <strong>si</strong><br />

operatii semantice <strong>de</strong> mo<strong>de</strong>lare a comportamentului instantelor unei clase), alaturi <strong>de</strong><br />

concluziile din sectiunea 4.2. ne conduc la i<strong>de</strong>ea ca <strong>si</strong> <strong>în</strong> cazul mo<strong>de</strong>larii<br />

126


comportamentului obiectelor active hartile <strong>de</strong> stari sunt potrivite. În cazul unor clase<br />

ce implementeaza obiecte cu un comportament complex utilizarea hartilor <strong>de</strong> stari<br />

este chiar necesara pentru <strong>în</strong>telegerea <strong>si</strong> gestionarea acestuia. Utilizarea <strong>în</strong>tr-un<br />

context orientat-obiect concurent <strong>în</strong>sa implica mai multe modificari <strong>si</strong> exten<strong>si</strong>i<br />

semantice, pentru a putea fi mo<strong>de</strong>lat un control general al interfetei.<br />

Maniera <strong>de</strong> utilizare a acestor harti <strong>de</strong> stari <strong>în</strong> diverse meto<strong>de</strong> <strong>de</strong> <strong>analiza</strong> <strong>si</strong><br />

proiectare nu este potrivita. Dupa cum am aratat <strong>si</strong> <strong>în</strong> sectiunea prece<strong>de</strong>nta, hartile <strong>de</strong><br />

stari sau variante ale acestora sunt utilizate relativ la mo<strong>de</strong>le <strong>de</strong> obiecte concurente<br />

particulare. Pe <strong>de</strong> alta parte, <strong>în</strong> cazul limbajului <strong>de</strong> mo<strong>de</strong>lare UML, hartile <strong>de</strong> stari nu<br />

se bucura <strong>de</strong> o <strong>de</strong>scriere riguroasa, precisa ceea ce conduce la o interpretare gre<strong>si</strong>ta a<br />

acestora. Acest neajuns implica impo<strong>si</strong>bilitatea realizarii <strong>de</strong> mo<strong>de</strong>le executabile ale<br />

comportamentului obiectelor. În momentul <strong>de</strong> fata majoritatea instrumentelor CASE<br />

<strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare care sprijina UML nu permit generarea <strong>de</strong> cod din diagrame<br />

<strong>de</strong> tranzitie a starii, cele care totu<strong>si</strong> o fac implementând variante restrânse ale acestor<br />

diagrame [DOU99].<br />

Prin urmare trebuie <strong>de</strong>finita o modalitate <strong>de</strong> <strong>de</strong>scriere vizuala a<br />

comportamentului obiectelor active, având la baza hartile <strong>de</strong> stari al lui Harel,<br />

exten<strong>si</strong>ile semantice <strong>si</strong> vizuale introduse <strong>în</strong> UML <strong>si</strong> îmbogatite cu o semantica care sa<br />

permita realizarea <strong>de</strong> mo<strong>de</strong>le executabile.<br />

O astfel <strong>de</strong> harta <strong>de</strong> stari va permite <strong>de</strong>scrierea comportamentului tuturor<br />

instantelor unei clase concurente. Prin urmare vom con<strong>si</strong><strong>de</strong>ra ca <strong>si</strong>ngurele evenimente<br />

care au loc <strong>în</strong> cadrul unui <strong>si</strong>stem <strong>si</strong> care pot influenta comportamentul instantelor unei<br />

clase sunt mesajele <strong>de</strong> apelare a operatiilor clasei.<br />

În practica <strong>în</strong>sa un obiect activ nu î<strong>si</strong> va modifica interfata astfel <strong>în</strong>cât acest<br />

lucru sa fie vizibil din exteriorul sau. El va comunica cu celelalte obiecte din <strong>si</strong>stem<br />

prin intermediul unei interfete <strong>de</strong>finite static, urmând ca mesajele receptionate prin<br />

intermediul acestei interfete sa fie apoi procesate intern <strong>de</strong> catre gestionarul <strong>de</strong><br />

interfata.<br />

Harta <strong>de</strong> stari va <strong>de</strong>scrie atributiile gestionarului <strong>de</strong> interfata, <strong>de</strong>oarece ea va<br />

contine toate informatiile necesare pentru <strong>de</strong>terminarea oportunitatii acceptarii unui<br />

mesaj sau nu.<br />

127


4.6. Concluzii<br />

Studiul limbajelor <strong>de</strong> programare orientate-obiect concurente realizat <strong>în</strong><br />

capitolul al doilea a evi<strong>de</strong>ntiat patru principii care stau la baza proiectarii <strong>de</strong> mo<strong>de</strong>le<br />

<strong>de</strong> obiecte concurente. Pe baza acestor principii am <strong>de</strong>terminat un mo<strong>de</strong>l general al<br />

obiectelor active. Implementarea acestui mo<strong>de</strong>l se regaseste <strong>în</strong> majoritatea limbajelor<br />

care utilizeaza mecanisme <strong>de</strong> <strong>si</strong>ncronizare bazate pe <strong>în</strong>capsulare.<br />

Am aratat <strong>în</strong> cadrul acestui capitol ca obiectele active au toate trasaturile care<br />

caracterizeaza <strong>si</strong>stemele reactive. De aceea hartile <strong>de</strong> stari [HAR87] reprezinta cel<br />

mai potrivit formalism grafic care poate fi utilizat <strong>în</strong> mo<strong>de</strong>larea comportamentului<br />

acestora.<br />

Am extins formalismul hartilor <strong>de</strong> stari cu elemente noi, atât grafice cât <strong>si</strong><br />

semantice, <strong>în</strong> scopul utilizarii acestora <strong>în</strong> specificarea comportamentului obiectelor<br />

active <strong>de</strong>finite <strong>de</strong> mo<strong>de</strong>lul <strong>de</strong>terminat. Exten<strong>si</strong>ile se refera <strong>în</strong> principal la scalabilitate,<br />

executabilitate <strong>si</strong> la <strong>de</strong>finirea unei semantici precise.<br />

Utilizarea unui astfel <strong>de</strong> formalism, alaturi <strong>de</strong> reguli <strong>de</strong> translatare a mo<strong>de</strong>lelor<br />

rezultate <strong>în</strong> cod sursa usureaza activitatea <strong>de</strong> <strong>de</strong>zvoltare, testare <strong>si</strong> <strong>de</strong>panare a<br />

aplicatiilor orientate-obiect concurente.<br />

Formalismul grafic propus <strong>în</strong> sectiunea a patra a acestui capitol poarta numele<br />

<strong>de</strong> harta <strong>de</strong> stari scalabile. Scalabilitatea starilor usureaza specificarea obiectelor<br />

active care au un comportament complex. Utilitatea acestei trasaturi este evi<strong>de</strong>nta <strong>în</strong><br />

special <strong>în</strong> cazul folo<strong>si</strong>rii unui instrument care sa a<strong>si</strong>ste analistul sau proiectantul <strong>de</strong><br />

aplicatii <strong>în</strong> activitatea <strong>de</strong> mo<strong>de</strong>lare. Mo<strong>de</strong>lele comportamentale ale obiectelor active<br />

pot fi astfel foarte usor <strong>de</strong> <strong>analiza</strong>t la diverse nivele <strong>de</strong> <strong>de</strong>taliu.<br />

Executabilitatea este la rândul sau o trasatura extrem <strong>de</strong> importanta a hartilor<br />

<strong>de</strong> stari scalabile, permitând automatizarea implementarii obiectelor active pe baza<br />

mo<strong>de</strong>lelor comportamentale ale acestora. De asemenea, executabilitatea ofera suport<br />

pentru <strong>si</strong>mularea, testarea <strong>si</strong> <strong>de</strong>panarea executiei obiectelor active la acela<strong>si</strong> nivel <strong>de</strong><br />

abstractizare cu mo<strong>de</strong>lul construit. Se evita astfel <strong>de</strong>zvoltarea aplicatiilor folo<strong>si</strong>nd<br />

formalisme vizuale <strong>si</strong> <strong>de</strong>panarea acestora la nivelul codului sursa.<br />

Deoarece semantica hartilor <strong>de</strong> stari scalabile are <strong>în</strong> ve<strong>de</strong>re un mo<strong>de</strong>l <strong>de</strong><br />

obiecte concurente general, ele permit generarea <strong>de</strong> cod sursa <strong>în</strong>tr-o diver<strong>si</strong>tate <strong>de</strong><br />

limbaje <strong>de</strong> programare orientate-obiect concurente, care utilzeaza diferite modalitati <strong>si</strong><br />

128


mecanisme <strong>de</strong> specificare a <strong>concurentei</strong> <strong>si</strong> a interactiunii <strong>în</strong>tre activitati concurente.<br />

Acest lucru confera o flexibilitate crescuta <strong>în</strong> ceea ce priveste translatarea mo<strong>de</strong>lelor<br />

comportamentale <strong>în</strong> cod sursa.<br />

Toate aceste trasaturi ale hartilor <strong>de</strong> stari scalabile au fost validate prin<br />

<strong>implementare</strong>a unui instrument <strong>de</strong> a<strong>si</strong>stare a <strong>de</strong>zvoltarii <strong>de</strong> aplicatii orientate-obiect<br />

concurente, instrument a carui arhitectura <strong>si</strong> <strong>de</strong>scriere functionala sunt prezentate <strong>în</strong><br />

capitolul urmator.<br />

129


5. ActiveCASE - instrument <strong>de</strong> mo<strong>de</strong>lare <strong>si</strong> <strong>si</strong>mulare a<br />

comportamentului obiectelor active<br />

5.1. Introducere<br />

În cadrul acestui capitol este <strong>de</strong>scrisa arhitectura <strong>si</strong> modul <strong>de</strong> functionare a<br />

unei aplicatii <strong>de</strong> mo<strong>de</strong>lare, <strong>implementare</strong> <strong>si</strong> <strong>si</strong>mulare a aplicatiilor orientate-obiect<br />

concurente. Aceasta aplicatie, numita ActiveCASE, a fost realizata integral <strong>de</strong> catre<br />

autorul tezei <strong>si</strong> are la baza mo<strong>de</strong>larea obiectelor active prin intermediul hartilor <strong>de</strong><br />

stari scalabile <strong>de</strong>scrise <strong>în</strong> finalul capitolului prece<strong>de</strong>nt. Instrumentul permite<br />

specificarea structurii claselor <strong>de</strong> obiecte active, mo<strong>de</strong>larea comportamentului<br />

acestora <strong>si</strong> generarea <strong>de</strong> cod sursa. Codul sursa este generat <strong>în</strong> limbajul C++ <strong>si</strong><br />

utilizeaza clase din biblioteca MFC (Microsoft Foundation Class) ver<strong>si</strong>unea 6.0. De<br />

asemenea, <strong>implementare</strong>a instrumentului ActiveCASE s-a realizat utilizând mediul <strong>de</strong><br />

programare Visual C++ 6.0 <strong>si</strong> biblioteca <strong>de</strong> clase MFC 6.0.<br />

Structura interna a acestui instrument a fost astfel conceputa astfel <strong>în</strong>cât sa<br />

poata fi integrata cu usurinta <strong>în</strong>tr-un instrument CASE <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare a<br />

aplicatiilor cu un caracter mai general. În particular, ActiveCASE va reprezenta un<br />

modul distinct al instrumentului Rocase ([BOZ94a], [SUC96b], [CHI97]), <strong>de</strong>zvoltat<br />

<strong>în</strong> cadrul Laboratorului <strong>de</strong> Cercetare <strong>în</strong> Informatica al Univer<strong>si</strong>tatii "Babes-Bolyai"<br />

din Cluj Napoca. Rocase este un instrument <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare a aplicatiilor<br />

orientate-obiect secventiale folo<strong>si</strong>nd UML, <strong>si</strong> contine module pentru editarea <strong>de</strong><br />

diagrame UML, verificarea con<strong>si</strong>stentei acestor diagrame, generare <strong>de</strong> cod sursa C++<br />

<strong>si</strong> reverse-engineering (construire automata <strong>de</strong> diagrame <strong>de</strong> clase pe baza <strong>analiza</strong>i <strong>de</strong><br />

cod sursa).<br />

130


distincte:<br />

Instrumentul ActiveCASE este constituit din trei elemente cu functionalitati<br />

- ActiveCASE.exe - aplicatie care permite editarea diagramelor <strong>de</strong> clase <strong>si</strong> a<br />

hartilor <strong>de</strong> stari <strong>si</strong> care realizeaza generarea codului sursa,<br />

- StateControl.ocx - componenta utilizata <strong>în</strong> vizualizarea unei harti <strong>de</strong> stari<br />

din cadrul unui mo<strong>de</strong>l,<br />

- ActiveStatechart.dll - componenta utilizata <strong>în</strong> <strong>si</strong>mularea executiei unui<br />

obiect activ.<br />

Metamo<strong>de</strong>lul diagramelor <strong>de</strong> clase <strong>si</strong> a hartilor <strong>de</strong> stari scalabile implementate<br />

<strong>în</strong> ActiveCASE este prezentat <strong>în</strong> cadrul sectiunii a doua, comparativ cu meta-mo<strong>de</strong>lul<br />

propus <strong>în</strong> [OMG99] la specificarea limbajului UML.<br />

Sectiunea a treia <strong>de</strong>scrie <strong>în</strong> <strong>de</strong>taliu functionalitatile componentelor<br />

instrumentului ActiveCASE. De asemenea este prezentat mo<strong>de</strong>lul <strong>de</strong> obiecte active<br />

implementat <strong>în</strong> C++ pe baza caruia se realizeaza generarea <strong>de</strong> cod pentru clasele<br />

mo<strong>de</strong>late prin intermediul instrumentului. Acest mo<strong>de</strong>l obiect este unul <strong>si</strong>mplu,<br />

<strong>de</strong>zvoltat <strong>în</strong> scopul <strong>de</strong>monstrarii utilitatii intrumentului ActiveCASE <strong>în</strong> etapele <strong>de</strong><br />

testare <strong>si</strong> <strong>de</strong>panare a aplicatiilor orientate-obiect concurente. O viitoare ver<strong>si</strong>une a<br />

acestui instrument, asa cum va fi subliniat <strong>în</strong> finalul acestui capitol, va putea oferi<br />

utilizatorului po<strong>si</strong>bilitatea <strong>de</strong> a-<strong>si</strong> <strong>de</strong>fini <strong>si</strong>ngur limbajul pentru generarea codului<br />

sursa, fara a afecta calitatile privind <strong>si</strong>mularea comportamentului obiectelor active<br />

generate prin intermediul componentei ActiveStatchart.dll.<br />

Sectiunea a patra <strong>de</strong>monstreaza capacitatea <strong>de</strong> mo<strong>de</strong>lare <strong>si</strong> executabilitatea<br />

hartilor <strong>de</strong> stari scalabile prin <strong>de</strong>zvoltarea <strong>si</strong> <strong>si</strong>mularea unei aplicatii <strong>de</strong> control al<br />

traficului <strong>de</strong> ma<strong>si</strong>ni pe o pista dreptunghiulara. Acest exemplu utilizeaza toate<br />

elementele componente ale hartilor <strong>de</strong> stari scalabile <strong>de</strong>scrise <strong>în</strong> cadrul capitolului<br />

prece<strong>de</strong>nt.<br />

În finalul acestui capitol este realizat un studiu comparativ <strong>în</strong>tre ActiveCASE<br />

<strong>si</strong> alte doua produse existente <strong>în</strong> acest moment care au ca <strong>si</strong> caracteristica comuna<br />

<strong>si</strong>mularea executiei obiectelor active prin intermediul hartilor <strong>de</strong> stari. De asemenea<br />

sunt prezentate directiile <strong>de</strong> viitor <strong>în</strong> acest domeniu.<br />

131


5.2. Meta-mo<strong>de</strong>lul hartilor <strong>de</strong> stari scalabile<br />

Asa cum am aratat <strong>în</strong> capitolul prece<strong>de</strong>nt, ma<strong>si</strong>nile <strong>de</strong> stari sunt foarte<br />

populare <strong>în</strong> lumea ingineriei softului. Calitatile <strong>si</strong> neajunsurile acestora au fost<br />

<strong>în</strong><strong>de</strong>lung discutate <strong>în</strong> multe lucrari <strong>de</strong> specialitate, mai ales dupa extin<strong>de</strong>rea acestora<br />

cu noi trasaturi [HAR87]. În cele mai multe cazuri <strong>în</strong>sa <strong>de</strong>scrierea <strong>si</strong> caracterizarea<br />

acestora s-a facut <strong>în</strong> absenta unui meta-mo<strong>de</strong>l.<br />

Specificatiile UML surprind <strong>în</strong>sa acest aspect <strong>si</strong> contin un meta-mo<strong>de</strong>l static<br />

(diagrama <strong>de</strong> clase) al acestor diagrame. Astfel <strong>de</strong> meta-mo<strong>de</strong>le sunt utile <strong>de</strong>oarece<br />

ele stau la baza implementarii diagramelor <strong>de</strong> stari <strong>în</strong> cadrul unor instrumente <strong>de</strong><br />

<strong>analiza</strong> <strong>si</strong> proiectare a aplicatiilor.<br />

În cele ce urmeaza vor fi prezentate <strong>în</strong> <strong>de</strong>taliu doua meta-mo<strong>de</strong>le statice ale<br />

diagramelor <strong>de</strong> stari care au stat la baza a doua instrumente CASE, <strong>si</strong> anume: meta-<br />

mo<strong>de</strong>lul prezentat <strong>în</strong> specificatiile UML <strong>si</strong> cel utilizat <strong>în</strong> mo<strong>de</strong>larea hartilor <strong>de</strong> stari<br />

scalabile pentru instrumentul ActiveCASE.<br />

5.2.1. Mo<strong>de</strong>larea hartilor <strong>de</strong> stari <strong>în</strong> UML<br />

În figura 5.1. este prezentata diagrama <strong>de</strong> clase corespunzatoare diagramelor<br />

<strong>de</strong> tranzitie a starilor a carei specificare am rezumat-o <strong>în</strong> sectiunea a treia a capitolului<br />

prece<strong>de</strong>nt.<br />

În aceasta diagrama Event reprezinta o clasa abstracta care mo<strong>de</strong>leaza toate<br />

evenimetele care pot <strong>de</strong>clansa o tranzitie <strong>în</strong> cadrul unei diagrame <strong>de</strong> stari (acestea sunt<br />

împartite <strong>în</strong> SignalEvent, CallEvent, TimeEvent <strong>si</strong> ChangeEvent). Evenimentele <strong>de</strong><br />

apel (call events) reprezinta receptionarea unei cereri <strong>de</strong> invocare a unei operatii.<br />

Aceste evenimente au <strong>în</strong> meta-mo<strong>de</strong>lul UML asociate operatii (meto<strong>de</strong> ale claselor),<br />

specificându-se existenta a doua operatii speciale, <strong>si</strong> anume cele <strong>de</strong> creare <strong>si</strong><br />

distrugere <strong>de</strong> obiecte.<br />

ChangeEnvent reprezinta evenimentele generate <strong>de</strong> modificari aduse unor<br />

atribute sau relatii (<strong>de</strong> asociere) care compun o anumita expre<strong>si</strong>e booleana. Aceste<br />

modificari pot fi verificate <strong>în</strong> urma executiei uneia sau mai multor actiuni (care nu au<br />

fost generat <strong>de</strong> catre un eveniment <strong>de</strong> modificare). Aceste evenimente au asociate<br />

câte o expre<strong>si</strong>e booleana, expre<strong>si</strong>e care este periodic evaluata. În momentul <strong>în</strong> care<br />

expre<strong>si</strong>a este a<strong>de</strong>varata se emite evenimentul care la rândul sau poate <strong>de</strong>clansa una<br />

sau mai multe tranzitii.<br />

132


Figura 5.1. Metamo<strong>de</strong>lul diagramelor <strong>de</strong> stari <strong>în</strong> UML<br />

Clasa ce mo<strong>de</strong>leaza starile compuse este <strong>de</strong>scen<strong>de</strong>nta a clasei State <strong>si</strong> contine<br />

una sau mai multe substari (una sau mai multe instante ale clasei StateVertex).<br />

Aceasta clasa are doua proprietati foarte importante, care precizeaza daca starea<br />

compusa este concurenta (isConcurrent) <strong>si</strong> daca ea este o substare a unei stari<br />

concurente (isRegion).<br />

Clasa SimpleState a fost introdusa doar din ratiuni <strong>de</strong> “<strong>si</strong>metrie” cu<br />

Compo<strong>si</strong>teState, ea neavând nici o alta trasatura <strong>în</strong> plus fata <strong>de</strong> clasa State. Instantele<br />

acestei clase reprezinta stari care nu contin substari.<br />

O stare este asociata cu doua secvente <strong>de</strong> actiuni care vor fi executate la<br />

intrarea (entry) respectiv la ie<strong>si</strong>rea (exit) din starea respectiva prin intermediul unei<br />

tranzitii. Aceste actiuni sunt atomice <strong>si</strong> ele nu sunt executate <strong>în</strong> cazul <strong>în</strong> care are loc o<br />

auto-tranzitie. De asemenea o stare are asociata o lista <strong>de</strong> evenimente care sunt<br />

amânate.<br />

133


O ma<strong>si</strong>na <strong>de</strong> stari este compusa din tranzitii <strong>si</strong> stari. Starile continute <strong>de</strong> o<br />

ma<strong>si</strong>na <strong>de</strong> stari formeaza un graf ale carui arce sunt tranzitiile <strong>în</strong>tre aceste stari. O<br />

ma<strong>si</strong>na <strong>de</strong> stari mo<strong>de</strong>leaza comportamentul unui anumit element din mo<strong>de</strong>l. Acest<br />

element reprezinta contextul ma<strong>si</strong>nii <strong>de</strong> stari. Pentru o ma<strong>si</strong>na <strong>de</strong> stari exista o<br />

<strong>si</strong>ngura stare (compusa sau nu), numita Top care are ca <strong>si</strong> parinte direct ma<strong>si</strong>na <strong>de</strong><br />

stari. Toate celelalte stari continute <strong>de</strong> ma<strong>si</strong>na <strong>de</strong> stari reprezinta <strong>de</strong> fapt exten<strong>si</strong>a<br />

starii compuse Top.<br />

Clasa abstracta StateVertex reprezinta clasa <strong>de</strong> baza pentru toate tipurile <strong>de</strong><br />

stari <strong>de</strong>finite <strong>în</strong> UML, relatiile outgoing <strong>si</strong> incoming specificând faptul ca o stare poate<br />

fi sursa <strong>si</strong> <strong>de</strong>stinatia unui numar ne<strong>de</strong>finit <strong>de</strong> tranzitii.<br />

Clasa SubmachineState reprezinta o ma<strong>si</strong>na <strong>de</strong> stari <strong>în</strong>cuibarita (sub-ma<strong>si</strong>na <strong>de</strong><br />

stari). Asa cum se precizeaza <strong>si</strong> <strong>în</strong> documentatia UML o subma<strong>si</strong>na <strong>de</strong> stari este<br />

echivalenta din punct <strong>de</strong> ve<strong>de</strong>re semantic cu o stare compusa precizându-se ca ea a<br />

fost introdusa cu scopul <strong>de</strong> a usura <strong>în</strong> primul rând reutilizabilitatea. Din pacate nu se<br />

precizeaza <strong>si</strong> modul <strong>în</strong> care s-ar putea realiza efectiv reutilizarea unei subma<strong>si</strong>ni <strong>de</strong><br />

stari <strong>si</strong> nici nu sunt impuse anumite constrângeri care sa granteze in<strong>de</strong>pen<strong>de</strong>nta<br />

subma<strong>si</strong>nilor.<br />

5.2.2. Mo<strong>de</strong>larea hartilor <strong>de</strong> stari scalabile <strong>în</strong> ActiveCASE<br />

Asa cum am aratat, hartile <strong>de</strong> stari scalabile se bazeaza diagramele <strong>de</strong> tranzitie<br />

a starii <strong>de</strong>scrise <strong>în</strong> UML. ActiveCASE implementeaza aceste harti <strong>de</strong> stari, oferind<br />

po<strong>si</strong>bilitatea mo<strong>de</strong>larii comportamentului obiectelor active. Modulul care<br />

implementeaza hartile <strong>de</strong> stari scalabile reprezinta <strong>de</strong>ocamdata un modul distinct,<br />

neintegrat <strong>în</strong>tr-un context mai larg care sa permita realizarea tuturor mo<strong>de</strong>lelor<br />

specificate <strong>în</strong> documentatia UML. Cu toate acestea, acest modul ofera suport pentru<br />

patru dintre cele mai importante etape ale ciclului <strong>de</strong> viata a unei aplicatii, <strong>si</strong> anume:<br />

<strong>analiza</strong>, <strong>implementare</strong>, testare <strong>si</strong> <strong>de</strong>panare.<br />

Asa cum am amintit <strong>în</strong> introducere, modulul <strong>de</strong> mo<strong>de</strong>lare a obiectelor active<br />

urmeaza sa fie integrat <strong>în</strong> cadrul instrumentului Rocase, <strong>de</strong>zvoltat la Laboratorul <strong>de</strong><br />

Cercetare <strong>în</strong> Informatica al Univer<strong>si</strong>tatii "Babes-Bolyai" din Cluj-Napoca. Rocase<br />

reprezinta un instrument <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare a aplicatiilor orientate obiect, care<br />

sprijina UML ca <strong>si</strong> limbaj <strong>de</strong> mo<strong>de</strong>lare <strong>si</strong> care ofera suport pentru toate etapele din<br />

ciclul <strong>de</strong> viata al unei aplicatii premergatoare implementarii (mo<strong>de</strong>lare statica,<br />

134


dinamica <strong>si</strong> functionala, generare <strong>de</strong> cod, reverse engineering, round-trip engineering<br />

etc). Modulul implementat pentru mo<strong>de</strong>larea obiectelor active ridica probleme care<br />

pentru instrumentele <strong>de</strong> a<strong>si</strong>stare a <strong>de</strong>zvoltatorilor <strong>de</strong> aplicatii orientate-obiect<br />

secventiale nu existau. Astfel, <strong>implementare</strong>a diagramelor <strong>de</strong> stari pentru mo<strong>de</strong>larea<br />

dinamica s-a realizat pe baza exten<strong>si</strong>ilor semantice prezentate <strong>în</strong> capitolul 4, <strong>si</strong> care se<br />

refera <strong>în</strong> principal la existenta <strong>de</strong> interfete dinamice pentru obiecte, a unei cozi <strong>de</strong><br />

mesaje <strong>si</strong> a unui gestionar <strong>de</strong> mesaje.<br />

Figura 5.2. Metamo<strong>de</strong>lul diagramelor <strong>de</strong> tranzitie a starilor <strong>si</strong> a claselor <strong>în</strong> ActiveCASE<br />

Mo<strong>de</strong>lul static propus pentru mo<strong>de</strong>larea acestor diagrame (figura 5.2) este mai<br />

robust <strong>si</strong> mai bine <strong>de</strong>finit, eliminând redundantele existente <strong>în</strong> alte mo<strong>de</strong>le. De<br />

asemenea, <strong>de</strong>finirea legaturilor dintre o clasa <strong>si</strong> diagrama sa <strong>de</strong> stari, respectiv dintre o<br />

stare compusa <strong>si</strong> substarile sale este mult mai clara <strong>si</strong> naturala.<br />

În cele ce urmeaza vor fi prezentate doar elementele noi care au fost introduse<br />

relativ la specificatiile date <strong>de</strong> UML.<br />

Un prim element <strong>de</strong> noutate este dat <strong>de</strong> faptul ca <strong>în</strong> ActiveCASE starile nu<br />

sunt împartite <strong>în</strong> stari <strong>si</strong>mple - stari compuse sau <strong>în</strong> stari ortogonale - neortogonale asa<br />

cum au fost gândite mai multe meta-mo<strong>de</strong>le anterioare. Prin urmare nu sunt <strong>de</strong>finite<br />

clase speciale pentru a mo<strong>de</strong>la fiecare dintre aceste categorii particulare <strong>de</strong> stari.<br />

135


În ActiveCASE exista doar doua tipuri <strong>de</strong> stari: pseudostari (<strong>de</strong> ie<strong>si</strong>re, intrare,<br />

istoric) - clasa FSMPseudoState- <strong>si</strong> stari concrete - clasa FSMConcreteState. O stare<br />

concreta poate contine una sau mai multe componente ortogonale (clasa<br />

FSMOrthogonalComponent). Aceste componente corespund substarilor ortogonale<br />

din mo<strong>de</strong>lul UML. Astfel, o stare concreta este concurenta daca contine mai mult <strong>de</strong><br />

o componenta ortogonala. Fiecare dintre aceste componente poate contine oricâte<br />

stari (aceste stari sunt practic vazute <strong>de</strong> catre proiectant ca <strong>si</strong> substari ale starii<br />

compuse care <strong>de</strong>tine componenta ortogonala). O stare se reprezinta grafic prin<br />

intermediul unui dreptunghi cu capetele rotunjite care are trei compartimente separate<br />

<strong>în</strong>tre ele prin linii orizontale.<br />

Prima sectiune va contine numele starii respective <strong>si</strong> un buton special utilizat<br />

<strong>în</strong> scalarea starii (afisarea sau ascun<strong>de</strong>rea componentelor ortogonale proprii).<br />

Scalarea permite tratarea unei stari compuse ca <strong>si</strong> o stare <strong>si</strong>mpla <strong>si</strong> ea este utila <strong>în</strong><br />

mo<strong>de</strong>le ce contin harti <strong>de</strong> stari <strong>de</strong> dimen<strong>si</strong>uni mari. În acest mod, atentia<br />

proiectantului va putea fi c<strong>analiza</strong>ta doar spre anumite parti a <strong>de</strong>scrierii<br />

comportamentului unui obiect activ. De asemenea, proprietatea <strong>de</strong> scalabilitate a<br />

starilor permite o mai buna testare <strong>si</strong> <strong>de</strong>panare a obiectelor active care au un<br />

comportament complex.<br />

Sectiunea a doua a reprezentarii grafice a unei stari va contine toate<br />

componentele ortogonale care compun starea, <strong>de</strong>spartite prin linii punctate, verticale.<br />

Componentele ortogonale nu au o reprezentare grafica propriu-zisa, ele fiind<br />

transparente proiectantului.<br />

Cea <strong>de</strong>-a treia sectiune va contine:<br />

- secventele <strong>de</strong> actiuni entry <strong>si</strong> exit asociate starii,<br />

- o expre<strong>si</strong>e booleana (invariant) care <strong>de</strong>fineste starea (pentru testarea<br />

con<strong>si</strong>stentei obiectelor),<br />

- evenimentele acceptate explicit <strong>de</strong> catre oricare dintre substari fara a se<br />

<strong>de</strong>clansa nici o tranzitie (vor fi acceptate implicit evenimentele<br />

corespunzatoare apelurilor <strong>de</strong> operatii <strong>de</strong>clarate ca observatori),<br />

- variabile <strong>de</strong> stare (variabile intermediare pentru stocarea anumitor valori <strong>în</strong><br />

timpul <strong>de</strong>clansarii unei tranzitii).<br />

O stare concreta va contine cel putin o componenta ortogonala. Daca aceasta<br />

nu contine nici o substare atunci este o starea concreta corespun<strong>de</strong> notiunii <strong>de</strong> stare<br />

136


<strong>si</strong>mpla din UML, <strong>în</strong> caz contrar fiind vorba <strong>de</strong> o stare compusa. În AciveCASE nici o<br />

componenta ortogonala nu va fi vida, aceasta continând <strong>în</strong> mod obligatoriu o pseudo-<br />

stare initiala sau o pseudo-stare istoric. În acest context o stare este <strong>si</strong>mpla, daca ea<br />

contine o <strong>si</strong>ngura componenta ortogonala, iar aceasta are o <strong>si</strong>ngura sub-stare: pseudo-<br />

starea initiala.<br />

Rezumând cele spuse pâna acum, <strong>în</strong> ActiveCASE o stare <strong>si</strong>mpla este perceputa<br />

ca o stare compusa cu zero substari, iar o stare neconcurenta ca o stare cu o <strong>si</strong>ngura<br />

componenta ortogonala. Aceasta modalitate <strong>si</strong>mpla <strong>de</strong> a gândi o diagrama <strong>de</strong> stari<br />

conduce la <strong>de</strong>scongestionarea vizibila a meta-mo<strong>de</strong>lului acesteia, eliminând clasele<br />

redundante (<strong>în</strong> UML <strong>de</strong> exemplu clasa SimpleState a fost mo<strong>de</strong>lata doar pentru<br />

"<strong>si</strong>metrie", ea <strong>în</strong>sa neavând nici o trasatura <strong>în</strong> plus fata <strong>de</strong> parintele sau State). În plus,<br />

o astfel <strong>de</strong> reprezentare are calitatea <strong>de</strong> a unifica din punct <strong>de</strong> ve<strong>de</strong>re semantic<br />

conceptele <strong>de</strong> stare <strong>si</strong>mpla, compusa <strong>si</strong> ortogonala.<br />

Figura 5.3 ofera o imagine intuitiva a legaturilor dintre entitatile hartilor <strong>de</strong><br />

stari scalabile. O astfel <strong>de</strong> harta <strong>de</strong> stari poate fi reprezentata printr-un arbore care va<br />

avea <strong>în</strong>tot<strong>de</strong>auna un numar par <strong>de</strong> nivele (nivelele impare contin stari concrete iar<br />

nivelele impare regiuni ortogonale), frunzele fiind <strong>în</strong>tot<strong>de</strong>auna regiunile ortogonale<br />

vi<strong>de</strong>, care nu contin nici o substare.<br />

137<br />

AM1<br />

A<br />

AM2<br />

B1 B2 C1<br />

B1M B2M C1M<br />

Figura 5.3. Reprezentarea hartilor <strong>de</strong> stari scalabile prin intermediul unui arbore eterogen,<br />

cu entitati grupate pe nivele<br />

Un alt element <strong>de</strong> noutate esential este acela ca o clasa nu va avea asociata o<br />

diagrama <strong>de</strong> stari sau o ma<strong>si</strong>na <strong>de</strong> stari ci o stare concreta. Aceasta stare concreta<br />

reprezinta practic parintele tuturor celorlalte stari care <strong>de</strong>scriu comportamentul<br />

obiectelor clasei asociate. Acesta stare va avea numele clasei careia i-a fost atasata,<br />

iar invariantul sau va reprezenta <strong>de</strong> fapt conditia <strong>de</strong> con<strong>si</strong>stenta a obiectelor apartinând<br />

clasei respective.


În alte mo<strong>de</strong>le realizate pâna <strong>în</strong> prezent o clasa putea sau nu sa aiba asociata o<br />

diagrama <strong>de</strong> stari care sa-i mo<strong>de</strong>leze comportamentul. Con<strong>si</strong><strong>de</strong>ram ca este util sa<br />

impunem ca o clasa sa aiba <strong>în</strong>tot<strong>de</strong>auna sa aiba atasata o stare. În cazul unei clase<br />

oarecare al carui comportament dinamic nu este semnificativ, atunci aceasta stare va<br />

fi una <strong>si</strong>mpla (nu va contine nici o substare). Invariantul acestei stari va <strong>de</strong>fini<br />

conditia <strong>de</strong> con<strong>si</strong>stenta a obiectelor clasei respective. În cazul unei clase cu un<br />

comportament complex, starea atasata va contine practic diagrama <strong>de</strong> stari a clasei. În<br />

momentul <strong>în</strong> care va fi creata o instanta a unei clase, obiectul sau va intra <strong>în</strong> starea<br />

asociata acesteia, stare care se va comporta ca o stare compusa obisnuita activând una<br />

dintre starile initiale ale acesteia.<br />

Aceasta abordare uniforma este mult mai naturala <strong>si</strong> mai comoda din punct <strong>de</strong><br />

ve<strong>de</strong>re al unui proiectant <strong>de</strong> aplicatii. Practic notiunea <strong>de</strong> diagrama <strong>de</strong> stari a disparut,<br />

comportamentul claselor fiind <strong>de</strong>scris prin intermediul unei ierarhii <strong>de</strong> stari <strong>în</strong>tre care<br />

exista diverse tranzitii.<br />

138<br />

invariantul<br />

starii State4<br />

este inclus <strong>în</strong><br />

conditia tranzitiei<br />

Figura 5.4. Exemplu <strong>de</strong> clonare a tranzitiilor<br />

În scopul reducerii complexitatii meta-mo<strong>de</strong>lului static, <strong>în</strong> figura 5.2. am<br />

prezentat toate clasele fara structura (proprietati <strong>si</strong> operatii). Este important <strong>de</strong><br />

precizat faptul ca <strong>în</strong> cadrul claselor FSMTran<strong>si</strong>tion <strong>si</strong> FSMAbstractState a fost<br />

introdus un atribut <strong>de</strong> tip <strong>în</strong>treg, numit InternalID care are rolul <strong>de</strong> a atribui atât<br />

tranzitiilor cât <strong>si</strong> starilor un i<strong>de</strong>ntificator unic la nivelul hartii <strong>de</strong> stari din care fac


parte acestea. Acest i<strong>de</strong>ntificator unic va fi utilizat <strong>în</strong> special <strong>în</strong> generarea <strong>de</strong> cod <strong>si</strong> <strong>în</strong><br />

procesul <strong>de</strong> <strong>si</strong>mulare.<br />

Autotranzitia <strong>de</strong> la nivelul clasei FSMTran<strong>si</strong>tion ataseaza fiecarei tranzitii câte<br />

o dublura, utila <strong>în</strong> cazul scalarii (minimizarii sau maximizarii) starilor compuse.<br />

Astfel, <strong>în</strong> figura 5.4. este dat un exemplu <strong>în</strong> care o astfel <strong>de</strong> dublura este necesara.<br />

Tranzitiile etichetate cu m1, respectiv m3 fac legatura <strong>în</strong>tre stari aflate la nivele<br />

diferite <strong>de</strong> <strong>în</strong>cuibarire. În momentul <strong>în</strong> care se doreste ignorarea continutului starii<br />

State2 <strong>de</strong> exemplu, substarile acesteia vor fi "ascunse", fapt care implica automat <strong>si</strong><br />

"ascun<strong>de</strong>rea" celor doua tranzitii amintite. Aceasta operatie <strong>de</strong> "ascun<strong>de</strong>re" conduce<br />

<strong>în</strong>sa la modificarea comportamentului obiectului mo<strong>de</strong>lat: obiectul nu va putea<br />

accepta un mesaj m1 <strong>în</strong> cazul <strong>în</strong> care se afla <strong>în</strong> starea State1, sau un eveniment m2<br />

atunci când se afla <strong>în</strong> starea State2. Aceasta este <strong>în</strong>sa un efect nedorit, <strong>de</strong>oarece<br />

scalarea starilor are doar rolul <strong>de</strong> a reduce complexitatea unei harti <strong>de</strong> stari din punct<br />

<strong>de</strong> ve<strong>de</strong>re al proiectantului <strong>si</strong> nu <strong>de</strong> a modifica comportamentul mo<strong>de</strong>lat.<br />

Prin urmare este necesara introducerea unor tranzitii suplimentare care sa<br />

conserve acest comportament. Aceste tranzitii sunt <strong>de</strong> fapt dublurile tranzitiilor<br />

originale, <strong>si</strong> ele fac legatura <strong>în</strong>tre starile State1 <strong>si</strong> State2. Aceste tranzitii vor avea<br />

acela<strong>si</strong> i<strong>de</strong>ntificator ca <strong>si</strong> tranzitiile originale pentru a nu perturba procesul <strong>de</strong><br />

<strong>si</strong>mulare, iar ele nu vor influenta generarea <strong>de</strong> cod sursa. Tot <strong>în</strong> scopul conservarii<br />

comportamentului, clonele tranzitiilor care au ca stare sursa o stare "ascunsa" vor avea<br />

conditia <strong>de</strong> <strong>de</strong>clansare ca o conjunctie <strong>în</strong>tre conditia originala <strong>si</strong> invariantul starii sursa<br />

(cazul tranzitiei etichetate cu m3, care va avea acum conditia <strong>de</strong> <strong>de</strong>clansare c3 && c4,<br />

un<strong>de</strong> && reprezinta operatorul <strong>si</strong>-logic din limbajul <strong>de</strong> programare C++).<br />

5.3. Descrierea aplicatiei ActiveCASE<br />

Instrumentele CASE <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare orientata-obiect a aplicatiilor<br />

ofera sprijin pentru cele mai importante etape ale ciclului <strong>de</strong> viata a unei aplicatii.<br />

Acestea sunt:<br />

- Analiza - <strong>în</strong> cadrul careia se realizeaza i<strong>de</strong>ntificarea caracteristicilor<br />

esentiale tuturor solutiilor corecte po<strong>si</strong>bile,<br />

- Proiectarea - care adauga mo<strong>de</strong>lelor <strong>de</strong> <strong>analiza</strong> noi elemente care <strong>de</strong>finesc<br />

o solutie particulara, pe baza optimizarii anumitor criterii,<br />

139


- Implementarea - <strong>în</strong> care se realizeaza un proiect executabil al solutiei<br />

particulare mo<strong>de</strong>lata <strong>în</strong> faza <strong>de</strong> proiectare,<br />

- Testarea - <strong>în</strong> care are loc verificarea faptului ca <strong>implementare</strong>a este<br />

echivalenta cu mo<strong>de</strong>lul proiectat <strong>si</strong> validarea faptului ca <strong>implementare</strong>a<br />

respecta criteriile <strong>de</strong> corectitudine i<strong>de</strong>ntificate <strong>în</strong> etapa <strong>de</strong> <strong>analiza</strong>.<br />

Instrumentul ActiveCASE este un instrument <strong>de</strong> mo<strong>de</strong>lare a obiectelor active<br />

care ofera suport pentru trei dintre aceste etape (etapa <strong>de</strong> proiectare nu este surprinsa,<br />

codul sursa fiind generat direct din mo<strong>de</strong>lele <strong>de</strong> <strong>analiza</strong>). Aplicatia ActiveCASE<br />

propriu-zisa permite editarea <strong>de</strong> diagrame <strong>de</strong> clase <strong>si</strong> <strong>de</strong> stari <strong>si</strong> contine un generator<br />

<strong>de</strong> cod C++.<br />

Editarea diagramelor <strong>de</strong> clase utilizeaza un sub-set restrâns <strong>de</strong> notatii dintre<br />

cele introduse <strong>de</strong> UML. Editorul <strong>de</strong> diagrame <strong>de</strong> stari <strong>în</strong>sa este mult mai complex, <strong>si</strong><br />

permite editarea <strong>de</strong> harti <strong>de</strong> stari scalabile, cu toate elementele introduse <strong>de</strong> acestea<br />

(figura 5.5). Editarea este senzitiva la context <strong>si</strong> se realizeaza uniform pentru ambele<br />

diagrame, modul <strong>de</strong> manipulare al entitatilor grafice fiind natural <strong>si</strong> <strong>si</strong>mplu iar<br />

actualizarea diagramelor facându-se rapid. Diagramele pot fi paginate, exista optiuni<br />

<strong>de</strong> aliniere a entitatilor selectate, cursorul î<strong>si</strong> modifica forma <strong>în</strong> raport cu entitatea<br />

editatã, barele <strong>de</strong> instrumente pot fi gestionate <strong>si</strong> <strong>de</strong>plasate. Editorul dispune <strong>de</strong><br />

facilitati <strong>de</strong> print preview <strong>si</strong> zoom. Toate caracteristicile mentionate fac ca editorul sã<br />

fie superior tuturor editoarelor instrumentelor cunoscute <strong>de</strong> noi pâna <strong>în</strong> prezent.<br />

Fiecare proiect este reprezentat <strong>în</strong>tr-o fereastra care are doua sectiuni: una<br />

pentru editarea diagramelor <strong>de</strong> clase iar cea <strong>de</strong>-a doua pentru cea a diagramelor <strong>de</strong><br />

stari. Fiecare clasa din diagrama <strong>de</strong> clasa va avea o stare concreta corespunzatoare <strong>în</strong><br />

diagrama <strong>de</strong> tranzitie a starilor.<br />

Codul generat din diagramele editate este <strong>în</strong> limbajul C++. Toate clasele<br />

mo<strong>de</strong>late <strong>în</strong> ActiveCASE vor fi subclase ale unei clase speciale ActiveObject, care<br />

<strong>în</strong>capsuleaza proprietati <strong>si</strong> operatii pentru tratarea corespunzatoare a starilor, a<br />

tranzitiilor dintre acestea <strong>si</strong> pentru interactiunea cu componenta <strong>de</strong> <strong>si</strong>mulare.<br />

140


Figura 5.5. Captura a aplicatiei ActiveCASE care surprin<strong>de</strong> editorul <strong>de</strong> diagrame <strong>de</strong> clase <strong>si</strong> <strong>de</strong> stari<br />

Codul <strong>de</strong> <strong>de</strong>clarare a clasei ActiveObject este dat mai jos.<br />

class ActiveObject : public CObject<br />

{<br />

//contructors/<strong>de</strong>structor<br />

DECLARE_DYNAMIC(ActiveObject)<br />

public:<br />

ActiveObject(CString strName, BOOL bActivateSimulation=FALSE);<br />

virtual ~ActiveObject();<br />

//Attribute<br />

protected:<br />

static DLGActiveObjectSelection m_dlgSelection;<br />

ISimulation* m_pSimulation;<br />

CString m_strName;<br />

public:<br />

//Operations<br />

protected:<br />

virtual void GetCurrentStateCo<strong>de</strong>(CUIntArray* pArray);<br />

virtual void LaunchTran<strong>si</strong>tion(UINT nTran<strong>si</strong>tionInternalID);<br />

virtual void EndTran<strong>si</strong>tion(UINT nTran<strong>si</strong>tionInternalID);<br />

public:<br />

static void SelectActiveObject();<br />

141


};<br />

CString GetName() {return m_strName;};<br />

void SetName(CString strName){m_strName=strName;};<br />

void ActivateSimulation();<br />

void DeactivateSimulation();<br />

BOOL IsSimulationActive(){return m_pSimulation!=NULL;};<br />

Clasa ActiveObject este o subclasa a clasei CObject a bibliotecii <strong>de</strong> clase<br />

MFC. Aceasta clasa permite consultarea informatiilor <strong>de</strong> tip in timpul executiei<br />

(RunTime Type Information - RTTI).<br />

O alta clasa importanta pentru <strong>si</strong>mularea aplicatiilor concurente generate cu<br />

ActiveCASE este clasa DLGActiveObjectSelection. Aceasta clasa implementeaza o<br />

fereastra <strong>de</strong> dialog care permite selectarea <strong>în</strong> timpul executiei unei aplicatii a<br />

obiectelor active pentru care se doreste vizualizarea diagramei <strong>de</strong> stari (figura 5.11).<br />

Fereastra <strong>de</strong> dialog contine doua liste, una care afiseaza toate clasele <strong>de</strong>scen<strong>de</strong>nte din<br />

ActiveObject <strong>si</strong> care au instante <strong>în</strong> executie, <strong>si</strong> o a doua care contine toate instantele<br />

clasei selectate existente <strong>în</strong> aplicatie la un moment dat.<br />

Clasa ActiveObject are un atribut static m_dlgSelection <strong>de</strong> tip<br />

DLGActiveObjectSelection. Atributul m_dlgSelection este informat <strong>de</strong> fiecare data<br />

când este creat sau distrus un nou obiect activ, astfel <strong>în</strong>cât atunci când se doreste<br />

vizualizarea diagramei <strong>de</strong> stari pentru un obiect activ <strong>în</strong> executie, fereastra <strong>de</strong> dialog<br />

va afisa toate obiectele active existente <strong>în</strong> aplicatie la momentul respectiv.<br />

I<strong>de</strong>ntificarea <strong>de</strong> catre utilizator a unui obiect activ particular se realizeaza prin<br />

intermediul atributului m_strName, implementat la nivelul clasei ActiveObject, care<br />

este un <strong>si</strong>r <strong>de</strong> caractere.<br />

Alaturi <strong>de</strong> fi<strong>si</strong>erele <strong>de</strong> <strong>de</strong>clarare <strong>si</strong> <strong>de</strong>finire a claselor ActiveObject <strong>si</strong><br />

DLGActiveObjectSelection, <strong>în</strong> aplicatiile concurente generate <strong>de</strong> ActiveCASE mai<br />

trebuie adaugate fi<strong>si</strong>ere pentru specificarea interfetei componentei <strong>de</strong> <strong>si</strong>mulare.<br />

Aceasta componenta exporta functii care permit <strong>de</strong>terminarea caii fi<strong>si</strong>erului <strong>în</strong> care a<br />

fost salvat mo<strong>de</strong>lul editat cu ajutorul instrumentului ActiveCASE, a diagramei <strong>de</strong> stari<br />

care se doreste a fi vizualizata, precum <strong>si</strong> pentru activarea unei anumite tranzitii.<br />

Codul <strong>de</strong> daclarare a interfetei este dat <strong>în</strong> continuare:<br />

class ISimulation : public COleDispatchDriver<br />

{<br />

public:<br />

ISimulation() {}<br />

ISimulation(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}<br />

142


Attributes<br />

public:<br />

// Operations<br />

public:<br />

void ShowDialog();<br />

void Hi<strong>de</strong>Dialog();<br />

CString GetPath();<br />

void SetPath(LPCTSTR lpszNewValue);<br />

CString GetClass();<br />

void SetClass(LPCTSTR lpszNewValue);<br />

void LaunchTran<strong>si</strong>tion(long Tran<strong>si</strong>tionCo<strong>de</strong>);<br />

CString GetTitle();<br />

void SetTitle(LPCTSTR lpszNewValue);<br />

void EndTran<strong>si</strong>tion(long Tran<strong>si</strong>tionCo<strong>de</strong>, long NewState);<br />

};<br />

Componenta <strong>de</strong> <strong>si</strong>mulare afiseaza o fereastra <strong>de</strong> dialog care contine un control<br />

special <strong>de</strong> vizualizare a unei diagrame <strong>de</strong> stari a carei reprezentare grafica se afla <strong>în</strong><br />

cadrul unui fi<strong>si</strong>er aflat la o cale data <strong>si</strong> care mo<strong>de</strong>leaza comportamentul unei clase <strong>de</strong><br />

asemenea specificate initial.<br />

Componenta <strong>de</strong> <strong>si</strong>mulare este inclusa <strong>în</strong> fi<strong>si</strong>erul ActiveStatechart.dll, <strong>si</strong> ea este<br />

<strong>în</strong>registrata <strong>în</strong> <strong>si</strong>stem, alaturi <strong>de</strong> componenta <strong>de</strong> vizualizare a unei diagrame <strong>de</strong> stari<br />

(inclusa <strong>în</strong> fi<strong>si</strong>erul StateControl.ocx), <strong>în</strong> momentul instalarii instrumentului<br />

ActiveCASE.<br />

În sectiunea urmatoare este prezentat un exemplu care implementeaza o<br />

aplicatie <strong>de</strong> <strong>si</strong>mulare a controlului traficului <strong>de</strong> ma<strong>si</strong>ni pe o pista <strong>de</strong> forma<br />

dreptunghiulara. Acest exemplu utilizeaza toate facilitatile oferite <strong>de</strong> instrumetul<br />

ActiveCASE împreuna cu componentele anexe, <strong>si</strong> toate elementele introduse <strong>de</strong><br />

hartile <strong>de</strong> stari scalabile.<br />

5.3. Mo<strong>de</strong>larea <strong>si</strong> testarea unei aplicatii <strong>de</strong> <strong>si</strong>mulare a traficului <strong>de</strong> ma<strong>si</strong>ni<br />

În figura 5.6. este prezentata diagrama <strong>de</strong> clase care mo<strong>de</strong>leaza o aplicatie <strong>de</strong><br />

<strong>si</strong>mulare a traficului ma<strong>si</strong>nilor pe o pista dreptunghiulara. Clasa Pista contine o<br />

matrice <strong>de</strong> locatii <strong>si</strong> o multime <strong>de</strong> ma<strong>si</strong>ni. Cele trei operatii ale clasei Pista (figura<br />

5.7) realizeaza afisarea acesteia pe ecran precum <strong>si</strong> pornirea, respectiv oprirea, tuturor<br />

ma<strong>si</strong>nilor care îi sunt asociate. Comportamentul unei piste este foarte <strong>si</strong>mplu, aceasta<br />

putându-se afla <strong>în</strong> doua stari, Stop <strong>si</strong> Start, care specifica faptul ca ma<strong>si</strong>nile asociate<br />

sunt oprite sau se afla <strong>în</strong> miscare.<br />

143


Figura 5.6. Diagrama <strong>de</strong> clase a aplicatiei <strong>de</strong> <strong>si</strong>mulare a traficului <strong>de</strong> ma<strong>si</strong>ni<br />

Figura 5.7. Mo<strong>de</strong>larea structurii <strong>si</strong> a comportamentului clasei Pista<br />

Instantele clasei Ma<strong>si</strong>na au un comportament mai complex (figura 5.8).<br />

Astfel, o ma<strong>si</strong>na se poate <strong>de</strong>plasa <strong>în</strong> cadrul unei piste <strong>în</strong> patru directii: sus, dreapta, jos<br />

sau stânga. În momentul <strong>în</strong> care acestea <strong>în</strong>tâlnesc un obstacol (marginea pistei, o<br />

locatie blocata sau o alta ma<strong>si</strong>na) ma<strong>si</strong>nile se vor roti <strong>în</strong> sensul acelor <strong>de</strong> ceasornic<br />

pentru a cauta o locatie libera pentru <strong>de</strong>plasare. O ma<strong>si</strong>na se poate afla <strong>în</strong> starile<br />

Oprit, respectiv Pornit. În cazul <strong>în</strong> care o ma<strong>si</strong>na este pornita ea se poate afla <strong>în</strong> una<br />

dintre cele patru stari corespunzatoare sensului <strong>de</strong> <strong>de</strong>plasare: InSus, InDreapta, InJos<br />

<strong>si</strong> InStanga. Functia MergeDrept este apelata <strong>în</strong> continuu cât timp ma<strong>si</strong>na se afla <strong>în</strong><br />

starea Pornit <strong>si</strong> ea apeleaza functiile corespunzatoare <strong>de</strong> <strong>de</strong>plasare <strong>în</strong> raport <strong>de</strong> starea<br />

locatiilor din vecinatatea locatiei ocupata <strong>de</strong> ma<strong>si</strong>na. În cazul opririi <strong>si</strong> repornirii<br />

ma<strong>si</strong>nii aceasta î<strong>si</strong> va continua <strong>de</strong>plasarea <strong>în</strong> sensul <strong>în</strong> care se <strong>de</strong>plasa <strong>în</strong>ainte <strong>de</strong> oprire<br />

(fapt mo<strong>de</strong>lat <strong>de</strong> pseudo-starea istoric din cadrul starii compuse Pornit).<br />

144


Figura 5.8. Mo<strong>de</strong>larea structurii <strong>si</strong> a comportamentului clasei Ma<strong>si</strong>na<br />

Figura 5.9. Mo<strong>de</strong>larea structurii <strong>si</strong> a comportamentului clasei Locatie<br />

Si clasa Locatie are un comportament complex (figura 5.9). O locatie se poate<br />

afla <strong>în</strong> doua stari distincte: Blocata <strong>si</strong> Neblocata. Starea Blocata sugereaza repararea<br />

drumului aflat pe locatia respectiva, iar un obiect <strong>de</strong> tip Locatie sta <strong>în</strong>tr-o astfel <strong>de</strong><br />

stare o perioada finita <strong>de</strong> timp, dupa care se va <strong>de</strong>bloca (<strong>în</strong> programul <strong>de</strong> test o locatie<br />

ramâne blocata 2 secun<strong>de</strong>). În cazul <strong>în</strong> care o locatie este <strong>de</strong>blocata ea intra automat<br />

<strong>în</strong> doua stari ortogonale: Libera <strong>si</strong> Utilizabila. Atunci când o locatie libera este<br />

ocupata <strong>de</strong> o ma<strong>si</strong>na ea va trece <strong>în</strong> starea Ocupata, iar când ea a fost ocupata <strong>de</strong> patru<br />

ori consecutiv va intra <strong>în</strong> starea CuGropi (o locatie se <strong>de</strong>gra<strong>de</strong>aza pe masura ce este<br />

traversata <strong>de</strong> ma<strong>si</strong>ni). Para<strong>si</strong>rea acestei stari (prin eliberarea locatiei <strong>de</strong> ma<strong>si</strong>na care o<br />

ocupa) genereaza automat un eveniment <strong>de</strong> blocare, pentru ca locatia sa fie reparata.<br />

145


Figura 5.10. Simularea comportamentului ma<strong>si</strong>nii ro<strong>si</strong>i<br />

Editarea diagramelor prezentate <strong>în</strong> figurile 5.7, 5.8 <strong>si</strong> 5.9 este realizata cu<br />

ajutorul instrumentului ActiveCASE (figura 5.5). De aici se va realiza generarea <strong>de</strong><br />

cod <strong>si</strong> atasarea codului generat unui proiect Visual C++. Interventia <strong>de</strong>zvoltatorului<br />

aplicatiei este necesara doar pentru a creea o pista <strong>si</strong> a atasa acesteia un numar dorit <strong>de</strong><br />

ma<strong>si</strong>ni. De asemenea este necesara interventia <strong>de</strong>zvoltatorului daca se doreste<br />

reprezentarea grafica a obiectelor celor trei clase.<br />

Dupa compilarea <strong>si</strong> link-editarea proiectului Visual C++ se poate lansa <strong>în</strong><br />

executie aplicatia care contine trasaturi <strong>de</strong> vizualizare a evolutiei comportamentului<br />

tutror obiectelor active cu ajutorul celor doua componente <strong>de</strong> <strong>si</strong>mulare amintite <strong>în</strong><br />

capitolul prece<strong>de</strong>nt.<br />

146


Figura 5.11. Alegerea unui obiect activ <strong>în</strong> ve<strong>de</strong>rea <strong>si</strong>mularii<br />

Figura 5.12. Simularea comportamentului locatie din coltul stânga-sus al pistei<br />

(starea Blocata e minimizata)<br />

Figurile 5.10, 5.11 respectiv 5.12 prezinta momente distincte din executia<br />

aplicatiei generate <strong>de</strong> ActiveCASE, <strong>si</strong> <strong>în</strong> care se exemplifica testarea<br />

147


comportamentului obiectelor active “Ma<strong>si</strong>na ro<strong>si</strong>e”, respectiv “Locatie_0_0”, prin<br />

<strong>si</strong>mularea acestuia prin harti <strong>de</strong> stari scalabile.<br />

5.4. Concluzii<br />

Dezvoltarea <strong>de</strong> aplicatii orientate-obiect concurente este extrem <strong>de</strong> laborioasa.<br />

Asa cum am aratat <strong>în</strong> capitolele prece<strong>de</strong>nte, diferentele existente la nivel conceptual<br />

<strong>în</strong>tre diverse limbaje <strong>de</strong> programare orientate-obiect concurente fac dificila<br />

translatarea aplicatiilor dintr-un limbaj <strong>în</strong> altul. De asemenea, activitatea <strong>de</strong> testare <strong>si</strong><br />

<strong>de</strong>panare a acestor aplicatii implica o serie <strong>de</strong> probleme neexistente <strong>în</strong> cazul <strong>de</strong>voltarii<br />

<strong>de</strong> aplicatii secventiale, probleme care tin <strong>în</strong> special <strong>de</strong> caracterul dinamic ridicat al<br />

acestora. Prin urmare mo<strong>de</strong>larea unor astfel <strong>de</strong> aplicatii folo<strong>si</strong>nd un set unitar <strong>de</strong><br />

notatii <strong>si</strong> concepte precum <strong>si</strong> po<strong>si</strong>bilitatea testarii <strong>si</strong> <strong>de</strong>panarii la nivelul mo<strong>de</strong>lelor <strong>si</strong><br />

nu la nivelul codului sursa implica o crestere a calitatii aplicatiilor <strong>si</strong> o mai buna<br />

<strong>în</strong>tretinere a acestora.<br />

Instrumentul ActiveCASE are rolul <strong>de</strong> a automatiza anumite etape ale<br />

procesului <strong>de</strong> <strong>de</strong>zvoltare a aplicatiilor orientate-obiect concurente. Printre<br />

principalele calitati ale acestui instrument amintim:<br />

- flexibilitate <strong>în</strong> mo<strong>de</strong>larea obiectelor active prin <strong>implementare</strong>a hartilor <strong>de</strong><br />

stari scalabile a caror semantica acopera o gama larga <strong>de</strong> mo<strong>de</strong>le obiect,<br />

- puterea <strong>de</strong> mo<strong>de</strong>lare a <strong>concurentei</strong> interne a obiectelor active,<br />

- ofera suport pentru adaptarea generatorului <strong>de</strong> cod la limbajul <strong>de</strong><br />

programare dorit,<br />

- ofera suport pentru <strong>si</strong>mularea comportamentului obiectelelor active la<br />

executie prin intermediul unor componente care fac po<strong>si</strong>bila utilizarea a<br />

diverse medii <strong>de</strong> programare <strong>în</strong> <strong>de</strong>zvoltarea aplicatiilor finale,<br />

- po<strong>si</strong>bilitatea controlarii sau, <strong>în</strong> anumite cazuri, chiar a eliminarii<br />

anomaliilor <strong>de</strong> mostenire prin impunerea <strong>de</strong> discipline <strong>de</strong> <strong>implementare</strong>a a<br />

obiectelor active.<br />

Alte produse care ofera suport pentru mo<strong>de</strong>larea comportamentului obiectelor<br />

active utilizând diagrame <strong>de</strong> stari sunt Rhapsody <strong>de</strong>zvoltat <strong>de</strong> firma i-Logix [DOU99]<br />

<strong>si</strong> Covers realizat <strong>de</strong> Experimental Object Technologies din Sankt Petersburg<br />

[BOR95]. Ambele produse permit generare <strong>de</strong> cod din diagrame <strong>de</strong> stari <strong>si</strong> ofera<br />

148


po<strong>si</strong>bilitatea testarii corectitudinii mo<strong>de</strong>lelor prin intermediul <strong>si</strong>mularii<br />

comportamentului la executie. De asemenea, ambele <strong>si</strong>mulari se bazeaza pe<br />

interpretarea structurii obiectelor <strong>si</strong> traducerea acestora <strong>în</strong> diagramele <strong>de</strong> stari din<br />

mo<strong>de</strong>l.<br />

Simularea comportamentului se realizeaza <strong>în</strong>sa la nivelul instrumentului <strong>de</strong><br />

mo<strong>de</strong>lare. O astfel <strong>de</strong> abordare reduce capacitatea <strong>de</strong> <strong>si</strong>mulare “reala”, introducându-<br />

se o serie <strong>de</strong> intârzieri datorate comunicarii <strong>în</strong>tre mediu <strong>si</strong> aplicatia concurenta<br />

executata. Diferentele <strong>în</strong>tre modul <strong>de</strong> realizare a <strong>si</strong>mularii <strong>în</strong> cadrul acestor<br />

instrumente <strong>si</strong> abordarea ActivCASE sunt <strong>de</strong> aceea<strong>si</strong> natura cu diferentele dintre<br />

interpretare <strong>si</strong> compilare/executie a codului sursa.<br />

Instrumentul Covers suporta mo<strong>de</strong>larea comportamentului obiectelor active<br />

doar prin intermediului ma<strong>si</strong>nilor cu stari finite, fara a introduce conceptele hartilor <strong>de</strong><br />

stari <strong>de</strong>scrise <strong>în</strong> [HAR87]. Prin urmare mo<strong>de</strong>larea unor comportamente complexe<br />

este extrem <strong>de</strong> dificila sau chiar impo<strong>si</strong>bila.<br />

Pe <strong>de</strong> alta parte instrumentul Rhapsody ofera suport pentru majoritatea<br />

tipurilor <strong>de</strong> mo<strong>de</strong>le <strong>de</strong>scrise <strong>în</strong> specificatiile UML. Si aici <strong>în</strong>sa, obiectele active cu un<br />

comportament complex sunt mai dificil <strong>de</strong> mo<strong>de</strong>lat, iar urmarirea executiei acestora<br />

prin intermediul <strong>si</strong>mularii este greoaie, neexistând po<strong>si</strong>bilitatea modificarii nivelului<br />

<strong>de</strong> observare a dinamicii. Mai mult, codul generat se bazeaza pe un mo<strong>de</strong>l obiect<br />

complex, criptic, dificil <strong>de</strong> <strong>în</strong>teles <strong>si</strong> modificat.<br />

Generarea <strong>de</strong> cod realizata <strong>în</strong> cadrul instrumentului ActiveCASE nu a avut <strong>în</strong><br />

ve<strong>de</strong>re un mo<strong>de</strong>l obiect complex. Acest mo<strong>de</strong>l obiect se bazeaza pe utilizarea <strong>de</strong><br />

mecanisme din categoria celor orientate pe activitati. Diagrama <strong>de</strong> stari <strong>si</strong> semantica<br />

atribuita acesteia permite <strong>în</strong>sa generarea <strong>de</strong> cod <strong>în</strong> oricare dintre mo<strong>de</strong>lele obiect<br />

specificate <strong>în</strong> literatura <strong>si</strong> luate <strong>în</strong> con<strong>si</strong><strong>de</strong>rare <strong>în</strong> capitolul doi.<br />

Spre <strong>de</strong>osebire <strong>de</strong> cele doua produse amintite, instrumentul ActiveCASE<br />

introduce o serie <strong>de</strong> elemente noi, atât la nivelul editarii <strong>de</strong> diagrame cât <strong>si</strong> la nivelul<br />

conceptelor introduse, cum sunt:<br />

- editor <strong>de</strong> diagrame <strong>de</strong> stari performant, interactiv, senzitiv la context,<br />

- scalabilitate,<br />

- in<strong>de</strong>pen<strong>de</strong>nta <strong>si</strong>mularii <strong>de</strong> mediul <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare,<br />

- generare <strong>de</strong> cod configurabila,<br />

149


- <strong>si</strong>mulare interactiva, care permite configurarea hartilor <strong>de</strong> stari <strong>în</strong> timpul<br />

executiei obiectelor active <strong>si</strong>mulate,<br />

- usurinta <strong>în</strong> manipulare <strong>si</strong> <strong>în</strong>tretinere a diagramelor realizate,<br />

- verificarea con<strong>si</strong>stentei mo<strong>de</strong>lelor.<br />

Una dintre dintre directiile viitoare <strong>de</strong> exten<strong>si</strong>e a instrumentului ActiveCASE<br />

este oferirea po<strong>si</strong>bilitatii <strong>de</strong> <strong>de</strong>finire <strong>si</strong> utilizare a sabloanelor <strong>de</strong> harti <strong>de</strong> stari.<br />

Sabloanele <strong>de</strong> harti <strong>de</strong> stari reprezinta harti <strong>de</strong> stari generice, caracteristice unor<br />

comportamente <strong>de</strong>s <strong>în</strong>tâlnite <strong>si</strong> care pot fi aplicate pe cazuri particulare <strong>de</strong><br />

comportament. Sabloanele <strong>de</strong> harti <strong>de</strong> stari sunt un concept nou, <strong>de</strong>scris <strong>în</strong> [DOU99],<br />

<strong>si</strong> care alaturi <strong>de</strong> sabloanele <strong>de</strong> proiectare contribuie la cresterea gradului <strong>de</strong><br />

reutilizabilitate a softului.<br />

De asemenea, va trebui avuta <strong>în</strong> ve<strong>de</strong>re po<strong>si</strong>bilitatea mostenirii hartilor <strong>de</strong> stari<br />

<strong>în</strong>tre super-clase <strong>si</strong> sub-clasele acestora. Exista doua modalitati distincte <strong>de</strong> abordare<br />

a acestei probleme: una care presupune rescrierea completa a hartilor <strong>de</strong> stari pentru<br />

sub-clase, <strong>si</strong> o a doua care presupune copierea integrala a hartii <strong>de</strong> stari a super-clasei<br />

<strong>în</strong> mo<strong>de</strong>lul comportamental al sub-claselor, acestea neputând fi modificate <strong>de</strong>cât prin<br />

respectarea unor restrictii bine precizate. Oferirea unui suport <strong>de</strong> automatizare a<br />

ultimului proces poate conduce la <strong>de</strong>zvoltarea <strong>de</strong> aplicatii orientate-obiect concurente<br />

mai robuste <strong>si</strong> care permit tratarea anomaliilor <strong>de</strong> mostenire.<br />

150


6. Concluzii<br />

Unificarea conceptelor programarii orientate-obiect cu mecanismele specifice<br />

programarii concurente reprezinta o preocupare constanta <strong>în</strong> lumea informaticii <strong>în</strong><br />

ultimele doua <strong>de</strong>cenii. Aceasta preocupare este justificata <strong>de</strong> puterea ridicata <strong>de</strong><br />

mo<strong>de</strong>lare, proprie limbajelor orientate-obiect, <strong>si</strong> puterea <strong>de</strong> calcul, proprie limbajelor<br />

concurente, care au facut ca limbajele <strong>de</strong> programare orientate-obiect concurente sa<br />

fie aplicabile <strong>în</strong>tr-un numar <strong>în</strong>semnat <strong>de</strong> domenii.<br />

Din nefericire, combinarea <strong>concurentei</strong> cu mecanismele orientate-obiect nu<br />

este un proces trivial, cercetarile <strong>în</strong> domeniu evi<strong>de</strong>ntiind existenta unor conflicte <strong>în</strong>tre<br />

conceptele introduse <strong>de</strong> catre fiecare filozofie <strong>de</strong> programare <strong>în</strong> parte. Unul dintre<br />

cele mai importante conflicte <strong>de</strong>terminate este cel dintre mecanismele <strong>de</strong> specificare a<br />

<strong>si</strong>ncronizarii activitatilor concurente <strong>si</strong> mecanismul <strong>de</strong> mostenire, conflict <strong>în</strong>tâlnit <strong>în</strong><br />

literatura sub numele <strong>de</strong> anomalie <strong>de</strong> mostenire.<br />

6.1. Rezultate obtinute<br />

Scopul tezei este acela <strong>de</strong> a <strong>de</strong>fini <strong>si</strong> valida un formalism vizual <strong>de</strong> mo<strong>de</strong>lare a<br />

aplicatiilor orientate-obiect concurente. Definirea unui astfel <strong>de</strong> formalism se bazeaza<br />

pe o <strong>analiza</strong> riguroasa a mo<strong>de</strong>lelor <strong>de</strong> obiecte concurente <strong>de</strong>zvoltate pâna <strong>în</strong> prezent <strong>si</strong><br />

a neajunsurilor care le caracterizeaza. Acesta este <strong>si</strong> motivul pentru care teza contine<br />

un prim capitol <strong>în</strong> care s-a realizat o <strong>si</strong>nteza a limbajelor <strong>de</strong> programare orientate-<br />

obiect concurente imperative <strong>de</strong>zvoltate pâna <strong>în</strong> prezent. Fiecare mo<strong>de</strong>l <strong>de</strong> concurenta<br />

implementat <strong>în</strong>tr-un astfel <strong>de</strong> limbaj <strong>de</strong> programare a fost <strong>analiza</strong>t pe baza unui set<br />

con<strong>si</strong>stent <strong>de</strong> principii <strong>de</strong> proiectare. De asemenea, pentru fiecare mo<strong>de</strong>l <strong>de</strong><br />

151


concurenta a fost propusa o exten<strong>si</strong>e a limbajului C++ <strong>si</strong> a fost prezentat un exemplu<br />

<strong>de</strong> <strong>implementare</strong> a unei cozi cu numar finit <strong>de</strong> elemente.<br />

Neajunsurile <strong>de</strong>terminate <strong>în</strong> mod unitar la nivelul mo<strong>de</strong>lelor <strong>de</strong> obiecte<br />

concurente au stat la baza <strong>de</strong>finirii notiunii <strong>de</strong> anomalie <strong>de</strong> reutilizare. S-a aratat ca<br />

anomaliile <strong>de</strong> reutilizare reprezinta un concept care surprin<strong>de</strong> atât anomaliile <strong>de</strong><br />

mostenire cât <strong>si</strong> conflictele care apar <strong>în</strong>tre mecanismele <strong>de</strong> specificare a <strong>concurentei</strong> <strong>si</strong><br />

relatiile <strong>de</strong> asociere, agregare <strong>si</strong> <strong>de</strong>legare <strong>în</strong>tre obiecte. Anomaliile <strong>de</strong> reutilizare sunt<br />

mo<strong>de</strong>late prin extin<strong>de</strong>rea unui <strong>si</strong>stem formal utilizat <strong>în</strong> cla<strong>si</strong>ficarea mecanismelor <strong>de</strong><br />

mostenire <strong>în</strong> programarea orientata-obiect concurenta.<br />

Tratarea formala a anomaliilor <strong>de</strong> reutilizare a permis <strong>de</strong>terminarea unui mo<strong>de</strong>l<br />

<strong>de</strong> obiecte concurente general care sta la baza <strong>de</strong>finirii unui formalism vizual <strong>de</strong><br />

mo<strong>de</strong>lare. Acest formalism reprezinta o exten<strong>si</strong>e a hartilor <strong>de</strong> stari <strong>de</strong>finite pentru<br />

mo<strong>de</strong>larea comportamentului <strong>si</strong>stemelor reactive. Formalismul vizual propus este un<br />

formalism executabil <strong>si</strong> el a fost numit harta <strong>de</strong> stari scalabila.<br />

În finalul tezei este <strong>de</strong>scrisa <strong>implementare</strong>a unui instrument <strong>de</strong> mo<strong>de</strong>lare a<br />

aplicatiilor orientate-obiect concurente. Acest instrument, numit ActiveCASE,<br />

vali<strong>de</strong>aza executabilitatea hartilor <strong>de</strong> stari scalabile <strong>si</strong> realizeaza generarea automata<br />

<strong>de</strong> cod sursa <strong>în</strong> limbajul C++, utilizând o ierarhie <strong>de</strong> clase concurente proprie. De<br />

asemenea instrumentul permite <strong>si</strong>mularea <strong>si</strong> <strong>de</strong>panarea grafica a executiei aplicatiilor<br />

orientate-obiect concurente.<br />

6.2. Perspective<br />

6.2.1. Anomalii <strong>de</strong> reutilizare<br />

Problema eliminarii anomaliilor <strong>de</strong> reutilizare din limbajele <strong>de</strong> programare<br />

orientate-obiect concurente ramâne <strong>în</strong> continuare <strong>de</strong>schisa. Notiunile <strong>de</strong> tip introduse<br />

<strong>în</strong> mo<strong>de</strong>lele obiect <strong>de</strong>zvoltate pâna <strong>în</strong> prezent nu rezolva aceasta problema. Solutiile<br />

<strong>de</strong> ameliorare a efectelor acestor anomalii propuse <strong>în</strong> teza vizeaza izolarea <strong>si</strong><br />

separarea codului contrângerilor <strong>de</strong> <strong>si</strong>ncronizare <strong>de</strong> codul <strong>de</strong> <strong>implementare</strong> a<br />

functionalitatii, precum <strong>si</strong> generarea automata <strong>de</strong> cod sursa.<br />

O alta po<strong>si</strong>bila abordare <strong>de</strong> ameliorare a anomaliilor <strong>de</strong> reutilizare este aceea<br />

<strong>de</strong> introducere a unui mecanism <strong>de</strong> sub-tipizare care nu conserva comportamentul.<br />

152


Astfel, adaugarea <strong>de</strong> noi operatii <strong>în</strong> cadrul unei clase nu va conduce <strong>în</strong> mod necesar la<br />

crearea <strong>de</strong> subtipuri ale tipului initial. Mecanismele fara conservare a<br />

comportamentului sunt mult mai expre<strong>si</strong>ve <strong>de</strong>cât cele cu conservare a<br />

comportamentului, <strong>si</strong> sunt capabile sa trateze mai multe anomalii <strong>de</strong> mostenire. În<br />

literatura <strong>în</strong>sa sunt foarte putine propuneri <strong>de</strong> astfel <strong>de</strong> mecanisme, <strong>de</strong>oarece ele<br />

implica o multime <strong>de</strong> probleme cum ar fi negarantarea relatiei <strong>de</strong> subtipizare sau<br />

nece<strong>si</strong>tatea unor studii <strong>în</strong> directia tehnicilor <strong>de</strong> <strong>analiza</strong> statica <strong>si</strong> a tehnicilor <strong>de</strong><br />

optimizare <strong>în</strong> ve<strong>de</strong>rea eficientizarii programelor.<br />

O alta po<strong>si</strong>bila solutie <strong>de</strong> reducere a anomaliilor are la baza tot respectarea<br />

principiului separarii codului <strong>de</strong> interactiune concurenta <strong>si</strong> consta <strong>în</strong> construirea <strong>de</strong><br />

biblioteci <strong>de</strong> politici generice <strong>de</strong> <strong>si</strong>ncronizare <strong>si</strong> concurenta. Astfel, <strong>în</strong> locul mostenirii<br />

partii <strong>de</strong> specificare <strong>si</strong> coordonare a <strong>concurentei</strong> dintr-o superclasa, o subclasa va avea<br />

po<strong>si</strong>bilitatea instantierii unei politici particulare. Aceasta abordare poate fi utila <strong>în</strong><br />

special <strong>în</strong> cazul specificarii <strong>concurentei</strong> interne, un<strong>de</strong> exista un numar relativ restrâns<br />

<strong>de</strong> politici utilizate (cum ar fi cititori/scriitor, prioritatea cititorilor etc).<br />

6.2.2. Mo<strong>de</strong>larea <strong>si</strong> <strong>si</strong>mularea aplicatiilor orientate-obiect concurente<br />

Hartile <strong>de</strong> stari scalabile reprezinta un formalism ce permite mo<strong>de</strong>larea<br />

comportamentului obiectelor concurente ce corespund mo<strong>de</strong>lelor obiect care<br />

utilizeaza mecanisme <strong>de</strong> <strong>si</strong>ncronizare orientate pe <strong>în</strong>capsulare. Astfel, receptionarea<br />

unui mesaj care nu poate fi tratat la un moment dat nu implica ignorarea acestuia, el<br />

fiind stocat <strong>în</strong>tr-o coada <strong>în</strong> ve<strong>de</strong>rea tratarii sale ulterioare. Exista <strong>în</strong>sa cazuri<br />

particulare <strong>de</strong> mesaje care nece<strong>si</strong>ta o planificare speciala, planificare ce ca<strong>de</strong> <strong>în</strong><br />

sarcina gestionarului <strong>de</strong> mesaje. Prin urmare, una dintre po<strong>si</strong>bilele exten<strong>si</strong>i ale<br />

hartilor <strong>de</strong> stari scalabile consta <strong>în</strong> capacitatea <strong>de</strong> mo<strong>de</strong>lare a planificarii mesajelor.<br />

De asemenea, mostenirea hartilor <strong>de</strong> stari scalabile reprezinta un alt subiect<br />

viitor <strong>de</strong> studiu. Automatizarea acestui proces, impunerea unor restrictii <strong>de</strong><br />

modificare a hartilor <strong>de</strong> stari mostenite precum <strong>si</strong> propagarea modificarilor hartilor <strong>de</strong><br />

stari ale sub-claselor <strong>în</strong> <strong>de</strong>scen<strong>de</strong>ntii acestora pot conduce la controlarea <strong>si</strong>/sau<br />

eliminarea conflictelor <strong>în</strong>tre mecanismul <strong>de</strong> mostenire <strong>si</strong> cel <strong>de</strong> <strong>si</strong>ncronizare<br />

concurenta.<br />

153


Simularea executiei obiectelor active poate fi îmbunatatita la rândul sau <strong>în</strong><br />

scopul unei testari riguroase <strong>si</strong> a unei <strong>de</strong>panari eficiente a aplicatiilor orientate-obiect<br />

concurente. Astfel, componentele intrumentului ActiveCASE utilizate <strong>în</strong> <strong>si</strong>mulare<br />

vor putea fi extinse pentru a permite blocarea executiei aplicatiei sau a unui anumit<br />

obiect la un moment dat, transmiterea <strong>de</strong> mesaje din afara aplicatiei sau chiar<br />

parcurgerea inversa a executiei aplicatiei.<br />

De asemenea se vor avea <strong>în</strong> ve<strong>de</strong>re realizarea <strong>de</strong> componente care sa verifice<br />

corectitudinea executiei aplicatiei prin <strong>de</strong>terminarea <strong>si</strong>tuatiilor <strong>de</strong> impas sau <strong>în</strong>calcarea<br />

proprietatii <strong>de</strong> vivacitate a activitatilor obiectelor precum <strong>si</strong> po<strong>si</strong>bilitatea <strong>de</strong> rezolvare<br />

a acestora <strong>în</strong> timpul executiei aplicatiei <strong>si</strong>mulate.<br />

154


Bibliografie<br />

[AAR96] Amund Aarsten, Davi<strong>de</strong> Brugali, Giuseppe Menga, De<strong>si</strong>gning<br />

Concurrent and Distributed Control Systems: an Approach Based on<br />

De<strong>si</strong>gn Patterns, Communication of ACM - Special Issue on De<strong>si</strong>gn<br />

Patterns, oct. 1996<br />

[AGH86] Gul Agha, Actors: A Mo<strong>de</strong>l of Concurrent Computation in Distributed<br />

Systems, MIT Press, Cambridge, 1986<br />

[AKS94] M. Ak<strong>si</strong>t, J. Bosch, W. van <strong>de</strong>r Sterren, L. Bergmans, Real-Time<br />

Specification Inheritance Anomalies and Real-Time Filters, Proceedings<br />

of ECOOP'94, Lecture Notes in Computer Science, vol. 821, Bologna,<br />

Italia, Springer-Verlag, p.386-407, iulie 1994<br />

[AME87] Pierre America, „POOL-T: A Parallel object-oriented language”, in<br />

Object Oriented Concurrent Programming, A. Yonezawa and M. Tokoro<br />

eds., MIT Press, 1987<br />

[AME90] Pierre America, De<strong>si</strong>gning an object-oriented programming language<br />

with behavioural subtyping, Foundations of Object-Oriented Languages,<br />

Lecture Notes in Computer Science, vol. 489, Noordwijkerhout, Olanda,<br />

Springer-Verlag, p. 60-90, iunie 1990<br />

[AND93] G. R. Andrews, R. A. Olsson, The SR Programming Language:<br />

Concurrency in Practice, Benjamin/Cummings Publishing Company,<br />

1993<br />

[ATK95] Colin Atkinson, Michel Izygon, ION A Notation for the Graphical<br />

Depiction of Object Oriented Programs, Cooperative agreement ncc 9-<br />

30, NASA, iul. 1995, disponibil pe Internet la adresa<br />

http://ricis.cl.uh.edu/atkinson/ion/.<br />

[BAQ95] C. Baquero, R. Oliveira, F. Moura, Integration of Concurrency Control<br />

in a Language with Subtyping and Subclas<strong>si</strong>ng, Usenix COOTS’95,<br />

Monterey, CA, 1995<br />

[BAR98] F. Barbier, H. Briand, B. Dano, S. Ri<strong>de</strong>au, The Executability of Object-<br />

Oriented Finite State Machines, The Journal of Object-Oriented<br />

Programming, 11(4), p. 16-24, iul./aug. 1998<br />

155


[BEE94] Michael von <strong>de</strong>r Beeck, A Comparison of Statecharts Variants, Formal<br />

Techniques in Real-Time and Fault-Tolerant Systems, Lecture Notes in<br />

Computer Science, vol. 863, Springer-Verlag, New York, p 128-148,<br />

1994<br />

[BER92] G. Berry, G. Gonthier, The Esterel synchronous programming language:<br />

De<strong>si</strong>gn, semantics, implementation, Science of Computer Programming,<br />

19(2), p. 87-152, 1992<br />

[BER94] Lo<strong>de</strong>wijk M. J. Bergmans, Compo<strong>si</strong>ng Concurrent Objects, teza<br />

doctorat, Twente Univer<strong>si</strong>ty, iunie 1994<br />

[BLO79] T. Bloom, Evaluating synchronization mechanisms, Proc. of the 7th<br />

Sympo<strong>si</strong>um on Operating Systems Principles, p. 24-32, Pacific Grove,<br />

CA, <strong>de</strong>c. 1979<br />

[BLU97] Lazlo Blum, Lazlo Kozma, Specifying Objects in Concurrent Object-<br />

Oriented Systems U<strong>si</strong>ng Temporal Logic, International COnference on<br />

Applied Informatics, Eger-Noszvaj, Ungaria, p. 313-322, aug. 1997<br />

[BOI94] Florian Mircea Boian, Sisteme <strong>de</strong> operare interactive, ed. Libris, Cluj-<br />

Napoca, 1994<br />

[BOO91] Grady Booch, Object Oriented De<strong>si</strong>gn With Applications, Benjamin/<br />

Cummings Publishing Company, Inc., Redwood City, California 1991<br />

[BOR95] A. V. Borshchev, Yu. G. Karpov, V. V. Roudakov, COVERS - A Tool<br />

for the De<strong>si</strong>gn of Real-Time Concurrent Systems, V. Malyshkin (ed.),<br />

Parallel Computing Technologies, Proceedings of the 3rd International<br />

Conference PACT-95, Lecture Notes in Computer Science, vol. 964,<br />

Springer Verlag, p. 219-233, 1995<br />

[BOZ94a] D. Bozga, D. Chiorean, A. Frentiu, B. Rus, V. Scuturici, D. M. Suciu, D.<br />

Va<strong>si</strong>lescu, Rocase - CASE Tool for Object-Oriented Analy<strong>si</strong>s and<br />

De<strong>si</strong>gn, Research Seminars, Seminar on Computer Science, Univ.<br />

"Babes-Bolyai" Cluj-Napoca, preprint no 5, p. 29-36, 1994<br />

[BOZ94b] D. Bozga, D. Chiorean, A. Frentiu, B. Rus, V. Scuturici, D. M. Suciu, D.<br />

Va<strong>si</strong>lescu, OOA&D: the Tran<strong>si</strong>tion Among Mo<strong>de</strong>ls, Research Seminars,<br />

Seminar on Computer Science, Univ. "Babes-Bolyai" Cluj-Napoca,<br />

preprint no 5, p. 37-44, 1994<br />

[BRI93] Jean-Pierre Briot, Object-Oriented Concurrent Programming:<br />

Introducing a New Programming Methodology, Proceedings of the 7th<br />

International Meeting of Young Computer Scientists, 1993<br />

[BRO81] J. D. Brock, W. B. Ackerman, Scenarios: a mo<strong>de</strong>l of non-<strong>de</strong>terministic<br />

computation, Formalization of Programming Concepts (Diaz and Ramos<br />

eds), Lecture Notes in Computer Science, vol. 107, Springer-Verlag, p.<br />

252-259, 1981<br />

[CAR90] Denis Caromel, Concurrency: An Object-Oriented Approach, TOOLS-<br />

2, (eds.) J. Bezivin, B. Meyer, J. M. Nerson, 1990, p. 183-197<br />

[CAR93] Denis Caromel, Toward a Method of Object-Oriented Concurrent<br />

Programming, Communication of the ACM, vol. 36, no. 9, sept. 1993,<br />

p. 90-102<br />

156


[CHI96] Dan Chiorean, Instrumente CASE pentru <strong>analiza</strong> <strong>si</strong> proiectare orientataobiect,<br />

PC REPORT, 46, p. 24-27, 1996<br />

[CHI97] Dan Chiorean, Iulian Ober, Marian Scuturici, Dan Mircea Suciu,<br />

Present and Perspectives in the Object-Oriented Analy<strong>si</strong>s & De<strong>si</strong>gn -<br />

The RO-CASE Experience, The Third International Sympo<strong>si</strong>um in<br />

Economic Informatics, p. 23-29, Bucharest, mai 1997<br />

[COL92] D. Coleman, F. Hayes, S. Bear, Introducing Objectcharts or How to Use<br />

Statecharts in Object-Oriented De<strong>si</strong>gn, IEEE Transaction on Software<br />

Engineering, Vol. 18, No. 1, p. 9-18, ian 1992<br />

[COO89] W. Cook, J. Palsberg, A <strong>de</strong>notational semantics of inheritance and its<br />

correctness, OOPSLA'89, p. 433-443, New Orleans, 1989<br />

[COO94] Steve Cook, John Daniels, Object Systems. Object-Oriented Mo<strong>de</strong>ling<br />

with Syntropy, Prentice Hall, 1994<br />

[CRN97a] L. Crnogorac, A. Rao, K. Ramamohanarao, Analy<strong>si</strong>s of Inheritance<br />

Mechanisms in Agent-Oriented Programming, Proceedings of IJCAI'97,<br />

p. 647-652, Nagoya, Japonia, aug. 1997<br />

[CRN97b] L. Crnogorac, A. Rao, K. Ramamohanarao, Inheritance Anomaly - a<br />

Formal Treatment, FMOODS'97, p.319-334, Anglia, iul. 1997<br />

[CRN98] L. Crnogorac, A. Rao, K. Ramamohanarao - Clas<strong>si</strong>fying Inheritance<br />

Mechanisms in Concurrent Object-Oriented Programming, ECOOP '98,<br />

p. 571-600, 1998<br />

[DAH67] O.-J. Dahl, K. Nygaard, SIMULA- A language for Programming and<br />

Description of Discrete Event Systems, Norwegian Computing Center,<br />

Forskningveien 1B, 5th edition, Oslo 3, Norvegia, sept. 1967<br />

[DIJ68] E. W. Dijkstra, Co-operating sequential processes, Programming<br />

Languages, p. 43-112, 1968<br />

[DOR96] Dov Dori, Unifying System Structure and Behavior Through Object-<br />

Process Analy<strong>si</strong>s, The Journal of Object-Oriented Programming, 9(4), p.<br />

66-73, iul./aug. 1996<br />

[DOU99] Bruce Powel Douglass, Doing Hard Time. Developing Real-Time<br />

Systems with UML, Objects, Frameworks and Patterns, Addison-<br />

Wesley, 1999<br />

[ELE91] Petru Eles, Horia Ciocârlie, Programarea concurenta <strong>în</strong> limbaje <strong>de</strong> nivel<br />

<strong>în</strong>alt, Editura Stiintifica, Bucuresti, 1991<br />

[ELI92] Giuseppe Elia, Giuseppe Menga, Mario Cavalotto, Object Oriented<br />

Analy<strong>si</strong>s and De<strong>si</strong>gn of Distributed Concurrent Systems, Technical<br />

Report grant 89.00039.69, Dip. di Automatica e Informatica <strong>de</strong>l<br />

Politecnico di Torino, 1992<br />

[FER95] Szabolcs Ferenczi, Guar<strong>de</strong>d Methods vs. Inheritance Anomaly /<br />

Inheritance Anomaly Solved by Nested Guar<strong>de</strong>d Method Calls,<br />

SIGPLAN Notices 30(2): 49-58, 1995<br />

157


[FRO92] Svend Frølund, Inheritance of Sinchronization Constraints in<br />

Concurrent Object-Oriented Programming Languages, Proceeding of<br />

ECOOP'92, L. Madsen editor, Lecture Notes in Computer Science, vol.<br />

615, p. 185-196, Springer-Verlag, Utrecht, Netherlands, 1992<br />

[GAN93] D. Gangopadhyay, S. Mitra, ObjChart: Tangible Specification of<br />

Reactive Object Behavior, Proceedings of ECOOP'93, Oscar Nierstrasz<br />

(ed.), LNCS 707, Springer Verlag, p. 432-457, 1993<br />

[GEO96] Horia Georgescu, Programare concurenta. Teorie <strong>si</strong> aplicatii, Editura<br />

Tehnica, Bucuresti, 1996<br />

[GIR97] Alain Girault, Bilung Lee, Edward A. Lee, Hierarchical Finite State<br />

Machines with Multiple Concurrency Mo<strong>de</strong>ls, Technical Memorandum<br />

Univer<strong>si</strong>ty of California at Berkeley, aug. 1997<br />

[GOL83] A. Goldberg, D. Robson, Smalltalk-80: The Language and its<br />

Implementation, Addison-Wesley, 1983<br />

[HAN72] P. Brinch Hansen, Structured multiprogramming, Communications of<br />

the ACM, 15(7), p. 574-578, iulie 1972<br />

[HAN73] P. Brinch Hansen, Concurrent programming concepts, ACM Computing<br />

Surveys, 5(4), p. 223-245, <strong>de</strong>c. 1973<br />

[HAR85] D. Harel, A. Pnueli, On the Development of Reactive Systems, Logics<br />

and Mo<strong>de</strong>ls of Concurrent Systems, NATO, ASI-13, Springer-Verlag, p.<br />

477-498, 1985<br />

[HAR87] David Harel, Statecharts: A Visual Formalism for Complex Systems,<br />

Science of Computer Programming, vol.8, no. 3, p. 231-274, iun. 1987<br />

[HAR96] D. Harel, A. Naamad, The STATEMATE Semantics of Statecharts, ACM<br />

Transaction on Software Engineering and Methodology, 5(4), p. 293-<br />

333, oct. 1996<br />

[HAR97] David Harel, Eran Gery, Executable Object Mo<strong>de</strong>ling with Statecharts,<br />

IEEE Computer, 0018-9162/97, p. 31-42, iulie 1997<br />

[HEN97] Brian Hen<strong>de</strong>rson-Sellers, Evaluating Third Generation Object-Oriented<br />

Software Development Approaches, predat la "Information and Software<br />

Technology", mai 1997<br />

[HOA74] C. A. R. Hoare, Monitors: an Operating System Structuring Concepts,<br />

Communications of the ACM, no. 17(10), p. 549-557, oct. 1974<br />

[HOA85] C. A. R. Hoare, Communicating Sequential Processes, Prentice-Hall<br />

International Series in Computer Science, Prentice-Hall, 1985<br />

[HOR83] E. Horowitz, Fundamentals of Programming Languages, Springer<br />

Verlag, 1983<br />

[HUI88] C. Huizing, R. Gerth, W. P. <strong>de</strong> Roever, Mo<strong>de</strong>lling Statecharts behaviour<br />

in a fully abstract way, LNCS, vol. 299, Springer Verlag, p. 271-294,<br />

1988<br />

[HUI91] C. Huizing, Semantics of Reactive Systems: Comparison and Full<br />

Abstraction, teza <strong>de</strong> doctorat, Technical Univer<strong>si</strong>ty Eindhoven, Olanda,<br />

1991<br />

158


[HUT87] N. C. Hutchinson, R. K. Raj, A. P. Black, H. M. Levy, E. Jul, The<br />

Emerald programming language report, Technical Report 87-10-07,<br />

Department of Computer Science, Univer<strong>si</strong>ty of Washington, Seattle,<br />

oct. 1987<br />

[iLO87] i-Logix Inc., The Languages of STATEMATE, <strong>în</strong> "Documentation for the<br />

STATEMATE System", 1987<br />

[JAC92] Ivar Jacobson, M. Christerson, P. Jonsson, G. Overgaard, Object-<br />

Oriented Software Engineering - A Use Case Driven Approach,<br />

Addison-Wesley/ ACM Press, 1992<br />

[KAF88] D. G. Kafura, K. H. Lee, Inheritance in Actor Based Concurrent Object-<br />

Oriented Languages, Technical Report TR 88-53 Departement of<br />

Computer Science Virginia polytechnic Institute and State univer<strong>si</strong>ty,<br />

1988<br />

[KAF90] D. Kafura, K. H. Lee, ACT++: Building a concurrent C++ with Actors,<br />

Journal of Object Oriented Programming, 3(1), p. 25-37, mai 1990<br />

[KAF93] D. Kafura, M. Mukherji, G. Laven<strong>de</strong>r, ACT++ 2.0: A Class Library for<br />

Concurrent Programming in C++ U<strong>si</strong>ng Actors, Journal of Object<br />

Oriented Programming, 6(3), p. 45-53, 1993<br />

[KES77] J. L. W. Kessels, An alternative to event queues for synchronization in<br />

monitors, Communications of the ACM, no. 20 (7), p. 500-503, iul.<br />

1977<br />

[KRA90] S. Kralowiak, M. Meysembourg, H. Nguyen Van, M. Riveill, C. Roi<strong>si</strong>n,<br />

X. Rousset <strong>de</strong> Pina, De<strong>si</strong>gn and implementation of an object-oriented,<br />

strongly typed language for distributed applications, Journal of Object<br />

oriented Programming, 3 (3), p. 11-22, sept./oct. 1990<br />

[LEC96] Ulrike Lechner, Christian Lengauer, Frie<strong>de</strong>rike Nickl, Martin Wir<strong>si</strong>ng,<br />

(Objects + Concurrency) & Reusability - A Proposal to Circumvent the<br />

Inheritance Anomaly, Proceedings of ECOOP'96, Lecture Notes in<br />

Computer Science, vol. 1098, p. 232-247, Springer-Verlag, Linz,<br />

Austria, 1996<br />

[LEC97] Ulrike Lechner, Object-Oriented Specification of Distributed Systems,<br />

Univer<strong>si</strong>tät Passau, Fakultät für Mathematik und Informatik, teza<br />

doctorat, iunie 1997<br />

[LÖH93] Klaus-Peter Löhr, Concurrency annotations for reusable software,<br />

Communication of the ACM , 36(9), p81-89, sep. 1993<br />

[MAC96] Stuart Maclean, Sean Smith, Direct Mapping of Object-Oriented<br />

Analy<strong>si</strong>s Mo<strong>de</strong>ls into C++ U<strong>si</strong>ng Asynchronous Messaging, The Journal<br />

of Object-Oriented Programming, 9(5), p. 24-31, sept. 1996<br />

[MAI97] Christoph Maier, Luis Man<strong>de</strong>l, Object-Oriented Development of<br />

Distributed Systems – a Survey, <strong>de</strong>c. 1997, disponibil pe Internet la<br />

adresa http://www.fast.<strong>de</strong>/Projekte/forsoft/oosurvey/in<strong>de</strong>x.html<br />

[MAN74] Z. Manna, Mathematical Theory of Computation, McGraw-Hill, 1974<br />

159


[MAT90] Satoshi Matsuoka, Ken Wakita, Akinori Yonezawa, Sinchronization<br />

Constraints With Inheritance: What Is Not Pos<strong>si</strong>ble - So What Is?,<br />

Technical Report 10, Department of Information Science, Univer<strong>si</strong>ty of<br />

Tokyo, 1990<br />

[MAT93] Satoshi Matsuoka, Akinori Yonezawa, Analy<strong>si</strong>s of Inheritance Anomaly<br />

in Object-Oriented Concurrent Programming Languages, Research<br />

Directions in Concurrent Object-Oriented Programming, p.107-150,<br />

MIT Press, Cambridge, 1993<br />

[MCH94] Ciaran McHale, Synchronization in Concurrent, Object-Oriented<br />

Languages: Expres<strong>si</strong>ve Power, Genericity and Inheritance, teza<br />

doctorat, Department of Computer Science, Trinity College, Dublin 2,<br />

Irlanda, oct. 1994<br />

[MES93] J. Meseguer, Solving the inheritance anomaly in concurrent objectoriented<br />

programming, Proceedings of ECOOP'93, Lecture Notes in<br />

Computer Science, vol. 707, Kaiserlautern, Germania, Springer-Verlag,<br />

p.220-246, iulie 1993<br />

[MEY93] Bertrand Meyer, Systematic Concurrent Object-Oriented Programming,<br />

Communication of the ACM, Vol 36, no9, 1993, p.56-80<br />

[MIT94] S. E. Mitchel, A. J. Wellings, Synchronisation, Concurrent Object-<br />

Oriented Programming and the Inheriyance Anomaly, jun. 1994<br />

[MOL00] Grigor Moldovan, Limbaje formale <strong>si</strong> tehnici <strong>de</strong> compilare, Centrul <strong>de</strong><br />

Formare Continua <strong>si</strong> Învatamânt la Distanta, Univ. “Babes-Bolyai”,<br />

Cluj-Napoca, 2000<br />

[MOL97] Grigor Moldovan, Limbaje formale <strong>si</strong> teoria automatelor, ed. Mesagerul,<br />

Cluj-Napoca, 1997<br />

[NIE87] O. Nierstrasz, Active objects in Hybrid, Proc. of OOPSLA'87, Conf. on<br />

Object Oriented Programming Systems, Languages and Applications,<br />

Orlando, Florida, ACM SIGPLAN Notices 22(12), p. 243-253, oct. 1987<br />

[OBE99] Iulian Ober, Ileana Stan, On the Concurrent Object Mo<strong>de</strong>l of UML,<br />

Proceedings of EuroPar'99, Toulouse. Lecture Notes in Computer<br />

Science, No. 1685, Springer Verlag, 1999<br />

[OMG99] Object Management Group, OMG Unified Mo<strong>de</strong>ling Language<br />

Specification, ver. 1.3, iunie 1999 disponibil pe Internet la adresa<br />

http://www.rational.com/<br />

[PAP89] Michael Papathomas, Concurrency Issues in Object-Oriented<br />

Programming Languages, in D. T<strong>si</strong>chritzis, editor, Object Oriented<br />

Development, p. 207-245, Univer<strong>si</strong>ty of Geneva, Switzerland, 1989<br />

[PAP92] Michael Papathomas, Language De<strong>si</strong>gn Rationale and Semantic<br />

Framework for Concurrent Object-Oriented Programming, teza<br />

doctorat, Dept. of Computer Science, Univer<strong>si</strong>ty of Geneva, 1992<br />

[PAP96] Michael Papathomas, ATOM: An Active Object Mo<strong>de</strong>l for Enhancing<br />

Reuse in the Development of Concurrent Software, Research Report,<br />

Ecole Nationale Superieure d'Informatique et <strong>de</strong> Mathematique<br />

Appliques <strong>de</strong> Grenoble, France, nov. 1996<br />

160


[PAP97] Michael Papathomas, An<strong>de</strong>rs An<strong>de</strong>rsen, Concurrent Object-Oriented<br />

Programming in Python with ATOM, Proceedings of the 6th<br />

International Python Conference, California, oct. 1997<br />

[PAR80] D. M. R. Park, Concurrency and Automata on Infinite Sequences,<br />

Lecture Notes in Computer Science, Vol 104, Springer Verlag, 1980.<br />

[PHI95a] Michael Phillipsen, Imperative Concurrent Object-Oriented Languages,<br />

Technical Report TR-95-049, International Computer Science Institute,<br />

Berkeley, aug. 1995<br />

[PHI95b] Michael Phillipsen, Imperative Concurrent Object-Oriented Languages:<br />

An annotated bibliography, Technical Report TR-95-049, International<br />

Computer Science Institute, Berkeley, aug. 1995<br />

[PIE95] Benjamin C. Pierce, Fundational Calculi for Programming Languages,<br />

CRC Handbook of Computer Science and Engineering, 1995<br />

[PUN96] Franz Puntigam, Coordination Requirements Expressed in Types for<br />

Active Objects, ECOOP p.367-388, 1996<br />

[QUI97] P. H. Quiros, Jose M. Olmo Millan, Inheritance Anomaly in CORBA<br />

Multithrea<strong>de</strong>d Environments, Theory and Practice of Object Systems,<br />

no. 1/3, 1997<br />

[REI96] Stephan Reitzner, Synchronizing Classes: Splitting Inheritance<br />

Concepts, Technical Report, Computer Science Department, Friedrich<br />

Alexan<strong>de</strong>r Univer<strong>si</strong>ty, Nürnberg, iul. 1996<br />

[RUM91] James Rumbaugh, Michael Blaha, William Premerlani, Fre<strong>de</strong>rick Eddy,<br />

William Lorensen, Object-Oriented Mo<strong>de</strong>ling and De<strong>si</strong>gn, Prentice Hall,<br />

Englewood Cliffs, 1991<br />

[RUM93] J. Rumbaugh, Controlling Co<strong>de</strong>: How to implement dynamic mo<strong>de</strong>ls,<br />

The Journal of Object-Oriented Programming, 6(2), p. 25-30, feb. 1993<br />

[RUM96] J. Rumbaugh, A State of Mind: Mo<strong>de</strong>ling Behavior, The Journal of<br />

Object-Oriented Programming, 9(4), p. 6-12, iul./aug. 1996<br />

[SCH86] C. Schaffert, T. Cooper, B. Bullis, M. Kilian, C. Wilpolt, An<br />

introduction to Trellis/Owl, Proc. of OOPSLA'86, Conference on<br />

Object-Oriented Programming Systems, Languages and Applications,<br />

Portland, Oregon, p. 9-15, sept 1986<br />

[SCU97] Marian Scuturici, Dan Mircea Suciu, Mihaela Scuturici, Iulian Ober,<br />

Specification of active objects behavior u<strong>si</strong>ng statecharts, Studia<br />

Univer<strong>si</strong>tatis "Babes Bolyai", Informatica, Vol. XLII, Nr. 1, p.19-30,<br />

1997<br />

[SET89] Ravi Sethy, Programming Languages Concepts and Constructs,<br />

Addison-Wesley, 1989<br />

[SHL88] S. Shlaer, S. J. Mellor, Object Oriented Systems Analy<strong>si</strong>s: Mo<strong>de</strong>ling the<br />

Worl in Data, Yourdon Press Computing Series, 1988<br />

[STR91] Bjarne Stroustrup, The C++ Programming Language (second edition),<br />

Addison Wesley, 1991<br />

161


[STU97] Shelly S. Stubbs, D. L. Carver, IPCC++: InterProcess Communication<br />

with C++, The Journal of Object-Oriented Programming, 9(9), p. 31-40,<br />

febr. 1997<br />

[SUC96a] Dan Mircea Suciu, Trei instrumente CASE la ora analizei, PC REPORT,<br />

iul. p. 32-35, 1996<br />

[SUC96b] Dan Mircea Suciu, RO-CASE, PC REPORT, iul. p. 40-41, 1996<br />

[SUC97a] Dan Mircea Suciu, Reuse Anomaly in Object-Oriented Concurrent<br />

Programming, Studia Univer<strong>si</strong>tatis "Babes-Bolyai", Informatica, Vol.<br />

XLII, Nr. 2, p. 74-89, 1997<br />

[SUC97b] Dan Mircea Suciu, Limbaje <strong>de</strong> programare orientate obiect concurente,<br />

PC REPORT, aug. 1997<br />

[SUC98a] Dan Mircea Suciu, Iulian Ober, Contructia <strong>si</strong>stemelor software -<br />

OPEN/OML, PC REPORT, feb. p. 28-32 1998<br />

[SUC98b] Dan Mircea Suciu, Anomalii <strong>de</strong> mostenire <strong>în</strong> programarea orientataobiect<br />

concurenta, referat <strong>de</strong> doctorat, Univer<strong>si</strong>tatea "Babes-Bolyai"<br />

Cluj Napoca, mai 1998<br />

[SUC98c] Dan Mircea Suciu, Mo<strong>de</strong>le <strong>de</strong> concurenta, referat <strong>de</strong> doctorat,<br />

Univer<strong>si</strong>tatea "Babes-Bolyai" Cluj Napoca, septembrie 1998<br />

[SUC98d] Dan Mircea Suciu, Analiza <strong>si</strong> <strong>proiectarea</strong> obiectelor concurente, referat<br />

<strong>de</strong> doctorat, Univer<strong>si</strong>tatea "Babes-Bolyai" Cluj Napoca, <strong>de</strong>cembrie 1998<br />

[SUC98e] Dan Mircea Suciu, Application Framework Reuse U<strong>si</strong>ng CASE Tools,<br />

Studia Univer<strong>si</strong>tatis “Babes Bolyai”, Informatica, Vol. XLIII, Nr. 2, p.<br />

81-92, 1998,<br />

[SUC99] Dan Mircea Suciu, Extending Statecharts for Concurrent Objects<br />

Mo<strong>de</strong>ling, Studia Univer<strong>si</strong>tatis “Babes Bolyai”, Informatica, Vol. XLIV,<br />

Nr. 1, p. 37-44, 1999<br />

[THO94] Laurent Thomas, Inheritance Anomaly in True Concurrent Object<br />

Oriented Languages: A Proposal, IEEE TENCON'94, p. 541-545, aug.<br />

1994<br />

[TOM89] C. Tomlinson, V. Singh, Inheritance and synchronization with Enabledsets,<br />

Proc. of OOPSLA'89, Conf. on Object-Oriented Programming<br />

Systems, Languages and Applications, New Orleans, Loui<strong>si</strong>ana, p. 103-<br />

112, oct. 1989<br />

[YOK87] Y. Yokote, M.Tokoro, Experience and Evolution of Concurrent<br />

Smalltalk, proceedings OOPSLA '87, ACM, Orlando, Florida, p. 406-<br />

415, <strong>de</strong>c. 1987<br />

[YON87a] Akinori Yonezawa, Jean-Pierre Briot, Inheritance and Synchronization<br />

in Concurrent Object Oriented Programming, Proceedings of the<br />

European Conference on Object-Oriented Programming (ECOOP'87),<br />

Lecture Notes in Computer Science, no. 276, p. 32-40, Springer -<br />

Verlag, 1987<br />

162


[YON97b] A. Yonezawa, E. Shibayama, T. Takada, Y. Honda, Mo<strong>de</strong>ling and<br />

Programming in an Object-Oriented Concurrent Language ABCL/1,<br />

Object-Oriented Concurrent Programming, Yonezawa and Tokoro eds.,<br />

The MIT Press, Cambridge, Massachusetts, p. 88-89, 1987<br />

[ZEN97a] Nanshan Zeng, Stephen R. Schach, A Critique of "Inheritance in<br />

Concurrent Object-Oriented Programming: Doing more with ATOM",<br />

Technical Report 97-01, Department of Computer Science Van<strong>de</strong>rbilt<br />

Univer<strong>si</strong>ty, Nashville, USA, febr. 1997<br />

[ZEN97b] Nanshan Zeng, Stephen R. Schach, A New Approach to the Inheritance<br />

Anomaly, submitted for publication, 1997<br />

163


Anexa A. Notatii matematice<br />

A.1. Multimi<br />

Fie multimile M, M1, M2. Am utilizat urmatoarele notatii pentru a exprima<br />

operatii asupra multimilor:<br />

- ? reprezinta multimea vida,<br />

- M1 ? M2 reprezinta reuniunea multimilor M1 <strong>si</strong> M2,<br />

- M1 ? M2 reprezinta intersectia multimilor M1 <strong>si</strong> M2,<br />

- M1 \ M2 reprezinta diferenta multimilor M1 <strong>si</strong> M2,<br />

- M1 ? M2 reprezinta incluziunea multimilor M1 <strong>si</strong> M2,<br />

- M1 ? M2 reprezinta produsul cartezian al multimilor M1 <strong>si</strong> M2,<br />

- ? M? reprezinta cardinalul multimii M,<br />

- ? (M) reprezinta multimea partilor lui M,<br />

- M* reprezinta multimea secventelor <strong>de</strong> zero sau mai multe elemente din M.<br />

Am utilizate urmatoarele multimi particulare:<br />

- ( + ) - multimea numerelor naturale (strict pozitive),<br />

- - multimea valorilor booleene, cu elemente {true, false}.<br />

A.2. Relatii binare<br />

Fie R o relatie binara <strong>de</strong>finita pe multimea M, notata (M, R). Am facut referire<br />

<strong>în</strong> cadrul tezei la urmatoarele proprietati ale relatiilor binare:<br />

- reflexivitate: ? x ? M (x, x) ? R<br />

164


ar fi n ? N.<br />

- <strong>si</strong>metrie: ? x, y ? M (x, y) ? R ? (y, x) ? R<br />

- anti<strong>si</strong>metrie: ? x, y ? M (x, y) ? R ? (y, x) ? R ? x = y,<br />

- tranzitivitate: ? x, y, z ? M (x, y) ? R ? (y, z) ? R ? (x, z) ? R.<br />

Relatii binare particulare:<br />

- preordine: relatie reflexiva <strong>si</strong> tranzitiva,<br />

- ordine partiala: relatie reflexiva, anti<strong>si</strong>metrica <strong>si</strong> tranzitiva,<br />

- ordine totala: ordine partiala <strong>si</strong> ? x, y ? M, (x, y) ? R ? (y, x) ? R,<br />

- echivalenta: relatie reflexiva, <strong>si</strong>metrica <strong>si</strong> tranzitiva.<br />

Fie N o submultime a multimii M (N ? M).<br />

Un element m ? M este limita inferioara a multimii N daca (m, n) ? R oricare<br />

O limita inferioara m pentru N este cea mai mare limita inferioara pentru N<br />

daca <strong>si</strong> numai daca pentru fiecare limita inferioara m’ a lui N avem (m’, m) ? R.<br />

pN.<br />

A.3. Functii<br />

Atunci când exista, vom nota cea mai mare limita inferioara a multimii N cu<br />

O functie este o aplicatiei f : M1 ? M2 care asociaza fiecarui element x ? M1<br />

un element unic y ? M2. M1 poarta numele <strong>de</strong> domeniu <strong>de</strong> <strong>de</strong>finitie, iar M2 co-<br />

domeniul sau domeniul <strong>de</strong> valori al functiei f.<br />

Fie n ? <strong>si</strong> xi ? M1 <strong>si</strong> yi ? M2 pentru 1? i ? n. Vom nota cu f[y1/x1,..., yn/xn]<br />

functia g : M1 ? M2 <strong>de</strong>finita astfel:<br />

? yi<br />

, daca x ? xi<br />

g(<br />

x)<br />

? ?<br />

.<br />

? f ( x),<br />

in rest<br />

165


Anexa B. Notatii UML<br />

Unified Mo<strong>de</strong>ling Language (UML) este un limbaj <strong>de</strong> specificare <strong>si</strong> mo<strong>de</strong>lare<br />

orientata-obiect a entitatilor <strong>si</strong> relatiilor care compun <strong>si</strong>stemele informatice complexe.<br />

El a fost realizat <strong>în</strong> urma cererii <strong>de</strong> standardizarea propuse <strong>de</strong> consortiul international<br />

Object Management Group (OMG), <strong>si</strong> a <strong>de</strong>venit limbajul standard <strong>de</strong> mo<strong>de</strong>lare la data<br />

<strong>de</strong> 17 noiembrie 1997. Denumirea limbajului provine din faptul ca el a rezultat <strong>în</strong><br />

urma unificarii a trei importante meto<strong>de</strong> <strong>de</strong> <strong>analiza</strong> <strong>si</strong> proiectare a aplicatiilor<br />

orientate-obiect: Object Oriented De<strong>si</strong>gn (OOD - [BOO91], Object Mo<strong>de</strong>ling<br />

Technique (OMT - [RUM91]) <strong>si</strong> Objectory ([JAC92]).<br />

UML a fost conceput ca un limbaj universal care sa fie utilizat la mo<strong>de</strong>larea<br />

<strong>si</strong>stemelor indiferent <strong>de</strong> tipul <strong>si</strong> scopul pentru care acestea au fost construite, la fel<br />

cum limbajele <strong>de</strong> programare, sau mai larg limbajele naturale sunt folo<strong>si</strong>te <strong>în</strong> cele mai<br />

diverse domenii.<br />

UML este un limbaj grafic, vizual, care alaturi <strong>de</strong> <strong>de</strong>finirea unor concepte <strong>de</strong><br />

mo<strong>de</strong>lare furnizeaza <strong>si</strong> un set <strong>de</strong> notatii grafice <strong>de</strong> reprezentare a acestora. De<strong>si</strong> gama<br />

<strong>de</strong> mo<strong>de</strong>le are pot fi realizate cu UML este bogata, <strong>în</strong> cele ce urmeaza sunt prezentate<br />

doar conceptele <strong>si</strong> notatiile corespunzatoare mo<strong>de</strong>lelor structurale <strong>si</strong><br />

comportamentale. Acestea au fost utilizate pe parcursul tezei <strong>în</strong> constructia unor<br />

exemple. În particular, mo<strong>de</strong>larea comportamentala este <strong>analiza</strong>ta <strong>în</strong> <strong>de</strong>taliu <strong>în</strong> cadrul<br />

capitolului patru, ea stând la baza rezultatelor obtinute <strong>în</strong> teza <strong>în</strong> directia mo<strong>de</strong>larii<br />

comportamentului obiectelor active.<br />

166


B.1. Diagrame <strong>de</strong> clase<br />

UML utilizeaza diagramele <strong>de</strong> clase pentru <strong>de</strong>scrierea statica, structurala a<br />

unui <strong>si</strong>stem. Diagramele <strong>de</strong> clase specifica strutura claselor <strong>si</strong> relatiile existente <strong>în</strong>tre<br />

acestea. Clasele <strong>în</strong> UML se reprezinta grafic sub forma unor dreptunghiuri care<br />

contin <strong>în</strong> partea superioara numele clasei. Optional dreptunghiul <strong>de</strong> reprezentare a<br />

unei clase poate contine doua compartimente speciale, care <strong>de</strong>tin o lista <strong>de</strong> proprietati<br />

(atribute), respectiv o lista <strong>de</strong> operatii (meto<strong>de</strong>).<br />

Tipurile <strong>de</strong> relatii <strong>în</strong>tre clase <strong>de</strong>finite <strong>în</strong> UML utilizate <strong>în</strong> cadrul tezei sunt:<br />

asocierea, agregarea, compunerea <strong>si</strong> generalizarea.<br />

Asocierile sunt relatii care permit specificarea comunicarii <strong>în</strong>tre obiecte prin<br />

intermediul mesajelor. Reprezentarea grafica a asocierilor se realizeaza prin linii<br />

<strong>si</strong>mple sau linii compuse din segmente care unesc doua clase. În lipsa unei specificari<br />

explicite, asocierile sunt relatii bidirectionale <strong>si</strong> permit transmiterea <strong>de</strong> mesaje <strong>în</strong><br />

ambele directii. Atunci când transmiterea <strong>de</strong> mesaje se realizeaza strict <strong>în</strong>tr-o directie,<br />

acest lucru este specificat prin intermediul unei sageti <strong>în</strong> capatul asocierii<br />

corespunzator clasei <strong>de</strong> obiecte care receptioneaza mesajele.<br />

<strong>si</strong>mboluri pentru<br />

vizibilitate<br />

<strong>si</strong>mbol mostenire<br />

clase<br />

proprietati<br />

operatii<br />

167<br />

multiplicitate<br />

<strong>si</strong>mbol agregare<br />

nume <strong>de</strong> rol<br />

Figura B.1. Principalele notatii utilizate <strong>în</strong> diagramele <strong>de</strong> clase UML<br />

Asocierea este o relatie <strong>în</strong>tre clase. O instanta a unei asocieri poarta numele <strong>de</strong><br />

legatura. Legaturile au loc <strong>în</strong>tre obiectele rezultate <strong>în</strong> urma instantierii claselor aflate<br />

<strong>în</strong> relatia <strong>de</strong> asociere.<br />

La ambele capete ale unei asocieri pot fi afisate anumite valori <strong>în</strong>tregi, sau<br />

intervale <strong>de</strong> valori, care reprezinta multiplicitatea relatiei <strong>si</strong> specifica numarul


obiectelor care sunt implicate <strong>în</strong> respectiva relatie. În lipsa unei specificari explicite,<br />

multiplicitatea este con<strong>si</strong><strong>de</strong>rata implicit 1.<br />

Asocierile pot avea atasat un nume. Rolul jucat <strong>de</strong> obiectele fiecarei clase <strong>în</strong><br />

cadrul asocierii poate fi <strong>de</strong>scris optional prin intermediul unor nume <strong>de</strong> rol, atasate la<br />

capetele asocierii.<br />

Agregarea este o relatie <strong>de</strong> asociere particulara, <strong>si</strong> ea specifica o legatura <strong>de</strong> tip<br />

parte-<strong>în</strong>treg <strong>în</strong>tre obiecte. Aceasta relatie este utilizata atunci când un obiect contine,<br />

<strong>în</strong> mod logic sau fizic, un alt obiect. Agregarea se reprezinta grafic la fel ca <strong>si</strong><br />

asocierea, utilizând <strong>în</strong> plus un romb alb <strong>în</strong> capatul corespunzator clasei care specifica<br />

obiectele proprietar.<br />

Compunerea este o forma mai puternica <strong>de</strong> agregare <strong>si</strong> ea specifica faptul ca<br />

obiectele proprietar sunt responsabile cu crearea <strong>si</strong> distrugerea obiectelor pe care le<br />

contin. Compunerea se reprezinta grafic ca <strong>si</strong> o agregare, dar culoarea rombului este<br />

neagra.<br />

În UML relatia <strong>de</strong> generalizare specifica mostenirea <strong>în</strong>tre clase. Ea se<br />

reprezinta grafic prin intermediul unei linii <strong>în</strong>tre doua clase ce contine la capatul<br />

corespunzator clasei parinte un triunghi cu unul din vârfuri <strong>în</strong>dreptat spre aceasta.<br />

B.2. Harti <strong>de</strong> stari<br />

În UML hartile <strong>de</strong> stari sunt utilizate <strong>în</strong> <strong>de</strong>scrierea comportamentului<br />

obiectelor apartinând unui clase.<br />

O stare (concreta) este caracterizata <strong>de</strong> valorile proprietatilor unui obiect <strong>si</strong> <strong>de</strong><br />

multimea mesajelor care pot fi acceptate <strong>de</strong> catre acest obiect la un moment dat. O<br />

stare contine <strong>de</strong>scrierea unui invariant <strong>de</strong> stare (conditie logica a<strong>de</strong>varata pentru toate<br />

obiectele care se afla <strong>în</strong> starea respectiva), <strong>si</strong> a trei proceduri speciale: entry, exit <strong>si</strong> do.<br />

Aceste proceduri <strong>de</strong>scriu secventele <strong>de</strong> actiuni care vor fi executate <strong>în</strong> momentul <strong>în</strong><br />

care un obiect intra (entry), paraseste (exit) sau se afla (do) <strong>în</strong> starea respectiva. O<br />

stare se reprezinta grafic prin intermediul unui dreptunghi cu colturile rotunjite,<br />

afisând <strong>în</strong> partea superioara un nume <strong>de</strong> stare. În partea inferioara a dreptunghiului<br />

optional poate exista un compartiment care contine expre<strong>si</strong>ile ce <strong>de</strong>finesc invariantul<br />

<strong>de</strong> stare <strong>si</strong> cele trei proceduri speciale.<br />

O tranzitie exprima o <strong>si</strong>tuatie <strong>în</strong> care un obiect poate trece dintr-o stare <strong>în</strong> alta.<br />

Tranzitiile se reprezinta grafic prin intermediul unor arce <strong>de</strong> cerc, linii <strong>si</strong>mple sau linii<br />

168


poligonale orientate <strong>si</strong> (optional) etichetate care unesc doua stari, numite stare sursa,<br />

respectiv <strong>de</strong>stinatie. Eticheta unei tranzitii este formata dintr-o <strong>si</strong>gnatura <strong>de</strong> mesaj, o<br />

conditie (expre<strong>si</strong>e logica) <strong>si</strong> o secventa <strong>de</strong> activitati care au loc <strong>în</strong> momentul<br />

<strong>de</strong>clansarii tranzitie. Pentru un obiect oarecare o tranzitie este <strong>de</strong>clansata atunci când<br />

obiectul se afla <strong>în</strong> starea sursa a acesteia, executa operatia corespunzatoare mesajului<br />

<strong>si</strong> este <strong>în</strong><strong>de</strong>plinita conditia specificata <strong>în</strong> eticheta.<br />

Hartile <strong>de</strong> stari permit reprezentarea ierarhica a starilor unui obiect prin<br />

intermediul starilor compuse (<strong>în</strong>tâlnite <strong>si</strong> sub <strong>de</strong>numirea <strong>de</strong> XOR-stari, stari abstracte<br />

sau super-stari). Starile compuse contin un numar finit <strong>de</strong> stari <strong>si</strong>mple sau compuse.<br />

Un obiect aflat <strong>în</strong>tr-o stare compusa se va afla <strong>în</strong> una <strong>si</strong> numai una din sub-starile<br />

acesteia. Starile compuse se reprezinta grafic la fel ca starile <strong>si</strong>mple, la care se adauga<br />

un compartiment special, localizat <strong>în</strong>tre numele starii <strong>si</strong> compartimentul <strong>de</strong>stinat<br />

afisarii invariantilor <strong>de</strong> stare <strong>si</strong> a procedurilor speciale. În cadrul acestui<br />

compartiment sunt reprezentate grafic toate sub-starile corespunzatoare.<br />

stare compusa mesaj<br />

conditie <strong>de</strong><br />

<strong>de</strong>clansare<br />

169<br />

activitate<br />

pseudo-stare<br />

terminala<br />

Figura B.2. Etichetarea tranzitiilor <strong>în</strong> hartile <strong>de</strong> stari UML<br />

Hartile <strong>de</strong> stari permit mo<strong>de</strong>larea <strong>de</strong> comportamente paralele ale unui obiect<br />

prin intermediul starilor ortogonale (<strong>de</strong>numite <strong>si</strong> AND-stari sau stari concurente).<br />

Starile ortogonale sunt formate din mai multe componente ortogonale, fiecare dintre<br />

acestea continând diverse sub-stari. Un obiect aflat <strong>în</strong>tr-o stare ortogonala se va afla<br />

<strong>de</strong> fapt <strong>în</strong> câte o stare corespunzatoare fiecarei componente ortogonale a acesteia.<br />

Reprezentarea grafica a starilor ortogonale este asemanatoare reprezentarii starilor<br />

compuse, componentele ortogonale ale acestora fiind <strong>de</strong>limitate prin linii punctate<br />

verticale.


mesaj pseudo-stare<br />

tranzitie<br />

stare compusa initiala<br />

pseudo-stare<br />

istoric<br />

invariant <strong>de</strong><br />

stare<br />

170<br />

componente<br />

ortogonale<br />

stare ortogonala<br />

Figura B.3. Principalele notatii ale hartilor <strong>de</strong> stari UML<br />

De asemenea, hartile <strong>de</strong> stari introduc o serie <strong>de</strong> stari speciale, numite pseudo-<br />

stari. Pseudo-starile sunt stari intermediare care permit conectarea mai multor<br />

tranzitii <strong>în</strong> scopul <strong>de</strong>scrierii unor <strong>si</strong>tuatii complexe <strong>de</strong> modificare a starii concrete a<br />

unui obiect. Cele mai importante pseudo-stari <strong>de</strong>finite <strong>în</strong> UML sunt:<br />

- starea initiala - indica sub-starea implicita <strong>în</strong> care intra un obiect <strong>în</strong> cazul<br />

<strong>de</strong>clansarii unei tranzitii a carei stare <strong>de</strong>stinatie este o stare compusa. Se<br />

reprezinta grafic sub forma unui cerc plin.<br />

- starea finala - indica para<strong>si</strong>rea contextului unei stari compuse. În cazul <strong>în</strong><br />

care starea finala apartine starii compuse <strong>de</strong> la cel mai <strong>în</strong>alt nivel al<br />

ierarhiei <strong>de</strong> stari (este radacina ierarhiei <strong>de</strong> stari) intrarea o tranzitie spre<br />

aceasta stare semnifica distrugerea obiectului.<br />

- starea istoric - este utilizata atunci când sub-starea initiala a unei stari<br />

compuse nu este fixata <strong>de</strong>cât pentru prima tranzitie spre aceasta stare<br />

compusa, ea fiind data mai apoi <strong>de</strong> ultima sub-stare activa. În figura B.3 o<br />

prima tranzitie spre starea Pornita implica activarea sub-starii Normal,<br />

urmatoarele tranzitii activând sub-starea (Normal sau Marsalier) activa <strong>în</strong><br />

momentul ultimei para<strong>si</strong>ri a starii Pornita.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!