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

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

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!