objektumok viselkedése · két objektum közötti üzenet megvalósulhat úgy, hogy o a küldő...

47
Objektumok viselkedése Gregorics Tibor [email protected] http://people.inf.elte.hu/gt/oep

Upload: others

Post on 24-Oct-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

  • Objektumok viselkedéseGregorics Tibor

    [email protected]

    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)