objektumok viselkedése · két objektum közötti üzenet megvalósulhat úgy, hogy o a küldő...
TRANSCRIPT
-
Objektumok viselkedéseGregorics Tibor
http://people.inf.elte.hu/gt/oep
-
Viselkedési nézetek
❑ Az UML az objektumok dinamikus viselkedésének jellemzésére számos
nézetet vezetett be. Ezek közül az alábbiakkal ismerkedünk meg:
• Használati eset (use case) diagram
• Kommunikációs (communication) diagram
• Szekvencia (sequence) diagram
• Állapotgép (state machine) diagram
2Gregorics Tibor: Objektumelvű programozás
-
Használati eset diagram
3Gregorics Tibor: Objektumelvű programozás
❑ Megmutatja, hogy a tervezett rendszer
• milyen funkciókat lát el, milyen szolgáltatásokat biztosít,
• kik számára nyújtja a szolgáltatásokat
• milyen követelményeket vár el a környezetétől
-
Használati eset diagram elemei
4Gregorics Tibor: Objektumelvű programozás
❑ Használati esetek: a rendszernek egy külső megfigyelő szempontjából azonosítható fő funkciói, szolgáltatásai
❑ Aktorok: felhasználók vagy külső szereplők, akik a funkciókat használják
❑ Használati esetek rákövetkezési sorrendje. o precede: felhasználó által közvetlenül kezdeményezhető két tevékenység
között biztosítandó sorrendet jelöli
o invoke: egy felhasználói tevékenység és az azt követő, de közvetlenül nem előidézhető tevékenység közötti kapcsolatot jelöli
❑ Használati esetek közötti tartalmazási viszony.o include: egy felhasználó tevékenységnek egy jól elkülöníthető, önállóan is
kezdeményezhető része, amely nélkül azonban a tartalmazó tevékenység nem teljes (absztrakt).
o extend: egy felhasználói tevékenységet opcionálisán kiegészítő másik tevékenység, amely önmagában is teljes (soha nem absztrakt)
❑ Egyéb:o Használati esetek vagy az aktorok közötti származtatás.
o Multiplicitás is megadható az aktoroknál.
-
Felhasználói esetek (user story)❑ A használati eset diagram önmagában nem ad elégséges képet a
megvalósítandó rendszerről, hiszen az egyes tevékenységekről a nevükön kívül nem árul el semmit.
❑ A felhasználói esetek felhasználói csoportonként („AS a …”) történő táblázatos („user story”) leírásában minden felhasználói tevékenységet részletesen ki kell fejteni:
• mi a tevékenység neve,
• milyen előfeltétel meglétét feltételezi (GIVEN)
• milyen esemény hatására következik be (WHEN)
• mi a hatása a végrehajtásának, milyen eredményt ad (THEN).
5Gregorics Tibor: Objektumelvű programozás
eset leírás
tevékenység neve
GIVEN tevékenység kiváltásakor feltételezett alaphelyzet
WHEN tevékenység kiváltása
THEN tevékenység hatása
AS a …
-
Példa: Felsorolás
6Gregorics Tibor: Objektumelvű programozás
eset leírás
Előkészítés normális esetben
GIVEN a felsorolni kívánt gyűjtemény
WHEN felsoroló példányosítása
THEN létrejön a felsoroló objektum
Előkészítésabnormális esetben
GIVEN nincs felsorolni kívánt gyűjtemény
WHEN felsoroló példányosítása
THEN hiba, felsoroló objektum nem jön létre
Elindítás normális esetben
GIVEN felsoroló állapota pre-start
WHEN felsorolás elindítása a first() művelettel
THEN a felsoroló in-process állapotba kerül
Elindítás abnormális esetben
GIVEN felsoroló állapota in-process vagy finished
WHEN Felsorolás elindítása a first() művelettel.
THEN hiba, és a felsoroló megőrzi állapotát
…
Előkészítés
Aktuális elem lekérdezése
Továbblépés
aktor
Elindítás
Befejezettség lekérdezése
< precede >
< precede >
< precede >
< precede >
t.first()
t.end()
… t.current() …
t.next()
-
Kommunikációs diagram
7Gregorics Tibor: Objektumelvű programozás
❑ A kommunikációs diagram azt mutatja meg, hogy az egymással kapcsolatban levő objektumok milyen üzeneteket küldenek egymásnak.
-
Kommunikációs diagram elemei
8Gregorics Tibor: Objektumelvű programozás
❑ Objektumok, amelyek jelölésében nem tüntetjük fel az adattagjaikat.
❑ Két objektum közötti üzenet megvalósulhat úgy, hogy
o a küldő objektum meghívja a fogadó objektum egyik metódusát,
o a küldő objektum szignált küld a fogadónak.
❑ Az üzenetváltás lehet
o szinkron: a fogadó objektum az üzenet hatására végrehajtott tevékenységét a küldő objektum tevékenységével szinkron módon végzi,
o aszinkron: az üzenet elküldése után a küldő és a fogadó objektumok tevékenységei párhuzamosan hajtódnak végre.
❑ Egyéb
o Kijelölhető az üzenetek sorrendje (azok sorszámozásával).
o Megadható az üzenetek előfeltétele (szögletes zárójelpár között).
o Jelölhető, ha egy üzenet ciklikusan ismétlődik.
-
Példa: Felsorolás
9Gregorics Tibor: Objektumelvű programozás
: Collection
: Enumerator
1 : createEnumerator()
1.1 create()
2.1 : first()2.2 * : [!end()] current(), 2.3 * : [!end()] next()
: Collection
: Enumerator
createEnumerator()
create()
first(), next()current(), end()
Collection
…+ createEnumerator()
Enumerator
+ first()+next()+ current()+ end()
*
létrehozbejár
actor
actor
t.first()
t.end()
… t.current() …
t.next()
-
Szekvencia diagram
❑ A kommunikációban az üzenetváltások időbeli sorrendjét mutatja.
10Gregorics Tibor: Objektumelvű programozás
-
Szekvencia diagram elemei❑ Objektum életvonala (az objektumból lefelé induló függőleges
szaggatott vonal) : az üzenetváltásokban résztvevő objektum
élettartamának egy részét jelző idővonal. (Az objektum példányosítása
illetve megszüntetése nem feltétlenül része a diagramnak.)
❑ Tevékenység (hosszú elnyújtott téglalap az életvonalon): egy objektum
aktivitásának (pl. egy metódusa működésének) időbeli elnyúlását jelzi az
életvonalon.
❑ Üzenet (vízszintes nyíl életvonalak között) : egy objektum tevékenysége
küldi egy másik objektumnak.
❑ Üzenetek sorrendje: az üzenetek egymás alatti megjelenése időbeli
sorrendre utal, de az eltelt időt külön jelzés hiányában nem definiálja.
❑ Fragmentek (dobozba zárt részek): olyan részleteit jelölik ki a
diagramnak, mint amely például ciklikusan ismétlődhet (loop), vagy
alternatívaként következhet be (alt), vagy máshol van részletesebben
kifejtve (ref).
11Gregorics Tibor: Objektumelvű programozás
-
Üzenetek fajtái❑ Szinkron üzenet
amikor a küldő objektum átadja a vezérlést a fogadó objektumnak, és a saját tevékenységét blokkolja mindaddig, amíg a fogadó objektum ezt nem oldja fel.
• fogadó objektum egy metódusának hívása.• egy időhöz kötött várakozó üzenet, amely során a küldő objektum megjelölt
ideig várakozik arra, hogy a fogadó objektum fogadja az üzenetet.
❑ Aszinkron üzenet a párhuzamosan működő objektumok között fordul elő, amikor a küldő objektum nem szakítja meg a tevékenységét az üzenet elküldése után. Gyakran egy jel (szignál) elküldése (paraméter-értékekkel kiegészítve).
❑ Speciális üzenetek:• visszatérési üzenet: korábban üzenetet kapó objektum küldi vissza a küldő
objektumnak (visszaadja a vezérlést vagy hibát jelez).• példányosító (create) üzenet: létrehoz egy objektumot• randevú üzenet: a fogadó objektum várakozik a küldő objektum üzenetére.
12Gregorics Tibor: Objektumelvű programozás
régebben:
-
Példa: Felsorolás
13Gregorics Tibor: Objektumelvű programozás
: Collection
: Enumerator
createEnumerator()
first()
end()
current()
next()
loop
t.first()
t.end()
… t.current() …
t.next()
-
Objektum életciklusa
14Gregorics Tibor: Objektumelvű programozás
❑ Az objektum életciklusa során:
• létrejön: az objektum speciális műveletével, a konstruktorral,
• működik: más objektumokkal kommunikál, azaz szinkron vagy aszinkron módon üzeneteket küldenek egymásnak, és ennek során megváltozhatnak az adatai,
• megsemmisül (egy másik speciális művelettel, a destruktorral).
❑ Egy objektumnak különféle állapotai (state) vannak: egy állapot (fizikai állapot) az objektum adatai által felvett értékek együttese, amely az életciklus során változik.
❑ A könnyebb áttekinthetőség kedvéért azonban gyakran egy állapotnak az objektum több különböző, de közös tulajdonságú fizikai állapotainak összességét tekintjük (logikai állapot).
-
Állapotgép
15Gregorics Tibor: Objektumelvű programozás
❑ Az állapotgép diagram egy objektum életciklusát ábrázolja. Megmutatja, hogyan változnak egy objektum állapotai az objektumnak küldött üzenetek (metódus hívások vagy szignálok) hatására.
❑ Az állapotgép egy működést ír le, amelyben mindig egy állapot lehet csak aktív.
❑ Az állapotgép egy irányított gráf, amelynek csomópontjai az objektum logikai állapotait, irányított élei pedig az állapotok közötti átmeneteket mutatják.
❑ Mind az állapotokhoz, mind az átmenetekhez tartozhatnak végrehajtandó tevékenységek.
-
• elágazás (choice)
• csomópont (junction)
• szétágazás (fork)
• összefutás (join)
Állapotok
• kezdő állapot
• végállapot
Hierarchikus állapotgépekben:
• belépés (entry)
• kilépés (exit)
• megszüntetés
• shallow history
• deep history
16
[feltétel][feltétel]
H
H*
Gregorics Tibor: Objektumelvű programozás
❑ Az állapotokat lekerekített sarkú téglalap jelöli:
anonim is lehet
Pszeudo állapotok:
-
Állapot belső tevékenységei
17Gregorics Tibor: Objektumelvű programozás
enter / do / exit /
/
anonim is lehet Belépési tevékenység: akkor hajtódikvégre (és mindig be is fejeződik), amikor egy átmenet révén az állapot aktív lesz.
Belső tevékenység: lehet folyamatos (végtelenített), amíg az állapot aktív,vagy befejeződő
Belső átmenet: egy olyan reflexív átmenet, amikor az állapotnak sem a be-, sem a kilépési tevékenysége nem hajtódik végre, csak az itt megadott tevékenység.
Kilépési tevékenység: akkor hajtódik végre(és mindig be is fejeződik), amikor egyátmenet révén másik állapot válik aktívvá.
-
Állapot-átmenetek jelölése
❑ Az állapot-átmenetet az alábbi elemek (bármelyik hiányozhat) jellemzik:
o átmenetet előidéző esemény (event, trigger) a paramétereivel
• lehet az adott objektum egy metódusának a hívása
• vagy az objektumnak küldött szignál
o átmenetet megengedő őrfeltétel (guard), amely
• vagy az esemény paramétereitől függő logikai állítás (when)
• vagy egy időhöz kötött várakozási feltétel (after)
o átmenethez rendelt tevékenység (az objektum adattagjaival és a kiváltó esemény paramétereivel operáló program)
❑ Egy átmenet lehet reflexív.
18Gregorics Tibor: Objektumelvű programozás
()[]
/
-
Állapot-átmenetek szemantikája I.
19Gregorics Tibor: Objektumelvű programozás
Amikor az átmenet egy esemény hatására jön létre:
állapot []
• Őrfeltétel hiányában, amikor az esemény bekövetkezik, akkor az állapot belső tevékenysége megszakad, és az átmenet megvalósul. Ugyanazon állapotból nem vezethet ki két él ugyanazon eseménnyel.
• Őrfeltétel mellett az átmenet (a belső tevékenység megszakításával) csak akkor valósul meg, ha az esemény bekövetkezésekor az őrfeltétel igaz. Egyébként az esemény hatástalan. (nincs várakozás) Egy esemény ugyanazon állapotból kivezető több élhez is tartozhat, feltéve, hogy diszjunkt őrfeltételekkel van rendelkezik.
állapot
-
Állapot-átmenetek szemantikája II.
20Gregorics Tibor: Objektumelvű programozás
állapot
állapot[]
Amikor az átmenetet nem esemény váltja ki:
• Őrfeltétel hiányában az átmenet az állapot belső tevékenységének befejeződésekor valósul meg. Ha nincs belső tevékenység, akkor azonnal.
• Őrfeltétel esetén az átmenet bekövetkezése (az esetleges belső tevékenység befejeződése után) addig várakozik, amíg az őrfeltétel igaz nem lesz, feltéve, hogy várakozás közben más állapot-átmenetre nem kerül sor.
-
Hierarchikus állapotok
21Gregorics Tibor: Objektumelvű programozás
Szekvenciális:
Párhuzamos:
ortogonális régiók
-
Példa: Felsorolás
22Gregorics Tibor: Objektumelvű programozás
end() / error, current() / error, next() / error
first() [gyűjtemény nem üres]
end(),current(), next() [gyűjtemény nem üres]
next() [gyűjtemény üres]end()first() [gyűjtemény üres]
first() / error
first() / error, current() / error, next() / error
first()
end()
… current() …
next()
create()
finished
destroy()
pre-start in-processdestroy()
destroy()
-
Gregorics Tibor: Objektumelvű programozás 23
Feladat
❑ Egy benzinkútnál több töltőhely és egy több kasszából álló pénztár működik.
• Az autósok behajtanak a benzinkúthoz, beállnak valamelyik töltőhelyhez tankolni.
• Amikor sorra kerülnek, akkor kívánt mennyiségű benzint töltenek a járművük benzintartályába.
• Ezután elmennek fizetni, és beállnak a pénztárhoz álló sorba.
• Amint egy kassza szabad lesz, a sorban elől álló autós odalép, ahol kiszámolják a tankolt mennyiség alapján fizetendő összeget.
• Fizetés után az autós kihajt a töltőhelyről, és távozik.
❑ Modellezzük ezt a folyamatot tetszőleges számú, egymással párhozamosan tevékenykedő autós esetére.
-
Használati eset diagram
behajt
benzint tölt
távozik
24Gregorics Tibor: Objektumelvű programozás
autós
töltőhelyet választ, ahol beáll a sorba, és vár, amíg sorra
nem kerül
>
pénztárhoz megy
>
beáll a sorba, és vár, amíg
sorra nem kerül
fizet
>
>
>
elhagyja a töltőhelyet
>
>
számláz>
pénztár
-
Felhasználói esetek
25Gregorics Tibor: Objektumelvű programozás
eset leírás
behajt GIVEN létezik a benzinkút töltőhelyekkel
WHEN behajt egy létező töltőhelyhez
THEN besorol a töltőhely melletti sorba
tölt GIVEN az egyik töltőhelyen elsőként áll
WHEN megadott liter benzin töltése
THEN a kijelző mutatja a felvett benzint
pénztárhoz megy
GIVEN létezik a benzinkút pénztárral
WHEN bemegy a pénztárba
THEN beáll a pénztár sorába
fizetés GIVEN létezik a benzinkút pénztárral, egy töltőhelyen áll, a pénztárban sorban áll
WHEN sorra kerül (első a sorban és valamelyik kassza üres)
THEN kiáll a sorból, kiszámolják a fizetendő összeget, lenullázzák a töltőhely kijelzőjét
elhagy GIVEN a benzinkút egyik töltőhelyén áll
WHEN távozik
THEN kiáll a töltőhely sorából
eset leírás
tölt GIVEN az egyik töltőhelyen elsőként áll
WHEN nulla liter benzin töltése
THEN figyelmeztetés
elhagy GIVEN töltőhelyen áll, a kijelző nem nulla
WHEN távozik
THEN riasztás
-
Felhasználói (hibás) esetek
26Gregorics Tibor: Objektumelvű programozás
eset leírás
behajt GIVEN nem létezik a benzinkút vagy nem létezik a kiválasztott töltőhely
WHEN behajt
THEN hibajelzés
tölt GIVEN nem áll töltőhelyen
WHEN benzint tölt
THEN hibajelzés
pénztárhoz megy
GIVEN létezik a benzinkút, de nem létezik pénztár
WHEN bemegy a pénztárba
THEN hibajelzés
fizet GIVEN nem áll töltőhelynél
WHEN fizet
THEN hibajelzés
elhagy GIVEN nem áll töltőhelynél
WHEN távozik
THEN hibajelzés
-
Elemzés
❑ Objektumok és tevékenységeik:
• autósok (tankolnak)
• benzinkút (ahová az autósok behajtanak, ahol tankolnak, pénztárhoz mennek, fizetnek, majd elhagyják a töltőhelyet)
• töltőhelyek (amely mellé beáll az autós, ahol várakozik, majd benzint tölt, végül fizetés után kiáll)
• pénztár több kasszával (ahol az autós sorba áll, ahol várakozik, majd fizet)
❑ Objektumok közötti kapcsolatok:
• a benzinkút részei a töltőhelyek és a pénztár
• egy autós ideiglenesen kapcsolatba kerül egy töltőhellyel és a pénztárral.
27Gregorics Tibor: Objektumelvű programozás
-
Objektum diagram
:Benzinkút
:Töltőhely :Pénztár
28Gregorics Tibor: Objektumelvű programozás
:Autós
:Töltőhely:Töltőhely
:Autós:Autós
:Autós:Autós
-
Kommunikációs diagram
:Töltőhely
:Pénztár
29Gregorics Tibor: Objektumelvű programozás
autós
1. sorbaáll()2. tölt()5. elhagy()
3. sorbaáll()4. fizet()
4.1. getKijelző()4.2. lenulláz()
-
Szekvencia diagram
30Gregorics Tibor: Objektumelvű programozás
: Pénztártöltő[i] : Töltőhely: Autós
tölt()
sorbaáll()
elhagy()
fizet()
sorbaáll()
lenulláz()
getKijelző()
-
31Gregorics Tibor: Objektumelvű programozás
Osztály diagram
Autós
+ tankol(b : Benzinkút, n : int, l : int)
Pénztár
+ fizet(Autós) : int
6
tölt
{ordered}
2
tankol
Töltő- kijelző
+ tölt(liter : int)+ lenulláz()+ getKijelző() : int
fizet*
0..1 0..1sorbanáll
*
{subset}
sorbanáll
{subset}
*{ordered} {ordered}
Kassza
Benzinkút- egységár
0..1
- telephely
- pénztár
- töltők
- sor - sor
+ sorbaáll(Autós)
+ sorbaáll(Autós)
+ elhagy(Autós)
-
❑ A rendszer állapotát az autósok és a benzinkút állapota határozza meg.
A benzinkút állapota a töltőhelyek és a pénztár állapotától függ.
❑ Az autósok ún. aktív objektumok: önerőből végeznek tevékenységet, így
állapotgépeik külön szálakon futnak majd.
❑ A benzinkút passzív objektum: állapotgépe más objektumok által
küldött üzenetek hatására működik. Nem igényel külön szálat.
rendszer stateMachine
autóskstateMachine
… …
Rendszer állapotgépe
32Gregorics Tibor: Objektumelvű programozás 32
benzinkút stateMachine
töltőhelyistateMachine
pénztárstateMachine…
…
-
Autósok állapotgépe
33Gregorics Tibor: Objektumelvű programozás 33
autósk stateMachine
do / mást csinál
do / tölt()
enter / p.sorbaáll()do / várakozik
do / p.fizet()
enter / t.sorbaáll()do / várakozik
❑ Egy autós ötféle állapotban lehet, amelyek akár ciklikusan is
változhatnak:
• mást csinál, behajt a benzinkút egy töltőhelyére és sorba áll,
üzemanyagot vesz fel, pénztárban sorba áll, fizet, és elhajt
❑ Az autósok ún. aktív objektumok (tevékenységüket önmaguk
szabályozzák), és egymással párhuzamosan működnek.
/ t := behajt() [első a töltőhelynélálló sorban]
/ p:=pénztárbaMegy()
/ t.elhagy()
[első a pénztárnálálló sorban és
van üres kassza]
nem kerül megvalósításra
-
34Gregorics Tibor: Objektumelvű programozás
Autós osztály
Autós- név : string+ Autós(str : string)+ tankol(b : Benzinkút, n : int, liter : int) : void- behajt(b : Benzinkút, n : int) : Töltő- pénztárbamegy(b : Benzinkút) : Pénztár
t := behajt(b, n)t.tölt(liter)p := pénztárbaMegy(b)p.fizet(this)t.elhagy(this)
t := b.getTöltő(n) t.sorbaáll(this)return t
p := b.getPénztár()p.sorbaáll(this)return p
-
35Gregorics Tibor: Objektumelvű programozás
class Car {public:
Car(const std::string &str) : _name(str) {}…void refuel(PetrolStation* petrol, unsigned int n, int liter) {
_fuel = new std::thread(activity, this, petrol, n, liter); }~Car() { _fuel.join(); }
private:std::string _name;std::thread _fuel;void activity(PetrolStation* petrol, unsigned int n, int liter);Pump* driveIn(PetrolStation* petrol, unsigned int n);Cash* goToCash(PetrolStation* petrol);
};
Autós osztály
car.h
megvárja, míg a különindított szál befejeződik
külön szálon indul el#include
-
36Gregorics Tibor: Objektumelvű programozás
Autós osztályPump* Car::driveIn(PetrolStation* petrol, unsigned int n){
if ( npumpsPieces() ) petrol->getPump(n)->joinQueue(this); return petrol->getPump(n);
}
Cash* Car::goToCash(PetrolStation* petrol){
if (petrol->getCash()!= nullptr) petrol->getCash()->joinQueue(this);return petrol->getCash();
}
void Car::activity(PetrolStation* petrol, unsigned int n, int liter){
if ( nullptr==petrol ) return;Pump *pump = driveIn(petrol, n); // beáll az n-dik töltőhözif( nullptr==pump ) return;pump->fill(this, liter); // tankol liter benzintCash *cash = petrol ->goToCash(petrol); // pénztárhoz megyif ( nullptr==cash ) return;int a = cash->pay(this); // fizetpump ->leave(this); // távozik a benzinkúttól
} car.cpp
-
37Gregorics Tibor: Objektumelvű programozás
Benzinkút- töltők : Töltőhely[*]- pénztár : Pénztár- egységár : int+ Benzinkút(n : int, m : int)
+ getTöltő(n : int) : Pump+ getPénztár() : Pénztár+ getEgységÁr() : int
+ setEgységÁr(e:int) : void
Benzinkút osztálya
-
38Gregorics Tibor: Objektumelvű programozás
class PetrolStation {public:
PetrolStation(int n, int m) {for(int i = 0; i
-
Töltőhely állapotgépe
töltőhelyi stateMachine
szabad[ sor üres ]
foglalt[ sor nem üres ]
sorbaáll(a) / sor.push(a) elhagy(a) [a = sor.front() sor egy elemű ]/ sor.pop()
elhagy(a) [ a = sor.front() sor több elemű ] / sor.pop();
sorbaáll(a) / sor.push(a)
❑ Egy töltőhely lehet szabad vagy foglalt.
❑ A sorba() és elhagy() a töltőhelynél álló sorra van hatással.
❑ A tölt() csak akkor hajtható végre, amikor az autós az első a sorban
(ilyenkor tehát a töltőhely foglalt). Ekkor az autós megadott mennyiségű
benzint tölt az autójába, amely a töltőhely kijelzőjén is megjelenik.
Gregorics Tibor: Objektumelvű programozás 39
/ kijelző:=0; sor.clear()
tölt(a, liter) [ a = sor.front() ] / kijelző := liter
várakozik, amígnem ő lesz a soros
-
40Gregorics Tibor: Objektumelvű programozás
Töltőhely osztálya
Töltőhely- kijelző : int- sor : Queue+ Töltőhely()+ sorbaáll(a : Autós) : void+ tölt(liter : int)+ lenulláz()+ elhagy(a : Autós)
+ getAutós() : Autós + getKijelző() : int
< sor.push(a)wait sor.front() = a >
if sor.front() = a then sor.pop() endif
kijelző := 0
if sor.front() = a then mennyiség := liter endif
várakozik, amígnem ő lesz a soros
atomi módon végrehajtandó
-
41Gregorics Tibor: Objektumelvű programozás
class Car;
class Pump {public:
Pump() : _quantity(0) { }
void joinQueue(Car * car);void fill(Car * car, int l);void leave(Car * car);
Car* getCar() const { return _queue.front(); }int getQuantity() const { return _quantity; }void resetQuantity() { _quantity = 0; }
private:int _quantity;std::queue _queue;
std::mutex _mu;std::condition_variable _cond;
};
Töltőhely osztálya
pump.h
A különböző szálakon fut az autósok tevékenysége, amelyet szinkronizálni kell#include #include
-
42Gregorics Tibor: Objektumelvű programozás
Töltőhely metódusai
void Pump::joinQueue(Car* car){
std::unique_lock lock(_mu);_queue.push(car);while ( _queue.front() != car ) _cond.wait(lock);
}
void Pump::fill(Car * car, int l){
std::unique_lock lock(_mu);if ( _queue.front() != car ) return;_quantity = l;
}
void Pump::leave(Car * car){
std::unique_lock lock(_mu);if( car ==_queue.front() ) _queue.pop();_cond.notify_all();
} pump.cpp
várakozik a szál
elindítja az összes cond-nálvárakozó szálat
egyszerre csak egy autósdolgozhasson a _queue-n
egyszerre csak egy autósdolgozhasson a _queue-n
egyszerre csak egy autósdolgozhasson a _queue-n
-
Pénztár állapotgépe
pénztár stateMachine
❑ A pénztárban az autósok sorban állnak.
❑ Az állapotokra a bemegy() és a fizet() metódusok vannak hatással. Csak
a sor elején álló autós fizethet akkor, ha van szabad kassza.
Gregorics Tibor: Objektumelvű programozás 43
/ foglalt := 0, sor.clear() szabad[sor üres]
foglalt[sor nem üres]
sorbaáll(a) / sor.push(a)
fizet(a) [a = sor.first() and foglalt
-
44Gregorics Tibor: Objektumelvű programozás
Pénztár
Pénztár- sor : Queue- foglalt : int- kapacitás : int - telephely : Benzinkút+ Pénztár(Benzinkút, int) + sorbaáll(a : Autós) : void- számláz(liter : int, ár : int) : int {query}- keres() : bool×int {query}+ fizet(a : Autós) : int
❑ A pénztár tulajdonságai közé tartozik a kasszák száma (kapacitás), a
fogalt kasszák száma (foglalt), és a pénztárban álló sor.
< sor.push(a)wait sor.front() = a and foglalt
< foglalt := foglalt+1; sor.pop() >l, n := keres(); if not l then return 0 endifösszeg := számláz(telephely.getTöltő(n).getKijelző(), telephely.getEgységár())telephely.getTöltő(n).lenulláz()foglalt := foglalt‒1return összeg
várakozik, amígnem ő lesz a soros
return liter * ár
return SEARCH ( telephely.töltő(i) = a )i=1..telephely.getTöltőkSzáma()
-
45Gregorics Tibor: Objektumelvű programozás
class PetrolStation;class Car;
class Cash {public:
Cash(PetrolStation * ps, int m): _ station(ps), _capacity(m) {}void joinQueue(Car *car);int pay(Car *car);
private:PetrolStation *_station;int _capacity;std::atomic_int _engaged;std::queue _queue;
int invoice(int liter, int price) const;bool search(Car *car, unsigned int &n) const;
std::mutex _mu;std::condition_variable _cond;
};
Pénztár osztálya
cash.h
-
46Gregorics Tibor: Objektumelvű programozás
Pénztár segéd metódusai
void Cash::joinQueue(Car* car){
std::unique_lock lock(_mu);_queue.push(car); // beáll a sorbawhile ( _queue.front()!=car || _engaged==_capacity ) _cond.wait(lock);
}
bool Cash::search(Car *car, unsigned int &n) const{
for(n = 0; npumpsPieces(); ++n) {if ( _station->getPump(n)->getCar() == car ) return true;
}return false;
}
int Cash::invoice(int liter, int price) const { return liter*price; }
várakozik a szál
cash.cpp
-
47Gregorics Tibor: Objektumelvű programozás
Pénztár fizet() metódusa
int Cash::pay(Car* car){
std::unique_lock lock(_mu);if ( _queue.front()!=car || _engaged==_capacity ) return 0;
++_engaged; // odaér egy kasszához_queue.pop(); // kilép a sorból_mu.unlock();
unsigned int n;if (!search(car, n)) return 0;
int sum = invoice(_station->getPump(n)->getQuantity(), _station->getUnit());
_station->getPump(n)->resetQuantity(); // lenullázza az n-dik töltõ kijelzõjét
--_engaged; // elhagyja a kasszát_cond.notify_all();
return sum;} cash.cpp
elindítja a cond-nálvárakozó szálakat (autósokat)