====== Další metody synchronizace ====== Na tomto cvičení byste si měli vyzkoušet další metody synchronizace vláken přes podmínkové proměnné (condition variables). ===== Domácí příprava ===== Nastudujte si použití podmínkový proměnných a k tomu příslušné funkce v knihovně pthread: * pthread_cond_init * pthread_cond_destroy * pthread_cond_signal * pthread_cond_broadcast * pthread_cond_wait ===== Zadání úlohy ===== Vytvořte program simulující výrobní závod, který vyrábí 3 druhy výrobků. Každý výrobek musí projít pevně danou sekvencí operací na různých pracovištích. Pracoviště obsluhují dělníci, přičemž každý dělník je schopen obsluhovat právě jeden druh pracoviště. Počet dělníků a jemu příslušejících pracovišť je různý a v čase proměnlivý – dělníci přicházejí a odcházejí, pracoviště mohou přibývat nebo být vyřazována. Požadavky na výrobu, příchod a odchod dělníků a nákup/vyřazení strojů se zadávají přes standardní vstup aplikace následujícími příkazy (jeden příkaz na řádce ukončené '\n'): make - požadavek na výrobu výrobku; je "A", "B", nebo "C" start - příchod dělníka s uvedením jeho specializace end - odchod dělníka add - přidáni nového pracoviště remove - odebraní pracoviště Neplatné příkazy či parametry ignorujte. Celý proces je řízen dělníky. Každý dělník bude reprezentován samostatným vláknem, které bude vytvořeno při příchodu dělníka a ukončeno při jeho odchodu. Dělník potřebuje ke své práci polotovar (meziprodukt) a volné pracoviště pro které je specializován. Pokud nebude mít jedno nebo druhé, čeká. Pro první pracoviště nahrazuje meziprodukt požadavek na výrobu. Pokud má dělník vše potřebné k dispozici, vypíše informaci o své aktivitě a poté počká čas, který je definován pro každý typ operace. Formát výpisu aktivity je tedy např. Karel vrtacka A 2 Pokud dělník dokončí poslední operaci v procesu, vypíše done kde je kód výrobku A, B, nebo C. Výrobní procesy pro výrobky A–C jsou následující: A: 1:nuzky - 2:vrtacka - 3:ohybacka - 4:svarecka - 5:vrtacka - 6:lakovna B: 1:vrtacka - 2:nuzky - 3:freza - 4:vrtacka - 5:lakovna - 6:sroubovak C: 1:freza - 2:vrtacka - 3:sroubovak - 4:vrtacka - 5:freza - 6:lakovna Časy operací v milisekundách na pracovištích jsou následující: * nuzky: 100 * vrtacka: 200 * ohybacka: 150 * svarecka: 300 * lakovna: 400 * sroubovak: 250 * freza: 500 Můžete předpokládat, že nepřijdou dva dělníci stejného jména. Pokud se odebírá pracoviště, odeberte přednostně neobsazené. Pokud není žádné pracoviště daného typu volné, vyřaďte libovolné, ovšem až po dokončení aktuální operace. Dělník odchází z pracoviště buď při ukončování celé aplikace (viz níže) nebo jako reakce na příkaz //end//. Dělník který má odejít nejdříve dokončí aktuálně rozdělanou práci. Pokud má dělník odejít, nesmí vzít novou práci. Při odchodu dělníka ukončete jeho vlákno. Pokud může dělník v danou chvíli pracovat na více různých místech, vybírá si místo s nejvyšším možným krokem tak, aby se prioritně zpracovávaly zakázky nejblíže dokončení. Je-li takových víc, vybírá mezi nimi výrobek blíže začátku abecedy, tedy např. výrobek A před B. Uzavření standardního vstupu je požadavkem na ukončení celé aplikace, přičemž vlastní ukončení aplikace nastane až poté, co žádný dělník nemůže pracovat. Před ukončením aplikace ukončete vlákna všech dělníků a dealokujte alokovanou paměť. Návratový kód aplikace bude 0. ==== Pokyny k implementaci ==== * Čekání všech vláken musí být efektivní, nesmí být vytěžován procesor. * Jsou-li dostupné zdroje, dělník musí započít práci okamžitě (bez prodlevy). * Standardní vstup čtěte pouze z hlavního vlákna. * Příkazy ze vstupu vykonávejte bez zbytečného odkladu, tj. hlavní vlákno neblokujte, pokud to není nezbytně nutné. * Standardní chybový výstup můžete použít pro libovolné ladící výpisy. * Binární soubor aplikace se bude jmenovat **factory** a bude vytvořen ve stejném adresáři kde se nachází Makefile. * Výpis aktivity musí být proveden tak, aby nemohlo dojít k prohození s výpisem jiné aktivity, která začala později. * Program kompilujte s příznaky ''-Wall -g -O2'' a dále s příznaky v proměnné ''EXTRA_CFLAGS''. Pokud tato proměnná není definována na příkazové řádce make, nastavte její hodnotu na "''-fsanitize=address -fno-omit-frame-pointer''" (viz např. operátor ''?=''). ==== Ukázkový vstup a odpovídající výstup ==== Vstup: add nuzky add vrtacka add ohybacka add svarecka add lakovna add sroubovak add freza start Nora nuzky start Vojta vrtacka start Otakar ohybacka start Sofie svarecka start Lucie lakovna start Stepan sroubovak start Filip freza make A Výstup: Nora nuzky A 1 Vojta vrtacka A 2 Otakar ohybacka A 3 Sofie svarecka A 4 Vojta vrtacka A 5 Lucie lakovna A 6 done A ===== Domácí příprava na další cvičení ===== TODO ...