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 ...
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.