# Časování aplikací reálného času

## O časování a reálném čase

Myšlenka, že stroj může ovlivňovat sám sebe, je velmi stará. Přesto však její uskutečnění připadá až do novověku. Parní motory byly v Anglii známy několik desetiletí, a přesto stále nebyly použitelné. Konstruktéři neuměli vyřešit problém prudkého zvýšení otáček stroje při jeho náhlém odlehčení. Stroj většinou vysoké otáčky mechanicky nevydržel. Teprve až geniální objev odstředivého regulátoru přívodu páry umožnil otáčky udržet ve správných mezích, a tehdy mohl být parní stroj masově nasazen. Sám odstředivý regulátor byl pravděpodobně vůbec první lidstvem použitý automatizační prostředek.

Odstředivý regulátor je mechanický analogový regulátor a pracuje dokonale spojitě — na změny otáček reaguje kdykoli a okamžitě. Stroje a technologie dnešní doby jsou o několik řádů složitější než parní stroj, a jejich řízení s jedním mechanickým regulátorem nevystačí. Přesné, rychlé, spolehlivé a kontrolovatelné řízení je uskutečnitelné pouze s pomocí jiného programovatelného stroje — číslicového počítače.

Číslicový počítač pracuje diskrétně — postupně po jedné vykonává sled elementárních akcí. Pracuje velmi rychle, a proto obrovské množství jednoduchých akcí může dohromady realizovat (pochopitelně o něco pomaleji) i velmi složitou činnost. Současné počítače však nemají inteligenci a dokáží uskutečňovat jen to, co jim člověk programem přikáže. Pokud mají provádět nějakou činnost delší (nebo neomezenou) dobu, musí nutně určitou část programu vykonávat opakovaně, ve smyčce.

Automatizační úlohy, ať to je samostatný sběr dat, vizualizace, regulace nebo složitější řízení, jsou právě takovou skupinou úloh, která musí pracovat bez výpadků dlouhou dobu, a počítač proto vykonává program (celý nebo jeho různé části) mnohonásobně opakovaně. Povaha úlohy přitom přikazuje, jak často se jednotlivé části programu mají opakovat. S rychlostí opakování nejspíše nebudou problémy při regulaci výšky hladiny rybníka, naopak měření vibrací hřídele turbíny si nejspíš nějaký svižnější přístup vynutí. Programy, které by tyto dvě úlohy řešily, budou vcelku podobné — oba budou muset umět měřit (jednou výšku hladiny, podruhé vibrace), oba budou muset umět získaná data analyzovat a oba budou také muset poskytnou nějaký výsledek. Zásadní rozdíl nebude v principu práce programů, ale v jejich časování, ve způsobu jak rychle programy poběží a jak rychle se budou muset opakovat.

Všimněte si, že povaha technologií a fyzikálních jevů vcelku přirozeně (i když pouze rámcově) předurčuje rychlosti, které je třeba při jejich řízení nebo vizualizaci použít. Řídicí nebo vizualizační akce, které program zajišťuje, tak mají předem přibližně dáno, jak často musí být spouštěny.

Všechny automatizační úlohy souvisejí s časem, jednak musejí pracovat periodicky a jednak musejí své výsledky vztahovat k okamžikům, kdy mají smysl a platnost. Skutečný čas plyne nezávisle a spojitě (kvantové aspekty pomineme), naopak čas automatizační úlohy plyne po skocích. Sladění těchto dvou časů a orientace mezi nimi je proto součástí každého automatizačního programu.

Některé úlohy navíc musí splňovat určitá další kritéria, například regulační smyčka běží každou sekundu, a program navíc musí zajistit, že jeden běh smyčky nebude delší než 50 milisekund. Možný největší počet opakování smyčky programu je s délkou jednoho běhu úzce svázán, není možné požadovat, aby smyčka běžela desetkrát za sekundu a přitom sama trvala 5 sekund. Zdroj času, který má program provozující automatizační úlohu k dispozici, musí být natolik přesný, aby úloha mohla nejen bezpečně zajistit své opakování (s patřičnou rychlostí), ale navíc také veškeré další časové požadavky na ni kladené. Obyčejně se za bezpečný považuje zdroj času, který má nejméně 10× až 20× větší rozlišení než je nejkratší časový interval, s nímž úloha operuje (například, má-li úloha pracovat s periodou 100 milisekund, měla by mít k dispozici zdroj času s rozlišením ne horším, než 5–10 milisekund).

Program provozující nějakou úlohu musí mít k dispozici prostředky, kterými dokáže požadavky řešení uspokojit. Pokud se to nedaří (z nejrůznějších důvodů) musí mít program jednak možnost zjistit, že a proč se něco nedaří, a jednak musí mít možnost chybný stav řízeně opravit (opět nejrůznějším způsobem — je možné úlohu zastavit, restartovat nebo pokusit se "zvýšeným úsilím" situaci napravit).

Programové systémy, které mají schopnost orientace v čase, znají svůj momentální stav, vědí, jakou mají rezervu a jsou schopny přesně zjistit (a případně odstranit) příčinu svých časových potíží jsou systémy reálného času. Důležité je, že systém reálného času má vždy informace o svém běhu, ale nemusí být vždy schopen všechny požadavky na něj kladené splnit absolutně. Důraz je tedy kladen na informace, podle kterých se aplikace sama může rozhodovat o svém vlastním běhu. Žádný systém reálného času nikdy nedokáže například:

- zaručit libovolnou přesnost a rychlost opakování programu
- zaručit libovolnou přesnost délky trvání jednoho průchodu programu
- stoprocentně zaručit, že všechny komunikace budou trvat nejdéle určitou dobu

Systémy reálného času jsou velmi flexibilní a mocné, ale jsou schopné uspokojit pouze požadavky, které jsou rozumné, neboli požadavky reálně vztažené k použitému hardware, technologii, možnostem operačního systému, možnostem přenosu dat a fyzikálním zákonům. Systém reálného času vždy dokáže "pouze":

- zaručit přesnost s určitou tolerancí
- zjistit přesný momentální stav úlohy
- zajistit případnou změnu svého chování tak, aby byly dodrženy v mezích tolerancí požadované podmínky.

## O časování a systému Control Web

Systém Control Web je systém reálného času. Jeho aplikace se může dobrovolně těchto vlastností vzdát — může pracovat jako řízená daty. To přináší zjednodušení návrhu a menší nutnost detailně celou úlohu promýšlet. Stojí však za úvahu, jestli zjednodušení tvorby aplikace vyváží nemožnost aktivně a přesně ovlivňovat její chod.

V předchozím oddíle se velmi často skloňovaly pojmy "program", "smyčka" případně "jeden průchod programu". Aplikace v systému Control Web žádný zjevný "program" nebo "smyčku" neobsahuje, a přesto všechny popsané principy a pravidla realizuje a splňuje — jako celek, sestavený z jednotlivých samostatných spolupracujících objektů. To je velká výhoda systému Control Web, neboť automatizační úlohu je možné rozložit na jednoduché (logické) části, které pracují "vedle sebe", nezávisle. Samozřejmě, všechny takové části spolu mohou velmi dobře komunikovat, vždyť jsou součástí jedné aplikace, nicméně míra a způsob této komunikace zůstavají plně v moci aplikačního programátora.

Pokud bychom se přeci jen snažili v aplikaci nalézt pojem "smyčka" nebo "program", nalezeneme je na dvou možných úrovních:

- Každý přístroj je svým způsobem "programem", neboť může provádět jakékoli akce (jednak sám a jednak pomocí procedur), a současně "smyčkou", neboť je periodicky systémem oživován.
- Jádro systému Control Web v principu také představuje "program", který je "smyčkou". Zde se však spíše jedná již o logický program a logickou smyčku, protože hlavním smyslem existence jádra je oživování aplikačních objektů, které teprve aplikační úlohu řeší.

Je možné říci, že jedna aplikace v systému Control Web pracuje jako řada zcela nezávislých automatizačních miniúloh, přičemž elementární jednotkou pro běh miniúlohy je přístroj. Tyto principy — jednak oddělení řídicích operací a jednak plná distribuovatelnost běhu úlohy (možné rozložení problému na mnoho přístrojů) — v souhrnu umožňují velmi jednoduchý a zároveň extrémně mocný návrh aplikací. Control Web přitom zůstává stát v pozadí s jediným úkolem — vykonávat požadavky jednotlivých aplikačních objektů.

### Princip časování

Hlavním problémem časování je zajištění dostatečné přesnosti běhu aplikace v jakémkoli stavu zaneprázdněnosti operačního systému. Control Web dosahuje požadované přesnosti jednoduchým (avšak promyšleným) způsobem. Běžící aplikace je vnitřně rozdělena na část časově kritickou, která zaručuje přesnost časování, a část výkonnou, která pohnání přstroje a komunikuje. Opět se zde objevuje charakteristický rys systémů reálného času — především je nutné mít dobré informace o časových poměrech v aplikaci (to právě zajišťuje časově kritická část aplikace).

#### Časovací tok

Control Web vyhrazuje pro kritickou část aplikace samostatný prováděcí tok (o procesech a tocích se dočtete více v kapitole Co jsou to procesy a prováděcí toky), který pracuje s vyšší prioritou, než mají všechny ostatní normální toky všech aplikací systému. Operační systém zaručuje, že z toků, které jsou v daném okamžiku schopny běžet (tedy nečekají a nespí), poběží vždy tok s nejvyšší prioritou (pokud je toků se stejně vysokou prioritou více, bude je operační systém střídat). Prováděcí tok s kritickou částí aplikace (jiný jeho používaný název je časovací prováděcí tok, případně česko-anglicky časovací thread) proto díky své vyšší prioritě poběží právě tehdy, kdy se sám rozhodne.

Časovací tok:

- zajišťuje periodické časování přístrojů a shromažďuje i rozděluje všechny asynchronní zprávy od přístrojů, ovladačů a procedur (a v aplikaci řízené změnami dat i zprávy od dat)
- synchronizuje běh aplikace se zbytkem operačního systému
- přesně odměřuje čas komunikačních prodlev
- neustále sleduje délku běhu jednotlivých přístrojů a ovladačů
- v případné časové tísni zajišťuje popohnání aplikace vpřed

Časovací tok pracuje velmi efektivně díky svému optimalizovanému návrhu a díky přesné definici svých činností. Realizuje skutečně jen to nejnutnější, co je třeba pro dokonalou časovou orientaci aplikace. Má to však jeden háček. I sebelepší návrh nepřemůže operační systém.

Operační systémy Windows95/98, WindowsNT4.0, Windows2000 a WindowsCE2.1 používají model prováděcích toků pracující s elementárním časový kvantem dlouhým 15 milisekund, přičemž k délce tohoto kvanta jsou vztaženy i operace čekání a "spánku". Pokud v těchto operačních systémech přikážete prováděcímu toku "spi 3 milisekundy", je tok při první vhodné příležitosti (maximálně po 18 milisekundách) po "probuzení" zařazen do fronty toků, které jsou připraveny běžet, a teprve jakmile se na něj dostane řada, je rozběhnut. Skutečný interval, po kterém bude probuzený tok rozběhnut, je závislý především na celkovém počtu toků běžících se stejnou prioritou. Bude-li tok v systému sám (velmi nepravděpodobná varianta), bude nejspíše skutečně "spát" 3 milisekundy. Čím více však v systému poběží toků, tím více se 3 milisekundy mohou natáhnout.

Většina programových balíků a aplikací operačního systému je naštěstí napsána ohleduplně (stejně jako Control Web), a jejich prováděcí toky pracují jen v okamžicích, kdy se něco stane a kdy je třeba skutečně reagovat. Typický příklad je textový editor — jeho tok zpracovávající vstup z klávesnice bude po většinu času dobrovolně spát, a nechá se vzbudit operačním systémem jen v okamžiku stisku klávesy. Výsledkem této dobrovolné ohleduplnosti je stav, kdy většina toků na něco čeká, a i když jich celkem v systému bývá běžně kolem stovky, skutečně aktivních — běžících jich je jen málo. Operačnímu systému se proto daří ve většině případů programátorem požadované prodlevy dodržet (i když by podle svých specifikací nemusel).

Časovací tok má vyšší prioritu a většinou běží samostatně. Přerušen může být jen toky s ještě vyšší prioritou (což jsou toky systémové) a uvedené možné variace prodlev proto nejsou tak velké. Nicméně i tak vzájemné interakce systémových toků a časovacího toku vyúsťují v drobné interferenční odchylky velikosti až ±5 milisekund od správné hodnoty.

Zkušenosti ukazují, že takové variace jsou celkem pravidelné. Například postupné délky opakovaného intervalu 1 000 milisekund mohou být 1 001, 1 002, 1 001 a 996 milisekund, což zase není až tak špatné. Bohužel (to uvidíte později), tyto variace mohou velmi ovlivnit okamžiky vztažené k absolutnímu času. Čtyřem uvedeným hodnotám intervalů mohou například odpovídat absolutní časové okamžiky 0,998, 1,999, 3,001, 4,002 a 4,998 sekund. Použijeme-li z těchto okamžiků jen celé sekundy (nebo jinak, budeme-li v těchto okamžicích číst sekundy absolutního času), dostaneme posloupnost sekund 0, 1, 3, 4, 4. Nic moc pravidelného i přesto, že aplikace, přesněji časovací tok, pracuje s přesností ± 0,2 % (největší odchylka byla na sekundovém intervalu ± 2 milisekundy).

Z uvedeného vyplývá, že systém Control Web je schopen velmi přesně dodržet počet časových kroků v určitém intervalu v případě, že aplikace běží volně, bez skluzu. Obecně lze říci, že čím více se zkracují periody běhu přístrojů, tím větší budou variace délek jednotlivých period (intervaly přestanou být izochronní).

Neměli bychom zapomenout, že časovací tok neběží jen tak sám pro sebe a že aplikace obsahuje také nějaké přístroje a ovladače. Především ony totiž nakonec ovlivňují skutečné délky period a určují, jestli aplikace bude pracovat hladce nebo s časovými potížemi. Nejrychlejší přístroje (program, samostatné procedury) spotřebují řádově desítky mikrosekund v každém běhu. Aplikace však také archivuje, vykresluje či komunikuje a spotřeby času těchto úloh mohou dosáhnout i sekundových hodnot. Konečný výsledek, pružnost a svižnost aplikace reálného času v důsledku proto vždy záleží jen na návrhu a implementaci vlastní aplikace.

#### Priorita procesu jako celku

Control Web nabízí pro globální úpravu běhu aplikace speciální možnost zvýšení (nebo snížení) priority celého procesu, tedy automaticky všech jeho prováděcích toků (detailně je rozdíl mezi prioritami procesů a prováděcích toků popsán v kapitole Co jsou to procesy a prováděcí toky). Celá aplikace (nejen časovací tok, ale i výkonná část) tak může mít přednost před všemi ostatními v operačním systému. To může být někdy užitečné, například v situacích, kdy v systému běží nějaká úloha na pozadí — například programy synchronizující čas. Jinak je zvyšování priority procesu jako celku de facto zbytečné, neboť:

- Aplikace a Control Web pracují v systému samostatně, bez konkurenčního běhu jiných aplikací operačního systému (to je nejčastější způsob provozování systému Control Web. Tehdy je zbytečné prioritu zvyšovat, protože operační systém bude jednu svou aplikaci obsluhovat stále stejně bez ohledu na její prioritu.
- Control Web pracuje na počítači s jinými aplikacemi, například tabulkovým kalkulátorem, nebo databázovým serverem. Tehdy zvýšení priority způsobí přednostní běh systému Control Web a databázový server (případně tabulkový kalkulátor) se nemusejí po dlouhou dobu dostat ke slovu a nemusejí tudíž být schopny vůbec plnit svůj účel.
- Control Web přímo spolupracuje s jinými aplikacemi, například OPC serverem nebo tabulkovým kalkulátorem (pomocí DDE). Tehdy zvýšení priority způsobí nedostupnost spolupracujících aplikací a Control Web bude muset nejspíše na výsledky operací těchto aplikací čekat. Vyšší priorita procesu bude promrhána synchronizací a Control Web vlastně bude "rychle zdržovat".

### Řízení nebo vizualizace?

Většina technologických úloh je povahou spíše vizualizační. Aplikace především slouží k zobrazení stavu, archivují hodnoty, případně předzpracovávají data pro další použití. Důležitý je sběr dat a jejich prezentace. Takové aplikace také většinou zpracovávají velký tok dat, nezřídka se současně měří mnoho tisíc kanálů a vytvářejí stovky databází.

V kontrastu proti vizualizačním úlohám stojí přímé řízení, které je takřka pravým opakem. Datový tok bývá malý (ale rychlý), aplikace především řídí a bývá zaručena určitá doba odezvy. Většinou se také nic nearchivuje a na obrazovce (pokud ji počítač vůbec má zapojenu) se zobrazují jen nejnutnější údaje.

Z pohledu aplikace a časovacího toku systému Control Web jsou oba přístupy (téměř) totožné, neboť funkčnost aplikace je vždy dána pouze funkčností použitých přístrojů. Obecný rámec reálného času poskytovaný systémem Control Web to nijak neovlivňuje. Co však může být nastaveno, a co může ovlivnit způsob práce aplikace, je míra zdržení operačním systémem.

Pokud Control Web zrovna neprovozuje nějakou aplikaci, pracuje normálně jako ostatní aplikace operačního systému. Většinu času čeká na nějakou vstupní událost, kterou nejčastěji bývají nějaká operace s myší, klávesnicí nebo pokyn k překreslení nějaké části plochy. Objeví-li se událostí najednou více, seřadí je operační systém do fronty a Control Web je zpracuje postupně. Pojmenujme všechny tyto události jako vstupní.

Rozběhnete-li aplikaci, situace se změní. Control Web jako systém reálného času dává přednost běhu aplikace před vstupními událostmi, které zpracovává až když mu zbude nějaký čas (řečeno s určitou nadsázkou). Běží-li aplikace s dostatečnou rezervou (neboli nemusí-li být neustále všechny přístroje poháněny), je v prodlevách mezi jejich akcemi na zpracování vstupní fronty času dostatek. Pokud však aplikace "nestíhá", není na vstupní události čas, a systém reálného času má dvě možnosti — buď vstupní události ignorovat, nebo respektovat. Bohužel, vstupní události jsou nevyzpytatelné, a nelze se nijak spolehnout, že jich bude jen malý počet nebo že budou všechny zpracovány v určitém čase. Pokud je systém zpracovává, může to pro něj být dosti nepříjemná věc.

Časovací tok je zpočátku nastaven tak, aby při svém běhu vstupní události respektoval, takže po dokončení každé jedné elementární smyčky zjišťuje, jestli operační systém něco zajímavého nepřipravil. Pokud ano, počká nejprve časovací tok na vyprázdnění vstupní fronty a teprve potom pokračuje ve svém běhu. Z toho vyplývá, že základní způsob práce aplikace systému Control Web je spíše vizualizační — po každém elementárním kvantu běhu jsou zpracovány všechny dostupné vstupní události.

Pro aplikace přímého řízení je tento přístup riskantní. Vstupní události mohou počkat, protože primární je zaručení správného chování řídicího systému. Časovací tok takovou změnu umožňuje, a dokáže běžet naplno bez čekání na vyprázdnění vstupní fronty — dokáže běžet v režimu pevného reálného času. Volba, která ovlivňuje popsané chování časovacího toku, je součástí aplikační sekce settings a jmenuje se hard_real_time:

    settings
    ...
    hard_real_time = true;
    ...
    end_settings;

Parametr samozřejmě můžete nastavit také v záložce "Systémové nastavení" v "Datových inspektorech" volbou "Striktní dodržování reálného času".

Aplikace pracující v režimu pevného reálného času dává přednost svému běhu. Uvažme nyní znovu důležitá fakta, která s během aplikace v tomto režimu souvisejí:

- aplikace (časovací tok) periodicky oživuje jednotlivé přístroje
- v mezidobí (uvnitř periody) se normálně zpracovává fronta vstupních událostí bez jakéhokoli omezení
- neexistuje-li žádné mezidobí (aplikace běží maximální rychlostí), aplikace vstupní frontu nezpracovává

Souhrný výsledek je tento: Pokud aplikace pevného reálného času nemá rezervu a pracuje maximální rychlostí, nezpracovávají se vstupní události, a aplikace proto: nekreslí, nereaguje na klávesnici a nereaguje na myš, takže nepracují tlačítka ani jiné ovládací prvky. Teprve až se systému uleví, vyšetří se nějaký čas, a fronta vstupních událostí se zpracuje. Není příliš dobré, aby aplikace soustavně vstupní frontu ignorovala, protože se tím de facto odřezává od zpráv operačního systému. Nicméně, pokud to má aplikace přikázáno, nic jiného jí nezbývá.

Běh v pevném reálném čase ovlivňuje ještě jeden parametr. Control Web standardně sleduje dobu, po kterou aplikace ignoruje vstupní frontu, a pokud je tato doba příliš dlouhá, násilím aplikaci pozdrží a frontu zpracuje. Tuto sledovací dobu, po kterou bude aplikace mít povoleno ignorovat vstupní události, nastavíte parametrem aplikace paint_time_limit v sekci settings. Možnosti nastavení jsou široké — od 0, kdy de facto zrušíte pevný reálný čas (otázka je, proč byste to tak dělali), až po infinite, kdy pevný reálný čas poběží přesně tak tvrdě bez zpracování vstupních událostí, jak to bylo popisováno.

Aplikace pevného reálného času musí být více než jiné dobře promyšlena a musí více než jiné pracovat s dostatečnou rezervou (opět další ukázka klasického konfliktu: mocnější a kvalitnější řešení vyžaduje více práce a promýšlení). Použití pevného reálného času je třeba vždy zvážit, protože jeho vlastnosti a způsob chování jej předurčují pro "neviditelný" běh. Je asi zbytečné snažit se pomocí pevného reálného času dávat přednost běhu aplikaci, která v každém svém kroku přeskládá několik databází na síťových serverech. Doporučení je jasné — prvotní nastavení aplikace (tedy bez pevného reálného času) vyhoví v 99,5 % případů a pevný reálný čas by měl zůstat vyhražen pro skutečně kritické řídicí aplikace.

### Okno časování

Součástí aplikace systému Control Web jsou různé podrobné informace o běhu časovacího i výkonného toku, o běhu jednotlivých přístrojů a o komunikacích. Aplikace (přesněji každý modul) může pomocí parametru show_timing_info sekce settings všechny tyto údaje zobrazit v okně "Časování" (volbu "Zobrazit okno s informacemi o časování aplikace" můžete nastavit také v záložce "Systém" v "Datových inspektorech"), které je potom kdykoli za jejího běhu dostupné k nahlédnutí. Okno "Časování" obsahuje čtyři vodorovné záložky:

Záložky okna Časování

Jednotlivé záložky obsahují údaje sdružené podle logického významu, přičemž záložka "Časování" obsahuje souhrnné informace o běhu, záložka "Ovladače" souhrnná data o komunikaci, záložka "Kanály" data o komunikaci jednotlivých kanálů a záložka "Přístroje" statistická data o jednotlivých přístrojích.

Význam jednotlivých položek v záložkách bude podrobně vysvětlován postupně v dalším textu kapitoly, tak jak se postupně bude odhalovat způsob práce systému Control Web. Zde bude vysvětlen pouze význam těch údajů, o kterých se již další text nebude zmiňovat:

- Záložka "Časování"

- "Čas od rozběhu aplikace" — časový interval, který uplynul od okamžiku startu aplikace. Zobrazený údaj plyne rovnoměrně a ukazuje na aplikaci nezávislý — absolutní čas.
- "Dosažený čas aplikace" — čas, kterého dosáhl časovací tok. Časovací tok vždy na konci svého elementárního cyklu určí časový okamžik, kdy má být operačním systémem probuzen. Rozdíl absolutního času (času od rozběhu) a času časovacího toku v tento okamžik přitom určuje, jaký bude další postup časování. Pokud je rozdíl záporný (skutečný čas ještě nedosáhl času aplikace), počká časovací tok do okamžiku probuzení; pokud je rozdíl kladný (skutečný čas předbíhá čas aplikace), aplikace pracuje ve skluzu (o skluzu viz. níže), má časové potíže, a časovací tok okamžitě pokračuje v časování aplikace. Pokud aplikace pracuje s rezervou, je zobrazený údaj větší než čas od rozběhu aplikace.
- "Rozdíl" — zobrazuje výše popisovaný rozdíl absolutního času a času časovacího toku. Údaj je nenulový, pouze je-li aplikace ve skluzu.
- "Striktní reálný čas" — zobrazuje aktuální stav (zapnuto/vypnuto) chování časovacího toku (význam striktního (pevného) reálného času je popsán v oddíle Řízení nebo vizualizace.
- "Celkový spotřebovaný čas" — čas, po který časovací tok nečekal na spuštění další elementární smyčky. Jinými slovy, časovací tok po většinu času čeká (ve správně navržené aplikaci, která nemá časové potíže) na okamžik, kdy má rozběhnout nějaký přístroj. Jakmile takový okamžik nastane, časovací tok se probudí a začne měřit čas. Proběhnou komunikace, spustí se přístroje, počká se (případně) na vyprázdnění vstupní fronty, časovací tok se dostane na konec své smyčky, a pokud bezprostředně nemá smyčka opět pokračovat, přestane měřit čas. Rozdíl těchto dvou časů — délka jedné smyčky časovacího toku (potkáme ji později) — je přičtena k celkovému spotřebovanému času. Celkový spotřebovaný čas tudíž neustále roste, a vždy je menší než čas od rozběhu aplikace.
- "Čekání a synchronizace" — souhrnná doba všech komunikačních prodlev. Údaj se zvyšuje při čekání na prodlevy měření (input_timeout), potvrzení zápisu (output_timeout) a mezimodulární synchronizace (remote_sync_timeout). Pokud jsou tyto prodlevy nulové, případně pokud aplikace nekomunikuje, je tento údaj nulový.
- "Čas spotřebovaný všemi ovladači" — souhrnná doba strávená ve volání procedur ovladačů.
- "Čas spotřebovaný všemi přístroji" — souhrnná doba strávená ve volání procedur přístrojů
- "Dokreslování" — souhrnná doba spotřebovaná při vyprazdňování vstupní fronty událostí. Operační systém za běhu aplikace posílá systému Control Web většinou jen pokyny k překreslení (překreslení bývá častým výsledkem akcí přístrojů), proto je tento údaj pojmenován "Dokreslování" (i přesto, že to není úplně přesné).
- "Režie Windows" — souhrn všech časových okamžiků strávených mimo vlastní kód časování aplikace. Časovací tok periodicky pohání aplikaci pracující v jiném prováděcím toku; operační systém zase postupně přiděluje čas jednotlivým prováděcím tokům. Přitom právě vzájemná přepínání časovacího a výkonného toku jsou z pohledu operačního systému okamžiky vhodné k manipulaci s prováděcími toky. Časovací tok v určité fázi svého běhu aktivuje výkonný tok, nicméně operační systém může dříve než výkonný aplikační tok aktivovat jiné toky také čekající na přidělení systémového času. Délka běhu takovýchto toků se tudíž připočítá k "Režii Windows", i přesto, že se nejedná o pouhé přepnutí časovacího a výkonného toku (například při běhu vícemodulární aplikace je součástí údaje "Režie Windows" mimo jiné i délka běhu časovacích toků ostatních modulů). Pokud je Control Web jedinou aplikací, která v daném operačním systému běží, bude údaj zobrazovat věrně skutečnou režii přepínání toků.
- "Režie časování systému Control Web" — zůstatková hodnota, skutečná doba spotřebovaná časovacím tokem pro vlastní běh a funkci — údaj zahrnuje čas spotřebovaný během všech činností časovacího toku, jak byly popsány v oddíle Princip časování.

- Záložka "Ovladače"

- "Čas spotřebovaný všemi ovladači" — souhrnná doba strávená ve volání funkcí ovladačů, údaj je kopií shodně pojmenovaného údaje ze záložky "Časování".
- "Čas spotřebovaný tímto ovladačem" — doba strávená ve volání funkcí ovladače, zvoleného z výběrového seznamu v horní části záložky.

- Záložka "Kanály"

Záložka kanály je mírně odlišná od záložek "Ovladače" a "Přístroje". Nenabízí totiž ve svém výběrovém řádku jména dostupných kanálů. Kanálů bývá v aplikacích velký počet a kopírování jejich jmen do seznamu by spotřebovalo mnoho času i paměti. V záložce "Kanály" proto musíte jméno požadovaného kanál nejprve vepsat do výběrového řádku, a teprve až po té systém zobrazí jeho data. Jednou zapsaná jména se přitom do výběrového řádku přidávají. Je-li vybraný kanál pole, musíte do řádku spolu s jeho jménem zapsat také požadovaný index (například chaPressure[112]).

- "Jméno ovladače" — jméno ovladače, kterému zvolený kanál patří.
- "Číslo kanálu v ovladači" — číslo kanálu definované v aplikaci a parametrickém souboru ovladače.
- "Směr kanálu" — zobrazení směru kanálu, tedy jestli je kanál vstupní, výstupní nebo obousměrný.

- Záložka "Přístroje"

- "Čas od rozběhu aplikace" a "Čas spotřebovaný všemi přístroji"— údaje jsou kopiemi údajů v záložce "Časování".
- "Dosažený čas přístroje" — budoucí časový okamžik, ve kterém bude přístroj časovacím tokem spuštěn. Pokud je čas větší než čas od rozběhu aplikace, pracuje přístroj pravidelně a jeho činnost probíhá v souladu s jeho periodou. V opačném případě (kdy přístroj dosáhl času, který je menší než čas od rozběhu aplikace) přístroj "nestíhá" a pracuje ve skluzu. Údaj je ekvivalentem údaje "Dosažený čas aplikace" ze záložky "Časování" — tam se ovšem údaj vztahuje k aplikaci jako celku, tedy ke všem existujícím přístrojům (později v oddíle o skluzu uvidíte, že je docela dobře možné, aby aplikace ve skluzu byla a přístroj nikoli).
- "Rozdíl" — zobrazuje rozdíl absolutního (skutečného) času a dosaženého času přístroje. Údaj je nenulový pouze tehdy, je-li přístroj ve skluzu.
- "Čas spotřebovaný tímto přístrojem" — doba strávená ve volání procedur přístroje.
- "Čas strávený ve skluzu" — souhrnná doba, po kterou přístroj běžel s časovými potížemi, kdy se dostával ke slovu později, než měl podle definice své periody časování.

Některé údaje zobrazované v okně "Časování" jsou dostupné přímo běžící aplikaci — většina informačních a statistických údajů o komunikaci kanálů je dostupná v jejich atributech (podrobný popis atributů obsahuje kapitola Datové elementy a výrazy, údaje o skluzu aplikace a skluzu přístroje jsou zase dostupné v parametru ActivateMode systémové událostní procedury OnActivate() (popis systémových událostních procedur obsahuje kapitola Programování a procedury — OCL). Aplikace se tak může přesně dozvědět, v jakém momentálním stavu se komunikace, případně celá aplikace, nachází.

## Časování přístrojů

Oddíl Časování přístrojů se zabývá časováním z pohledu přístrojů — z pohledu aplikace a jejího tvůrce. Její náplní budou způsoby časování — tedy jak aplikaci pohánět. Vnitřní principy běhu systému Control Web popisuje dále oddíl Časování zevnitř.

Aplikace reálného času jsou navrhovány "událostním" a "algoritmickým" způsobem — "událostním" proto, že v řadě situací aplikace reagují (a vykonávají akce) na uživatelský zásah nebo informaci z ovladače, "algoritmickým" proto, že aplikace realizuje nějaký předem známý postup řízení, archivací nebo jiných akcí. Primární je znalost technologie a jejích součástí, aplikace je potom modelem, který technologii ovlivňuje.

Zatímco "událostní" přístup vyúsťuje v řadu akcí neperiodických, asynchronních, přístup "algoritmický" produkuje akce peridodické, akce, které v pravidelných intervalech něco monitorují, nebo ovlivňují. Periodické provádění akcí je základ běhu všech aplikací reálného času.

Elementárním prvkem aplikace je přístroj. Každý přístroj může uskutečňovat velké množství činností (v extrémním případě můžete celou aplikaci vytvořit s použitím procedur jednoho přístroje), přičemž z pohledu systému je již lhostejné, kolik jich vlastně je. Control Web časuje (v tomto oddíle se pojem časování zúží a bude synonymem ke spojení "periodická aktivace") vždy celé přístroje — procedury mohou také "běžet samostatně" a "dobíhat", ale jejich aktivaci zajišťuje (vnitřně) přístroj, nikoli systém. Dále proto budeme používat spojení "časování přístroje", přičemž tím bude vždy myšleno "časování přístroje jako celku", tedy včetně případných procedur.

### Relativní časování

Základní způsob, jak časovat, je časování periodou. Časování periodou znamená aktivaci přístroje vždy po uplynutí zvolené délky periody, bez vztahu k okolnímu absolutnímu času. Systém zajišťuje jen periodicitu a shodnost intervalů, nic více. Protože je počátek časování periodou vždy relativně vztažen k okamžiku startu aplikace, nazývá se toto časování také relativní časování (časovací periody musejí někdy začínat a start aplikace je celkem přirozeným vhodným okamžikem). Systém Control Web bude přístroj relativně časovat, pokud bude v zápisu jeho parametru timer číselná hodnota (případně číselná konstanta):

    meter Graph;
      ...
      timer = 15;
      ...
    end_meter;

Přístroj Graph bude časován každých 15 sekund počínaje startem aplikace (z příkladu vyplývá, že časový údaj v přístroji je udáván v sekundách; všechny časové údaje v aplikaci jsou udávány v sekundách).

Perioda může být zadána v rozmezí od 0 do "nekonečna". Nulová perioda má speciální význam — přístroj bude časován maximální možnou rychlostí systému a jednotlivé smyčky časovacího toku budou velmi krátké a rychlé. Přístroj s nulovou periodou bude pracovat značně anizochronně (koneckonců perioda je nulová, tak jakápak izochronie) a okamžiky jeho oživování budou tudíž značně ovlivněny momentálním stavem celého operačního systému. Nicméně, rychlost systému je opravdu značná a přístroj s nulovou periodou může být obvolán mnohotisíckrát za sekundu. Perioda "nekonečno" se do textu zapisuje jako klíčové slovo infinite (celý parametr potom bude timer = infinite;) a má také speciální význam — přístroj bude spuštěn pouze jednou při startu aplikace.

Na tomto místě je vhodné poprvé použít pojmu časový krok a začít s ním operovat. Časový krok má (bohužel) v systému Control Web dva významy. První význam je vztažen k přístroji, a znamená jednu aktivaci přístroje (ať už to je aktivace časováním nebo nějakou událostí), druhý význam je vztažen k vnitřnímu časování a znamená jeden elementární běh časování systému. Tento oddíl zůstane u významu prvního, neboť druhého si dosyta užijete později.

Pro relativní časování přístrojů v souhrnu platí:

- Relativní časování začíná v okamžiku startu aplikace. Každý relativně časovaný přístroj provede při startu aplikace jeden (první) časový krok, bez ohledu na délku své periody.
- Další časové kroky přístroj provádí vždy po uplynutí délky periody. Zachovávání délky periody je primární, a relativní časování proto není nijak ovlivňováno změnami systémového (absolutního) času.

Všimněte si, z prvního bodu vyplývá, že start aplikace může být velmi náročný. Aplikace může obsahovat velké množství relativně časovaných přístrojů, a všechny takové přístroje při startu provedou svou akci. Start aplikace proto může představovat značné nahuštění činností přístrojů (takové nahuštění již nikdy později nemusí nastat) se všemi důsledky z toho plynoucími — například může vzniknout skluz.

Důsledkem druhého bodu je zase skutečnost, že relativně časovaný přístroj ignoruje absolutní čas. Jednak není možné stanovit počátek časování (vždy se začne v okamžiku startu) a jednak beze změny periody není možné zachovat aktivace ve stále stejných okamžicích absolutního času (i kdyby se to po startu podařilo, tak první změna systémového času vše zhatí). Případnou vazbu na absolutní čas je proto třeba realizovat jinak.

Relativní časování je velmi jednoduché, je možné je považovat za časování "první volby" a pravděpodobně bude použito ve většině případů.

### Absolutní časování

Jednoduchým rozšířením popsaného relativního časování vznikne časování absolutní, neboli časování periodou s posunutím. Přístroje s absolutním časováním budou mít v zápisu parametru timer dvě časové hodnoty:

    program Analyze;
      ...
      timer = 60, 10;
      ...
    end_program;

První číslo opět definuje periodu (podobně jako při relativním časování), druhé posunutí. Časování periodou s posunutím je vztaženo ke skutečnému absolutnímu času, systém časování přístroje udržuje v závěsu systémového času.

Počáteční okamžik všech period s posunutím je stanoven na půlnoc dne, kdy byla aplikace spuštěna (půlnoc, která již uplynula). Parametr posunutí potom určuje zpoždění začátku první periody, neboli čas, který uplyne od půlnoci do okamžiku prvního časového kroku přístroje.

Podívejme se na periodu s posunutím více prakticky. Uvažme případ nulového posunutí. Absolutní perioda časování začíná o půlnoci a dále pokračuje ve stanovených intervalech. Časování 60, 0 proto znamená "první časový krok je o půlnoci a další následují po minutě", časování 259200, 0 znamená "první krok o půlnoci a další následují každou třetí půlnoc, tedy o půlnoci na konci 3., 6., 9., ... dne běhu".

Nenulové posunutí celý mechanizmus časování posune o patřičný interval vpřed. Časování 60, 30 znamená "první časový krok je 30 sekund po půlnoci a další následují po minutě, tedy v 00.01:30, 00.02:30, ...", časování 259200, 86400 znamená "první časový krok bude jeden den po půlnoci, další potom po třech dnech, tedy o půlnoci na konci 1., 4., 10., ... dne běhu".

Vztah periody a posunutí je omezen pouze přirozenou podmínkou, že posunutí nemůže být větší než perioda. Pokud však přesto takové posunutí zadáte, použije z něj systém zbytek po dělení periodou (stejného výsledku dosáhnete jak časováním 60, 17 tak časováním 60, 77).

Aplikace bývá spuštěna v nepříliš přesně určeném okamžiku. Bez ohledu na tento fakt systém samozřejmě musí zajistit správné rozběhnutí absolutních period. Control Web vypočítá nejbližší vhodný okamžik (který odpovídá výše popsanému "půlnočnímu" mechanizmu) tak, aby přístroj svůj první časový krok provedl v souladu s definicí časování. Absolutně časovaný přístroj prostě jen začne pracovat místo v první periodě po půlnoci v některé z period dalších. To znamená, že absolutně časované přístroje vždy vykonají svůj první časový krok dříve, než uplyne (relativně od startu aplikace) jejich perioda.

Absolutní časování je zavěšeno na skutečný (absolutní) čas. Musí proto reagovat na jeho změny. Zadáte-li například časování 3600, 1800, předpokládáte, že časové kroky přístroje budou vždy v polovině mezi celými hodinami, a to samozřejmě musí být zachováno i v případě, že se čas počítače posune o deset minut (třeba kvůli tomu, že se předbíhal). Změny systémového času proto vždy způsobují změny absolutního časování přístrojů. Na rozdíl od relativního časování (kde je prioritní perioda) má při časování absolutním přednost vazba na skutečný čas. Periody nejsou tak důležité, zachovávají se pouze v intervalech mezi změnami systémového času.

Mechanizmus výpočtu period s posunutím pracuje stejně dobře i pro desetinná čísla (pro zlomky sekundy). Klidně můžete přístroji definovat časování 1.17, 0.29 a systém zajistí přístroji časové kroky ve správných okamžicích. Je to poněkud méně zřejmé než při použití celých čísel, nicméně je to stejně dobře možné; i přesto, že většina absolutně časovaných přístrojů bude používat period a posunutí celistvých.

Systém Control Web počítá periody a posunutí v okamžiku startu a dále vždy při změně systémového času. Control Web vždy vypočítá jen počáteční zdržení, které je nutné pro zarovnání posunuté periody, a další časové kroky již následují periodicky. Mechanizmus výpočtu dalších časových kroků je tak shodný pro obě časování — absolutní i relativní. Z hlediska výkonu aplikace a režie systému je proto absolutní časování shodné s relativním.

Pro absolutní časování v souhrnu platí:

- Absolutní časování má vždy zdánlivý počátek v okamžiku uplynutí "posunutí" sekund od půlnoci dne spuštění aplikace. Aplikace při startu vypočítá nejbližší budoucí okamžik uplynutí posunuté periody. Tehdy bude přístroj poprvé periodicky aktivován.
- Další časové kroky přístroj provádí po uplynutí délky periody, pokud nedojde ke změně absolutního času. Primární je zachování posunutí vůči půlnoci, která se změnou času může posunout.

Absolutně časované přístroje proto mohou být použity například:

- k rozfázování běhu aplikace. Větší množství shodně relativně časovaných přístrojů provádí svou činnost ve skupinách, v mezidobí jejich period se naopak nic neděje. Může být proto rozumné přístroje pomocí absolutního časování rozložit posunutím v jejich intervalech, tak, aby byl výsledný běh plynulejší — častěji se budou vykonávat menší množství přístrojů. Například 100 přístrojů s periodou 10 sekund můžete rozložit do 5 skupin s časováními "10, 0", "10, 2", "10, 4", "10, 6", "10, 8" vždy po dvaceti přístrojích. Podobně můžete rozfázovat akce, které se vážou k určitému důležitému okamžiku — například k okamžiku celé hodiny. V tuto dobu se zpravidla v aplikacích sejde několik činností — třeba hodinové archívy, desetiminutové a minutové archívy. Archivace je obecně časově náročná (protože se pracuje se soubory) a souhrnný běh více archivací může snadno aplikaci donutit ke skluzu. Zdržením (nebo zpožděním) hodinových archivací o deset sekund (časovač 3600, 10 nebo 3600, 3590) aplikace na přesnosti nic neztratí a nedojde přitom k časovým potížím.
- k přesné synchronizaci přístroje a absolutního času. To je hlavní způsob použití absolutního časování, pokud absolutní časování někde potkáte, tak nejspíše v této podobě. Typické jsou archivace — jak jinak než absolutním časováním přístroji řeknete, aby archivoval v každou celou čtvrthodinu absolutního času? (mimochodem, jde to, ale není to nic elegantního...)
- k rozfázování startu aplikace (aby se nevytvořil počáteční balík všech prvních časových kroků přístrojů). Princip je stejný jako v prvním bodě; rozfázování startu aplikace je samostatně uvedeno jen proto, že to je mírně odlišná motivace.

Hlavní odlišnost absolutního a relativního časování spočívá v zachovávání či nezachovávání délek jednotlivých period. Pokud není délka periody pro přístroj kritická (chcete-li přístroj časovat "asi tak každých deset sekund" tak perioda kritická není), je vhodné zamyslet se nad časovým rozdělením zátěže — rozfázováním běhu a použít absolutní časování. Uvidíte, že aplikace poběží lépe, když bude častěji provádět menší dávky přístrojů.

V souvislosti s absolutním časováním mějte na paměti časové variace způsobené přepínáním prováděcích toků. Uvažme přístroj s časovačem 1, 0, který zobrazuje sekundy skutečného času. Takový přístroj by měl zobrazovat každou sekundu novou hodnotu. Již bylo vysvětleno, že tomu tak nebude vždy (milisekundové variace period se ořezáním projeví jako sekundová chyba). Je proto třeba s tímto mechanizmem počítat:

- chcete-li zajistit správné zobrazení sekund v přístroji, který ukazuje v aplikaci reálný čas, použijte časování s rezevou — například 1, 0.1. Totéž platí pro minuty a hodiny — časovače 60, 0.1 a 3600, 0.1
- chcete-li vždy do archivního souboru zapsat skutečně aktuální novou hodinu, posuňte archiver kousek dopředu — použijte například časování 3600, 1 (správná hodina bude samozřejmě do archívu zapsána také v případě, že je archiver již posunut kvůli rozfázování zátěže).

Poslední poznámka se týká odlišných konvencí zápisu desetinných čísel v našich a anglosaských zemích. Zatímco u nás je obvyklé oddělovat desetinnou část čísla čárkou, v anglosaských zemích se používá tečka. Control Web používá stejně jako všechny ostatní vývojové systémy a programovací jazyky desetinnou tečku. Pokud v přístroji použijete zápis expression = a * 1,9;, systém ohlásí chybu. Pokud ale stejné číslo zapíšete u klíčového slova timer, žádná chyba hlášena nebude, systém údaj akceptuje jako časování s periodou 1 a posunutím 9.

### Časovače

Relativně i absolutně časované přístroje provádějí své časové kroky v rytmu, který jim přikazuje časovací tok aplikace. Jsou časovány přímo samotným systémem. Control Web definuje ještě i jiný způsob časování — nepřímý, kdy přístroje provádějí své časové kroky uvnitř časového kroku jiného logicky nadřazeného přístroje. Přístroje, které mohou zastřešovat při časování jiné přístroje, se nazývají časovače a způsob časování přístrojů s využitím časovačů časování časovačem.

Princip práce časovačů je jednoduchý — časovač ve svém časovém kroku prochází jednotlivé podřízené přístroje a podle určitých pravidel jim povolí uskutečnit jejich časové kroky. Časovače vytvářejí jakési "malé jadérko", které pohání jen omezenou skupinu přístrojů. Je proto celkem logické, že podřízené přístroje pracují všechny se stejnou periodou jako jejich časovače. Samotné přístroje časovačem časované pracují úplně stejně jako při periodickém časování (dokonce to ani nijak nejsou schopny rozlišit). Přístroj časovaný časovačem obsahuje ve svém parametru timer jméno příslušného časovače, a případně navíc požadované pořadí časování:

    meter Graph;
      ...
      timer = Sequencer_100ms, 4;
      ...
    end_meter;

Přístroj Graph bude časován časovačem se jménem Sequencer_100ms a časovač bude tento přístroj spouštět jako čtvrtý v pořadí. Definice pořadí časování není povinná, a pokud ji neuvedete, bude přístroj zařazen do časovače na aktuální poslední pozici (další přístroje bez určení pořadí časování budou opět umístěny na aktuální poslední pozici, tedy za). Definované pořadí časování je nejlépe viditelné ve stromu časování grafického editoru vývojového prostředí. Pořadí jednotlivých přístrojů zařazených do časovače přesně odpovídá zapsaným hodnotám. Pokud pořadí přístroje ve stromu (přetažením) upravíte, změní se i zápis pořadí časování ve zdrojovém textu. Pokud je během načítání zdrojového textu nalezeno několik přístrojů se shodně definovaným pořadím, zařadí je systém do časovače postupně tak, jak jsou nalezeny ve zdrojovém textu.

Všechny časovače mohou obsahovat najednou více přístrojů (i časovačů). Podřízené přístroje jsou v časovačích uspořádány za sebou v sekvenci, kterou časovače pevně dodržují. Znamená to, že časovač jednotlivé podřízené přístroje časuje postupně, tak jak přístroje ukončují své časové kroky. Dokud přístroj neukončí svou činnost, nepokračuje časovač dále. Tato sekvenčnost zpracování je vlastní všem časovačům a je to zároveň to hlavní, co odlišuje periodické časování od časování časovačem, neboť při periodickém časování systém nijak pořadí časování přístrojů nezaručuje — v ideálním případě nekonečně rychlého počítače (toho se nikdy nedočkáme) by pracovaly všechny periodicky časované přístroje současně.

Poznámka k procedurám — procedury mohou ukončit (nebo přerušit) svůj běh několika způsoby: doběhnutím na konec, nebo příkazy pause, wait, yield a stop. Pokud bude v přístroji procedura OnActivate(), která bude některým z popsaných ukončovacích příkazů přerušena, ukončí se tím i celý časový krok přístroje. Zařadíte-li proto do časovače přístroj s procedurou, je vhodné pečlivěji rozmyslet, jak jsou použité procedury naprogramovány. Jejich předčasné (neuvědomělé) ukončení může ovlivnit běh dalších přístrojů jinak, než by si autor přál (a plánoval).

Základní a nejjednodušší časovač je sequencer. Nedefinuje k popsaným principům navíc žádná další pravidla a pracuje jako jednoduchá posloupnost přístrojů. Sequencer použijete v případě, kdy vyžadujete zajištění následnosti nějakých akcí.

Složitější časovač je iterator, který navíc k sekvenčnímu zpracování přístrojů přidává možnost jejich opakování — zacyklení. Iterator na počátku svého časového kroku nejprve vyhodnotí podmínku výskoku (jestli má podřízené přístroje rozběhnout či ne) a případně přístroje postupně aktivuje. Jakmile iterator všechny přístroje obvolá, opět podmínku testuje a v případě jejího nesplnění pokračuje v obvolávání přístrojů znova od začátku. Celkem zřejmé je, že cyklus přístrojů v iteratoru musí nějak (i nepřímo) ovlivňovat podmínku výskoku. Jinak se snadno může stát, že se cyklus stane nekonečným. Iterator je přístroj, který nebudete příliš často používat, jednodušší je vytvářet smyčky přímo programátorským zápisem v těle nějaké procedury.

Poslední časovač je selector. Tento časovač (kromě sekvenčního zpracování přístrojů) umí pracovat s několika sekvencemi najednou a umí jednotlivé sekvence také vypínat a zapínat. Jednotlivé sekvence selectoru jsou nazývány větve (podle podobnosti s živými stromy). Součástí definice větve je podmínka, která určuje, jestli selector přístroje v odpovídající sekvenci v daném časovém kroku rozběhne nebo ne. Selector tak nabízí velmi užitečnou možnost vypínat a zapínat časování mnoha přístrojů najednou. Přístroje zařazené do různých větví selectoru pracují podmíněně podle výsledku vyhodnocení příslušných podmínek. Je-li podmínka splněna, selector přístroje v dané sekvenci aktivuje, v opačném případě nikoli.

Selector budete (měli byste) používat velmi často, protože vypínaní nebo zapínání časování přístrojů může dramaticky zefektivnit běh aplikace. Selector se typicky používá ve vazbě na panely, přesněji na jejich viditelnost na obrazovce. Mnoho panelů obsahuje mnoho přístrojů, které nemusejí být časovány, když panel není zobrazen (grafy pochopitelně musí běžet neustále). Patří sem všechny signalizace stavů nebo zobrazení hodnot bez historie. Pokud tyto přístroje necháte časovat selectorem, který bude mít v podmínce výraz "panel je vidět", budou tyto přístroje časovány jen bude-li panel zobrazen. Uvážíte-li, že panelů bývá často více jak deset, a přístrojů v nich mnohem více jak deset, bude úspora prostředků při vypnutí časování velmi výrazná. Pamatujte na to, že aplikace bude právě tak výkonná a svižná, jak ji naprogramujete.

Všechny tři časovače dohromady umožňují definovat obecný algorimus. Aby to bylo možné, musí mít programátor možnost vytvořit posloupnost (sequencer), vyrobit cyklus (iterator) a mít možnost rozhodování — větvení programu (selector). To časovače umožňují a teoreticky byste s jejich pomocí mohli zapsat jakýkoli program (i když to příliš nedoporučuji, snad jen jako oddychové zpestření).

### Časování pomocí procedur

Trochu netypické a odlišné je časování pomocí procedur nebo přímo časování procedur. Výrazové prostředky zápisu algoritmu v systému Control Web jsou totiž natolik mocné, že umožňují samy o sobě řídit a časovat přístroje. Hlavním aktérem takového časování je vždy příkaz pause, který dokáže po stanovenou dobu vykonávání algoritmu pozdržet. Stanovená doba je výsledkem výpočtu výrazu, a může se proto libovolně měnit. Procedurou proto můžete časovat dynamicky s proměnlivými periodami.

Do procedury můžete zapsat vlastní časovací smyčku, která postupně bude podle různých (vašich) pravidel vykonávat nejrůznější operace. Vezměme následující příklad (zase mírně předbíhám, procedury jsou posány až v kapitole Programování a procedury — OCL, datové elementy v kapitole Datové elementy a výrazy):

    var
      Signal = boolean, false;
      Period = real, 2;
    end_var;

    instrument

      meter Display;
        timer = 0.05;
        ...
        mode = flow_graph;
        history = 100;

        procedure OnActivate();
        begin
          if Signal then
            Display.SetValue( 75 );
          else
            Display.SetValue( 25 );
          end;
        end_procedure;

      end_meter;

      program Rectangle;
        timer = infinite;

        procedure OnActivate();
        begin
          loop
            Signal = true;
            pause Period / 2;

            Signal = false;
            pause Period / 2;
          end;
        end_procedure;

      end_program;

    end_instrument;

Přístroj Display je časován periodicky a ukazuje v grafu dlouhém 100 vzorků (tedy 5 sekund) vývoj hodnoty proměnné Signal. Důležitější (a zajímavější) je přístroj Rectangle. Tělo jeho procedury OnActivate() obsahuje nekonečnou smyčku (loop..end), kterou přístroj neustále prochází a opakovaně tak vykonává čtyři příkazy: nastaví proměnnou Signal na true, počká 1 sekundu (Period / 2), nastaví proměnnou Signal na false a zase počká 1 sekundu. Vidíte, že se střídavě sekundu co sekundu překlopí proměnná Signal ze stavu aktivního do stavu neaktivního a naopak. Zajímavé je dále:

- Přístroj má časovač infinite. To znamená (jak bylo popsáno u relativního časování), že jej systém při startu aplikace rozběhne — provede se první časový krok (zkuste časovač zrušit a uvidíte, že přístroj nepoběží). Tím se umožní, aby se procedura dostala do nekonečné smyčky — a dále se již systém o přístroj nemusí (a nebude) starat.
- Příkaz pause ukončuje časový krok přístroje. To znamená, že přístroj, ačkoli běží v nekonečném cyklu(!), sám sebe časuje. Časování je přitom stejně efektivní jako časování systémové, zkuste se podívat do "Okna časování" na počet časových kroků přístroje Rectangle. Bude jeden za sekundu.
- Formální nekonečnost cyklu (v tomto případě) neimplikuje nekonečnost běhu aplikace. Příkaz pause přerušuje běh procedury a dává tak prostor ostatním přístrojům.
- Délka čekání je proměnlivá, neboť příkaz pause svůj výraz vyhodnocuje vždy. Snadno proto můžete změnou proměnné Period dosáhnout změny časování celého přístroje, a tím i změny (zrychlení nebo zpomalení) generovaného signálu.
- Popsaný mechanizmus pracuje obecně a klidně můžete v aplikaci mít podobně zkonstruovaných procedur několik. Navíc, pokud budete místo nastavování proměnné posílat zprávy přístrojům, budete dynamicky časovat i je.

Ukázka je samozřejmě pouze ukázka, a nepokryje všechny možné varianty, zápis algoritmu je zcela obecná věc. Například jsme se vůbec nepokusili upravit výrazy příkazu pause — tím bychom měnili střídu generovaného signálu. Vyzkoušejte si to.

Časování procedur nejspíše nebude příliš často používáno. Jednak proto, že většinou postačí použití některého jednoduššího způsobu časování a jednak proto, že může být ve složitějších situacích dosti obtížné celý problém včetně komunikací pochopit a analyzovat tak, aby vše pracovalo správně (problém domyšlení všech souvislostí). Na druhé straně, pokud budete procedurou pouze časovat (nebudete v ní komunikovat ani pracovat s daty), můžete velmi jednoduše dosáhnout velmi složitého dynamického časování — podobně jako v naší ukázce.

Nakonec poznámka: příkaz procedury pause není totéž co wait. Příkaz wait čeká na splnění podmínky maximální rychlostí (a navíc beztak neobsahuje žádný časový údaj), a je proto pro časování procedurou nepoužitelný.

## Časování zevnitř

Doposud jsme hovořili o obecných principech časování, o principech časování systému Control Web a o způsobu časování přístrojů. Ve všech případech jsme hovořili (abstraktně) o "systému, který časuje" nebo o "jádru, které obvolává přístroje". Je to zatím tajemná část aplikace, která je odpovědná za správnou komunikaci, správný běh přístrojů a správnou synchronizaci dat. Dále ji budeme nazývat jádro, které spolu s časovacím tokem odpovídá za veškeré časování a aktivitu aplikace.

Na rozdíl od časovacího toku pracuje jádro ve výkonném prováděcím toku, a je proto postaveno na roveň všem ostatním normálním tokům přítomným v operačním systému. Bez zvýšení priority celého procesu tedy veškeré přístroje, jejich kreslení a reakce na události, ovladače a komunikace pracují konkurenčně se zbytkem systému. To v principu nijak nevadí, protože čas, který přístroje spotřebují, žádná priorita procesu neovlivní.

Výkonný časovací tok je v systému Control Web jeden společný pro všechny spuštěné moduly (pokud jich je více). I zde je v principu jedno, jestli přístroje různých modulů pracují v jednom nebo více tocích, neboť souhrnný jimi spotřebovaný čas se rozdělením do více toků nijak nezmenší. Naopak, jeden tok znamená menší režii operačního systému a lepší vzájemné ovlivňování chodu přístrojů z různých modulů, což v důsledku vyúsťuje v hladší běh a lepší pocit z ovládání.

### Co je to časový krok

V oddíle o časování přístrojů byl pojem časový krok používán ve významu jednoho elementárního spuštění přístroje. V oddíle Časování zevnitř bude používán druhý význam tohoto pojmu — časový krok bude jeden elementární běh jádra systému, během něhož se uskuteční vstupní i výstupní komunikace a provedou časové kroky (už je tu opět první význam) přístrojů, které měly být spuštěny. Pro větší bezpečnost budu používat (kde to jen půjde) rozlišení "časový krok jádra" a "časový krok přístroje".

Časový krok jádra může být v různých okamžicích aplikace různě dlouhý — rozdíly mohou dosahovat až několika řádů (!). Vše závisí pouze na aktuálních akcích (komunikacích především), které se v kroku provádějí. Ve většině aplikací se dokonce délky kroků střídají — zpravidla nejprve přijde krok dlouhý, způsobený periodickými časovači (v něm se většinou komunikuje), a po něm následuje krok krátký, ve kterém se "dodělávají" přístroje, které byly aktivovány událostmi z přístrojů v kroku dlouhém (krátký krok většinou nekomunikuje, proto je krátký).

Délka časového kroku jádra je samozřejmě důležitý informační údaj. Control Web proto změřené údaje uchovává a zobrazuje je v "Okně časování". Délka časového kroku jádra již byla jednou přesně definována (při popisu údaje "Celkový spotřebovaný čas" "Okna časování"), nebylo však řečeno, že to je délka časového kroku. Proto délku definuji znovu — délka časového kroku jádra je interval mezi probuzením časovacího toku a dalším testem na případný možný jeho spánek (čekání na další krok). Součástí této délky je samotný běh jádra, běh přístrojů, veškeré režie, komunikace a případně vyprazdňování vstupní fronty událostí. Sečtené délky jednotlivých časových kroků jádra dohromady dávají "Celkový spotřebovaný čas".

"Okno časování" zobrazuje o časovém kroku jádra celou řadu informací:

- "Časové kroky" — řádek obsahuje hned několik údajů najednou. Nejdříve je zobrazena délka časového kroku nejrychleji časovaného přístroje. Další číslo zobrazuje celkový počet časových kroků jádra, které systém uskutečnil od startu aplikace (postupem toto číslo narůstá a narůstá). Jako poslední je v řádku zaznamenán aktuální počet kroků jádra za sekundu. Protože tento počet není průměrný ukazuje velmi přesně skutečný počet právě probíhajících kroků.
- "Průměrná délka časového kroku" — "Celkový spotřebovaný čas" vydělený počtem časových kroků. Údaj ukazující dlouhodobou průměrnou spotřebu času jednotlivých časových kroků jádra.
- "Průměrná rezerva časového kroku" — časovací tok po dokončení kroku jádra může určitou dobu čekat na další časový krok (nebo událost). V aplikacích, které pracují s rezervou, to je běžná věc. Zobrazený údaj ukazuje dlouhodobou průměrnou délku prodlev mezi časovými kroky. Procenta ve druhém sloupci udávají vzájemný poměr délky a rezervy.
- "Okamžitá délka časového kroku" — poslední známá délka časového kroku jádra.
- "Okamžitá rezerva časového kroku" — poslední známá rezerva časovacího toku. "Okamžité" údaje zobrazují (na rozdíl od průměrných) aktuální stav časování. Na okamžitých údajích uvidíte, jak aplikace pracuje v současném okamžiku, jak zatěžuje systém zrovna teď. Procenta opět vymezují vzájemný vztah rezervy a délky kroku jádra.

Popisované údaje jsou navzájem svázány i jinak.

Například:

- Procentuální poměr u průměrné délky časového kroku odpovídá (i když vzniká z jiných údajů) poměru "Času běhu" a "Času od rozběhu aplikace"
- Pokud součet délky a rezervy vynásobíte počtem kroků za sekundu, dostanete v ideálním případě číslo 1 (obyčejně se však součin bude jedničce pouze blížit).
- Je-li aplikace ve skluzu, odpovídá poměr délky nejkratšího kroku přístroje a průměrné délky kroku jádra přibližně podílu dosaženého času a času od rozběhu aplikace.

### Skluz

Nastane-li na konci jednoho běhu časovacího toku situace, kdy je nově vypočtěný okamžik vzbuzení toku (neboli "Čas aplikace") pozadu za systémovým časem, říkáme, že je aplikace ve skluzu. Skluz vznikne tehdy, trvá-li některý z časových kroků jádra příliš dlouho. Časovací tok při skluzu možnou časovou rezervu nejen vyčerpá, ale také ji i překročí a spotřebuje část času, který již měl patřit novému časovému kroku. Aplikace ve skluzu nemůže dodržet správné intervaly period — příliš dlouhé trvání časového kroku jádra jí v tom brání.

Skluz je normální součástí běhu aplikace, a téměř v každé se občas objeví. Systém se snaží skluz vyrovnat, snaží se "dohnat" skutečný čas, pracuje "zvýšeným úsilím" a jednotlivé zpožděné časové kroky jádra uskutečňuje tak rychle, jak to jen jde. Skluz bývá okamžitou událostí, která většinou rychle pomine, a dohánění proto většinou splní svůj účel — skluz se vyrovná. Nicméně, chybně navržená aplikace nemá rezervu, časové kroky trvají soustavně déle, než je v aplikaci naprogramováno, a ani dohánění tudíž situaci nespraví. Taková aplikace má nereálné požadavky a neměla by být provozována.

Skluz by bylo možné v okamžiku jeho vzniku rozeznat v časovacím okně tak, že by součet okamžité délky kroku a okamžité rezervy překročil délku nejmenšího časového kroku. Jinými slovy, krok jádra by byl delší, než měl být. V okně časování se okamžitě skluz projeví také na dosaženém času aplikace, který se začne zpožďovat za časem od rozběhu. V hrubém přiblížení je možné pomocí podílu údaje "Rozdíl" a délky nejkratšího kroku zjistit, kolik časových kroků jádra chybí, kolik jich systém bude muset provést, aby skluz vyrovnal. Skluz také způsobí vynulování okamžité rezervy, veškerý čas bude spotřebován na běh aplikace. Při skluzu se situace může dále vyvíjet třemi způsoby:

- Následující časový krok jádra trvá méně než rozdíl délky nejkratšího kroku přístroje a skluzu. Jinými slovy, v době do počátku dalšího (třetího) kroku jádra systém stihne dva kroky — krok, kterým vyrovná skluz a krok následující. Skluz nevyčerpá rezervu vymezenou možnou délkou kroku. Skluz pomine.
- Součet skluzu a délky následujícího kroku sice přesáhne nejkratší délku kroku, ale o méně než je aktuální skluz. Délka skluzu se zmenší, aplikace dohání.
- Součet skluzu a délky následujícího kroku přesáhne nejkratší délku kroku, ale o více než je aktuální skluz. Délka skluzu se zvětší, aplikace nedohnala nic, naopak, ještě se jí přitížilo.

Je-li skluz delší než nejkratší délka kroku přístroje, nemůže nastat první situace, a systém musí skluz vyrovnat pomocí několika časových kroků jádra. Dohánějící jádro tudíž běží rychleji, takže také rychleji časuje jednotlivé přístroje. Během skluzu proto systém nezachovává délky period. Je to nutné opatření, protože byla-li perioda jednou delší (v okamžiku vzniku skluzu), musí být jedna, nebo více dalších period kratší, aby další časové kroky přístroje (po vyrovnání skluzu) nastaly v původních teoretických vypočítaných okamžicích. Pokud se tento mechanizmus zdá býti podivným, je to jen další argument pro tvrzení, že aplikace musí být navržena tak, aby ke skluzu nedocházelo. Když už skluz jednou vznikne, tak je pozdě lamentovat, a nezbývá nic jiného, než se ze skluzu zotavit doháněním.

Skluz vznikne v okamžiku, kdy se některý časový krok jádra protáhne, a nestihne se kvůli tomu časový krok přístroje s nejkratší periodou časování. Prodloužení kroku jádra může být i takové, že utečou časové kroky přístrojů s delší periodou. Control Web proto rozeznává skluz aplikace a skluz přístroje. Skluz aplikace vznikne, když se alespoň jeden z přístrojů dostane do skluzu. Aplikační skluz je důležitější, protože zahrnuje všechny přístroje, a citlivější, neboť registruje i přístroj s nejkratším časovým krokem. Některé přístroje se do skluzu nemusejí vůbec dostat, je-li například přístroj časován s periodou 86 400 sekund (1 den), postihne jej skluz jen s malou pravděpodobností (skluz by musel vzniknout těsně před okamžikem aktivace tohoto přístroje).

Skluz přístroje i aplikace je možné detekovat pomocí systémové událostní procedury OnActivate( ActivateMode : cardinal ) (popis programování procedur obsahuje kapitola Programování a procedury — OCL:

    procedure OnActivate( ActivateMode : cardinal );
    begin
      if bitget( ActivateMode, 8 ) = 1 then
        ... (* aplikace je ve skluzu *)
      end;
      if bitget( ActivateMode, 5 ) = 1 then
        ... (* přístroj je ve skluzu *)
      end;
    end_procedure;

Parametr ActivateMode obsahuje v jednotlivých bitech i různé jiné informace (více je o proceduře OnActivate napsáno v kapitole Programování a procedury — OCL, nás momentálně zajímá jen bit 8, který nese informaci o skluzu aplikace a bit 5 s informací o skluzu přístroje.

Pracuje-li aplikace ve skluzu, nemůže až do okamžiku jeho zániku přesně plnit časovací kritéria. Časové kroky přístrojů se zpožďují vůči teoretickým hodnotám a periody jsou delší než by měly být. Dlouhodobý skluz je v rozporu s požadavky kladenými na aplikace reálného času — aplikace již nemá rezervu, kterou by mohla použít pro překlenutí potenciálních časovacích potíží. O takové situaci systém Control Web musí uživatele informovat, protože aplikace nepracuje podle představ jeho návrhu. Dlouhodobý skluz je považován za chybu časování, která je oznámena speciálním dialogovým oknem:

Chyba časování

a je zapsána do záložky "Chybové zprávy" "Okna zpráv". Systém chybu časování hlásí v případě, že po určitou dobu skluz aplikace neklesl. Prodleva hlášení této chyby je nastavitelná pomocí parametru time_error_limit v aplikační sekci settings v rozmezí od 0 do infinite, přičemž 0 znamená okamžité hlášení chyby, jakmile vznikne skluz, a infinite potlačení hlášení chyby časování (systém chybu časování nikdy nenahlásí).

V aplikacích pevného reálného času je chyba časování považována za natolik závažnou, že při jejím objevení (po uplynutí intervalu vymezeného parametrem time_error_limit) dojde k chybě běhu a systém Control Web modul zastaví.

Aplikace může být navržena z hlediska skluzu různými způsoby:

- Skluz vzniká ihned po startu aplikace a nezmenšuje se. To je nejhorší případ, který by neměl vůbec nastat. Nabízí se srovnání s jízdou z kopce v automobilu, jehož brzdy nestačí ani na zpomalení zrychlování. Aplikace pracující tímto způsobem je špatná.
- Skluz vzniká v okamžicích nahuštění činnosti více přístrojů (například v okamžicích přelomu celých hodin nebo zpracování většího množství přijatých dat) a po odeznění tohoto nahuštění skluz zaniká; aplikace na skluz nijak nereaguje, je pasivní. Pokud není skluz na závadu, může taková aplikace bez problémů pracovat. Může-li skluz aplikaci způsobit nějaké potíže (případně přejete-li si jej pouze odstranit) je možné pouvažovat nad rozfázováním běhu přístrojů pomocí absolutního časování. Pasivita aplikace v sobě skrývá určitá rizika, která souvisejí s okolím systému Control Web — s ostatními aplikacemi, které mohou v operačním systému běžet. Hypoteticky může nastat třeba takováto situace: při rozběhu aplikace bylo všechno v pořádku a skluz nenastával, protože nikdo nepožadoval po databázovém serveru žádná data. Jakmile však začal normální databázový provoz, počítač se více zatížil a aplikace se rázem přesunula do první skupiny špatných aplikací běžících s trvalým skluzem. Podobné potíže se mohou objevit také v případě, že během testování a vývoje nikdy nenastanou skutečné reálné podmínky — hustá komunikace nebo velký počet požadavků na vestavěné httpd servery (zkrátka na to programátor nepomyslel. Proto se velmi vyplatí aplikaci navrhovat pro nejhorší případ a velmi se vyplatí aplikaci důkladně otestovat v reálném provozu.

Pasivní aplikace se nemohou skluzu bránit, a neměly by proto nikdy běžet v režimu pevného reálného času.

- Skluz vzniká stejně jako v druhém případě, ale aplikace obsahuje mechanizmy, které v případě skluzu "povolí" a skluz tak rychleji zanikne. Aplikace na skluz reaguje aktivně. Mechanizmus vzniku skluzu umožňuje aplikaci reakci na skluz škálovat. Stále narůstající skluz totiž postupně systém zahlcuje a "stahuje" postupně přístroje s delším a delším časovým krokem. Aplikace proto může obsahovat například několik přístrojů s časováním "0.1", "1", "10" a "100", které budou reagovat na svůj (přístrojový) skluz stále silnějšími prostředky (vypínat komunikaci, časování nebo archivace). Aktivní (dalo by se říci až inteligentní) aplikace se sama stará, aby pracovala korektně, je bezpečná, a je proto použitelná i pro běh v režimu pevného reálného času.

Občas se přihodí, že aplikace pracuje "na hraně" mezi prvním a druhým případem. Jeden z projevů těchto aplikací je celkem matoucí. Pokud aplikace spustíte bez pevného reálného času, dostane se ihned po startu do skluzu, a již se z něj nedostane. Patří tedy do skupiny první. Pokud aplikaci spustíte v režimu pevného reálného času, aplikace se při startu do skluzu nedostane a pracuje jako aplikace ze skupiny druhé. Matení spočívá ve faktu, že se zdá, že pevný reálný čas aplikaci nějak pomohl a že aplikace lépe běží. Není to pravda, naopak, zapnutí pevného reálného času (a vymizení skluzu) maskuje potíže a vytváří menší časovanou nálož. Velký nárůst skluzu při startu aplikace je způsoben velkým množstvím požadavků na kreslení — při startu se celá aplikace musí nakreslit. Víme již, že kreslení probíhá prostřednictvím fronty zpráv, kterou operační systém plní a aplikace vyprazdňuje — dokresluje. Toto prvotní překreslení může trvat relativně dlouho a může proto způsobit vznik skluzu. Zapnutí pevného reálného času zablokuje zpracování vstupní fronty, neobjeví se zdržení a skluz nevznikne. Časovaná nálož se projeví okamžitě, kdy se aplikace bude muset celá najednou překreslit — najednou odkryjete celou její plochu nebo operační systém překreslí všechna okna (to občas dělává). Vznikne kopie situace při startu a aplikace se dostane do skluzu, ze kterého se nemusí být schopna dostat. Aplikace takto vytvořená, používající pevný reálný čas pro "zodolnění" proti potížím, je špatná.

### Průběh časového kroku jádra

Každý jeden časový krok jádra musí zajistit několik spolu souvisejících činností.

- Primární je aktivace přístrojů, neboli vlastní pohánění aplikace.
- Přístroje pro svou práci potřebují data z technologie (reprezentovaná kanály). Jádro musí zajistit jejich dostupnost, musí je komunikovat.
- Výsledkem práce přístrojů je změna řídicích signálů, které je třeba přenést zpět do technologie.

Popsané úkoly — aktivaci přístrojů a komunikaci — jádro plní podle jednoznačně definovaných jednoduchých protokolů — na straně ovladačů je protokol zapouzdřen do několika procedur (podrobný popis viz kapitola Komunikace, ovladače a kanály) jejich rozhraní, na straně přístrojů je protokol skrytý uvnitř systému a je realizován pomocí metod objektů přístrojů. Jádro pracuje jako realizátor příkazů časovacího toku, který zprostředkovává vzájemnou komunikaci mezi aplikací (přístroji) a ovladači (technologií):

Schéma časování

Časovací tok před začátkem časového kroku připraví seznam přístrojů, které se mají dostat ke slovu, a rozběhne jádro. Jádro začne realizovat své činnosti a cyklicky pracuje tak dlouho, dokud neuspokojí všechny požadavky připravených přístrojů. V prvém přiblížení je jasné, že jádro musí:

1. zjistit, jaké vstupní kanály jednotlivé přístroje potřebují (příprava)
2. změřit připravené kanály
3. aktivovat přístroje
4. zapsat (komunikací) výsledky práce přístrojů

#### Příprava

Příprava dat je fáze, ve které jádro spolupracuje s přístroji. Přístroje, které neobsahují procedury, jsou schopny jádru informace o všech kanálech, které potřebují, poskytnout najednou. Přístroje s procedurami (a časovače) toho schopny nejsou, a jak uvidíme později, pracují komplikovaněji.

#### Měření

Druhá fáze — měření kanálů — následuje bezprostředně po fázi první. Jádro nyní spolupracuje s ovladači, kterým nejdříve oznámí všechny kanály, které si přeje změřit. Následuje krok potvrzovací, kdy jádro postupně pro všechny kanály zjišťuje, jestli je ovladač úspěšně změřil. Odpoví-li ovladač kladně (kanál změřil), uschová jádro změřenou hodnotu ve své datové oblasti. Odpoví-li ovladač záporně, jádro si zapamatuje, že kanál ještě nebyl změřen. Potvrzování dokončení měření skončí ve chvíli, kdy se jádro zeptá ovladače na poslední požadovaný kanál.

Běh jádra se může po dokončení potvrzování ubírat dvěma cestami:

- Jádro nemá zapamatován žádný nezměřený kanál a přechází přímo k aktivaci přístrojů.
- Některý z kanálů dosud nebyl změřen, jádro začíná čekat na dokončení měření.

Čekání na dokončení měření je důležité, neboť bez něj by přístroje pracovaly se špatnými — starými hodnotami kanálů. Jádro musí počkat, až ovladač data poskytne. Zpoždění způsobuje komunikace ovladače s měřicím zařízením (snímačem). Jak uvidíte v kapitole Komunikace, ovladače a kanály, mohou být délky komunikací různých ovladačů velmi odlišné. Měřicí karta zasunutá přímo do počítače bude data poskytovat mnohem rychleji než průmyslový automat komunikující po sériové lince.

V průběhu čekání na dokončení měření se jádro chová pasivně. Veškerá aktivita leží na bedrech ovladače, který sám musí v případě doměření systém informovat. (prostředky, které ovladač musí v takovém případě použít popisuje kapitola Komunikace, ovladače a kanály). Jinými slovy, jádro během čekání nic nedělá, nespotřebovává žádné systémové prostředky, a teprve když mu ovladač oznámí, že změřil data, probudí se a zpracuje doměřené kanály.

Daří-li se komunikovat, je všechno v pořádku. Ovladač po určité době všechna změřená data poskytne jádru a to pokračuje aktivací přístrojů. Komunikace se však může nedařit. Mohou se vyskytnout potíže na komunikační lince, průmyslový automat selže, případně pouze vypnou v technologii proud. Ovladač není schopen data jádru předat (nemůže žádná změřit), jádro nemůže pokračovat a aplikace přestává vizualizovat a řídit. Systém sice reaguje na vstupní události (operace s myší a klávesnicí), ale aplikace stojí. Aby se předešlo popsanému zastavení aplikace, definuje Control Web v aplikaci nejdelší povolenou dobu čekání na měření — parametr input_timeout aplikační sekce settings. Jádro nikdy nečeká na odezvy ovladačů déle, než má tímto parametrem povoleno. Celý postup jádra při měření kanálů ukazuje obrázek:

Měření kanálů

Komunikační prodleva samozřejmě může sloužit i k jiným účelům než je ochrana před nekončícím měřením. S její pomocí můžete efektivně omezovat nejdelší dobu komunikace, například v aplikacích, kde je řízení s použitím starých hodnot menším zlem, než řízení zpožděné. Délka prodlevy je stavitelná od nuly (jádro nikdy nečeká a okamžitě po zapsání požadavků do ovladače pokračuje aktivací přístrojů bez ohledu na výsledek měření) až do "nekonečna" (infinite), kdy jádro vždy čeká až do okamžiku doměření posledního kanálu. Hodnota 0 znamená minimální zdržení běhu časového kroku jádra a vysokou pravděpodobnost práce se starými hodnotami kanálů, hodnota nekonečno znamená naopak stoprocentní jistotu aktuálnosti dat za cenu možného velmi dlouhého čekání na výsledek.

Je vhodné ještě chvíli zůstat u zdůrazněných slov předchozího odstavce — nejdelší doba komunikace. Ve většině případů jádro od ovladačů dostane změřená data dříve, než uplyne definovaná prodleva. Jádro pozná, že již byly všechny kanály korektně předány, a čekání ukončí. Definovaná prodleva tedy stanovuje horní mez, která většinou není dosažena, ale která není nikdy překročena.

Nastane-li situace, kdy se ovladači nepodaří požadované kanály změřit do vypršení prodlevy, pokračuje jádro dále. Ovladač přitom stále pracuje (na pozadí), komunikuje a stále je schopen poskytovat výsledky. Jádro v takovém případě informace od ovladačů pouze registruje a při vhodné příležitosti (buď na konci časového kroku jádra nebo při měření kanálů nově požadovaných při postupné aktivaci přístroje — viz níže) je zpracuje. Ovladač tedy může komunikovat svou rychlostí a jádro jeho výsledky použije při nejbližší volné chvilce.

Ne všechny kanály jsou stejně důležité. Některé musí být skutečně vždy změřeny, jiné klidně mohou zastarat. Vzniká problém, jak prodlevu nastavit, aby vyhověla pro všechny případy. Řešení problému je velmi rychlé — s jednou hodnotou prodlevy nevystačíte. Systém Control Web proto umožnuje u každého kanálu prodlevu definovat samostatně. Kanály, které se musejí vždy změřit, budou mít prodlevu větší, kanály, na kterých "nezáleží" menší (nebo nulovou). Definice prodlevy přímo u kanálu má přednost před definicí v sekci settings. To znamená, že kanál použije buď prodlevu svou (je-li definovaná), nebo prodlevu systémovou (kanál je definován bez prodlevy). V nejširším pojetí se nabízejí dvě základní strategie definic prodlev:

- Systémová prodleva se nastaví na nulu, čímž se čekání na doměření vypne. Důležitým kanálům se prodleva přiřadí přímo v definici, takže na jejich měření bude systém vždy čekat.
- Systémová prodleva se nastaví na nenulovou hodnotu, což způsobí všeobecné čekání na dokončení měření. Nedůležitým kanálům se prodleva nastaví na nulu (nebo jinou hodnotu), takže na jejich měření systém nebude čekat.

Sejdou-li se v jednom časovém kroku jádra kanály s různými komunikačními prodlevami, vybere jádro pro čekání prodlevu nejdelší. Uvážíme-li, že délka prodlevy u kanálu vyjadřuje přibližně jeho důležitost, je to výběr logický. Přístroje jsou v časovém kroku jádra aktivovány nejpozději tehdy, je-li vyčerpána největší možná komunikační prodleva.

Již víte, že prodlevu je možné nastavit globálně pro všechny kanály nebo jednotlivě pro vybrané kanály. Kromě těchto způsobů může vaše aplikace použít dynamického řízení komunikačních prodlev — pomocí atributu timeout (o atributech pojednává kapitola Datové elementy a výrazy). Zápisem hodnoty prodlevy do atributu okamžite upravíte chování měření kanálu (okamžitě od dalšího následujího měření). V běžných aplikacích pravděpodobně vystačíte se statickými definicemi prodlev, nicméně i tak máte přesné dynamické řízení stále k dispozici.

Poslední způsob čekání na výsledek komunikace, který systém poskytuje, je nejvíce expertní a bude používán velmi výjimečně — čekání s využitím stavových informací kanálu. Toto čekání je uskutečnitelné pouze tehdy, má-li kanál nastavenu nulovou prodlevu (tehdy na jeho doměření jádro nečeká). Aplikace může po vzniku požadavku sledovat, jak se mění stav komunikace (pomocí atributu status) a v okamžiku jejího dokončení pokračovat dále.

S prodlevami a měřením kanálů souvisí jedna potenciálně nepříjemná věc. Využití prodlev v aplikaci mlčky předpokládá, že použitý ovladač odpovídá specifikacím a správně obsluhuje komunikaci svých kanálů. Ovladače specifikacím samozřejmě musí odpovídat (specifikace nejsou nijak komplikované) a drtivá většina jim také odpovídá. Nicméně, ovladač může být buď z neznalosti nebo ze spekulativních důvodů napsán chybně tak, že simuluje okamžité změření hodnoty. To pochopitelně znamená, že jádro na fyzické změření nikdy nepočká. Nemůže, neboť je ovladačem obelháno. O této chybě ovladače se můžete více dočíst v kapitole Komunikace, ovladače a kanály.

Systém Control Web za běhu aplikace o komunikaci průběžně shromažďuje různá statistická data. Takto získané údaje je možné prohlédnout v "Okně časování", přičemž souhrnné údaje o komunikaci obsahuje záložka "Ovladače" a údaje o jednotlivých samostatných kanálech záložka "Kanály". O průběhu komunikace vypovídají následující údaje:

- Záložka "Ovladače" je v horní části rozdělena na "čtení" a "zápis". Obě sekce obsahují čtyři vzájemně si odpovídající údaje:

- "Požadavky na čtení/zápis" — celkový počet všech požadavků na komunikace uskutečněné prostřednictvím vybraného ovladače. Údaj je souhrnem všech požadavků na jednotlivé samostatné kanály.
- "Přečteno/Zapsáno do timeoutu" — celkový počet požadavků, které ovladač stihnul úspěšně vyřídit v čase vymezeném komunikační prodlevou. Komunikace, které nebyly dokončeny do vypršení prodlevy, zde nejsou započítány. S rostoucí délkou prodlevy se tento údaj zvětšuje — roste poměr komunikací, které se dokončí během čekání na výsledek. Nastavíte-li komunikační prodlevu na nulu, měl by i tento údaj klesat k nule (pokud údaj k nule neklesá, tak ovladač buď data skutečně poskytne okamžitě — například je čte přímo z měřicí karty, nebo je tak speciálně nakonfigurován — to umí například ovladač DDE, a nebo si úspěšnou komunikaci pouze vymýšlí).
- "Počet chyb při čtení/zápisu" — počet komunikací, které skončily chybou (chybu komunikace rozpoznává a jádru oznamuje sám ovladač). Komunikační chyby se zapisují do "Okna zpráv" a do diagnostických údajů jednotlivých kanálů.
- "Poslední chyba čtení/zápisu" — pokud při komunikaci nastala chyba, obsahuje tento údaj její kód.

Kromě údajů rozdělených podle směru komunikace záložka obsahuje také časové informace o komunikaci:

- "Čas od poslední komunikace" — časová vzdálenost od okamžiku dokončení poslední úspěšné komunikace.
- "Průměrná doba komunikace" — průměrná hodnota délky intervalu vymezeného zápisem požadavku do ovladače a dokončením komunikace. Pokud je komunikační prodleva kratší, než je tento údaj, nestihne se část komunikací dokončit během čekání na výsledek, a přístroje ve svém časovém kroku mohou pracovat se starou hodnotou.

Připomínám, že údaje v této záložce platí souhrnně pro všechny kanály vybraného ovladače. Proto například "Průměrná doba komunikace" představuje pouze orientační údaj. Přesné (neprůměrované) hodnoty jsou k dispozici v údajích záložky "Kanály".

- Záložka "Kanály"

- "Poslední chyba" — údaj zobrazuje poslední chybu komunikace vybraného kanálu. Údaj je dostupný také jako atribut error kanálu.
- "Požadavky na komunikaci" — počet požadavků na komunikaci kanálu. Údaj je dostupný v atributu requests.
- "Ukončeno do timeoutu" — počet komunikací kanálu, které byly vyřízeny před uplynutím komunikační prodlevy. Čím větší prodleva bude, tím větší bude i tento údaj. Hodnota údaje je dostupná v atributu hits kanálu.
- "Timeout" — aktuální hodnota komunikační prodlevy, která se použije při komunikaci kanálu. Hodnotu prodlevy je možné číst (i zapisovat) pomocí atributu timeout.
- "Čas od poslední komunikace" — časová vzdálenost od okamžiku dokončení poslední úspěšné komunikace vybraného kanálu.
- "Průměrná doba komunikace" — průměrná hodnota délky intervalu vymezeného zápisem požadavku komunikace kanálu do ovladače a dokončením jeho komunikace. Průměrná doba komunikace je dlouhodobý údaj a ukazuje typickou dobu komunikace kanálu. Údaj je dostupný prostřednictvím atributu rtt.
- "Okamžitá doba komunikace" — okamžitá délka komunikace kanálu. Na rozdíl od průměrné doby komunikace tento údaj ukazuje právě aktuální rychlost komunikace a umožňuje tak nahlédnout na právě aktuální stav ovladače.

O atributech, na které se text odkazuje, se můžete dočíst také v kapitole Datové elementy a výrazy.

#### Aktivace

Jakmile jádro úspěšně dokončí měření vstupních kanálů, případně jakmile uplyne komunikační prodleva, přijdou na řadu přístroje — přesněji jejich aktivace. Aktivace přístroje znamená, že přístroj provede svůj časový krok. Aktivace přístrojů není ovlivňována žádnými speciálními parametry (tak jak bylo například ovlivňováno měření prodlevami) a vše je řízeno jen postupnou interakcí jádra a samotného přístroje.

Přístroje jsou aktivovány jádrem sekvenčně, přičemž není možné, aby se přístroj aktivoval dříve, než předcházející přístroj dobrovolně ukončí svůj časový krok. Toto pravidlo zamezuje vzájemnému skrytému (a tudíž špatnému, protože neovlivnitelnému) paralelnímu běhu přístrojů. Již bylo naznačeno, že přístroje mohou být dvojí: "jednoduché", které vědí jaké vstupní kanály chtějí, a "komplikované" (lepší by bylo říci promyšlené), které to nevědí, a musejí měřené kanály postupně zjišťovat. Postupné zjišťování informací o požadovaných kanálech je přímým důsledkem optimalizace komunikací v přístrojích — optimalizace vám umožňuje v jedné proceduře jednou tisíc kanálů měřit a podruhé zase neměřit. "Komplikované" přístroje jsou všechny přístroje s nějakou procedurou a časovače. "Jednoduché" přístroje jsou všechny ostatní. Podle druhu přístroje jádro při aktivaci postupuje následovně:

- "Jednoduché" přístroje jsou aktivovány a po návratu řízení zpět do jádra se bezprostředně pokračuje dalším přístrojem nachystaným k aktivaci.
- "Komplikované" přístroje jsou také aktivovány, ale po návratu řízení zpět jádro zjišťuje, co se stalo. Přístroj může svůj časový krok ukončit a tehdy se pokračuje v aktivaci dalšího přístroje. Přístroj ale také může připravit kanály, které si přeje před pokračováním aktivace změřit. Jádro tedy požadované kanály změří a opětovně přístroj aktivuje. Tento cyklus trvá tak dlouho, dokud přístroj požaduje měření nových kanálů. Během těchto cyklů aktivací jednoho přístroje nekončí časový krok přístroje, a tudíž ani časový krok jádra jádra.

Z druhého bodu ("komplikované" přístroje) vyplývá několik důležitých skutečností:

- Jeden kanál může být přístrojem požadován vícekrát (například napíšete-li v proceduře jeden kanál do podmínek dvou příkazů if). Platnost hodnoty kanálu je v systému Control Web vztažena k jednomu časovému kroku jádra, což znamená, že hodnota jednou změřená nebude opětovně v tomtéž kroku jádra komunikována. Připomeňme si, že cykly aktivací neukončují časový krok jádra, takže všechny přístroje aktivované v jednom časovém kroku budou pracovat se shodnými hodnotami kanálů — s jednou výjimkou — pokud ovladač nestihl kanál změřit během komunikační prodlevy, pracují přístroje se starou hodnotou do okamžiku, než ovladač doměří hodnotu novou. Jádro v takovém případě novou hodnotu akceptuje a hodnota kanálu se tak může změnit v průběhu aktivací ze staré na novou. Nová hodnota už ovšem bude v daném časovém kroku jádra poslední.
- Příkazy procedur pause, wait a yield přerušují běh procedury a ukončují časový krok přístroje. Procedura po vykonání jednoho z uvedených ukončovacích příkazů znova poběží až v některém z dalších časových kroků jádra. Hodnoty kanálu použitého v proceduře před i za uvedenými příkazy se proto mohou lišit (v různých krocích jádra mívají kanály různé hodnoty).
- Přístroj ve své aktivaci může kromě vstupních kanálů připravit také kanály výstupní. O těch jsme zatím nehovořili (ale už to začíná být nutné). Uvažme následující situaci: přístroj během první aktivace požaduje nový vstupní kanál a navíc na jiný výstupní kanál zapíše hodnotu. Jádro mu vstupní kanál změří a přístroj je opětovně aktivován. V zápise procedury je již výstupní kanál zapsán. Fakticky se tak ale ještě nestalo, a vzniká rozpor "chtěného" a "skutečného". Uvážíme-li, že zápis výstupního kanálu do řídicího zařízení mohl ovlivnit nově čtený vstupní kanál, vyplyne jasně, že takové chování systému je chybné. Při každém přerušení aktivace přístroje z důvodu požadavku měření nových kanálů jsou proto nejprve vyřízeny nasbírané výstupní požadavky. Podobně, jako se vstupní kanály postupně měří, tak se výstupní kanály postupně zapisují. Motivace postupného zápisu je však jiná — není třeba optimalizovat množství měření (jako u vstupních kanálů), ale je třeba zachovat logickou koherenci zápisu aplikace, dat ve vnitřních strukturách jádra, ovladači a technologii.
- Měření (i zápis) kanálů během přerušované aktivace používá stejný mechanizmus, který byl popsán při základní fázi měření. Pro komunikace během přerušených aktivací proto platí veškerá pravidla — počítání prodlev, čekání na výsledek i zpracovávání odezev ovladačů. Dodatečná komunikace během aktivací tudíž také může trvat nejvýše jen čas vymezený prodlevou.
- Fakt, že jádro neaktivuje další přístroj před koncem běhu jiného přístroje, může vést při chybě v proceduře (nekonečný cyklus) k zacyklení celé aplikace. Jádro s těmito eventualitami počítá a obsahuje vnitřní mechanizmy, které umožní alespoň ukončit aplikaci. (Jiná věc je, vyskytne-li se nekonečný cyklus například v ovladači, nebo v přístroji mimo proceduru. Tomu se samozřejmě jádro ubránit nedokáže.)

Souhrnně aktivaci jednoho přístroje demonstruje následující obrázek:

Aktivace přístroje

Stejně jako o časování, ovladačích a kanálech aplikace i o přístrojích shromažďuje statistická data. V "Okně časování" je přístrojům věnována samostatná záložka, z níž již část byla popsána (přímo v oddíle "Okno časování"). Zbývající zobrazené údaje jsou:

- "Časový krok" — řádek je složen ze dvou údajů. Nejdříve je zobrazena perioda časování přístroje (povšimněte si, že některé přístroje nemají periodu uvedenou, takové přístroje buď nejsou časovány vůbec, nebo jsou časovány časovačem a nebo jinak — asynchronně). Další údaj obsahuje celkový počet všech uskutečněných časových kroků přístroje. Je přitom lhostejné, jakým způsobem byly kroky vyvolány. Hovořilo se o mechanizmu přerušované aktivace, který umožňuje provést jeden časový krok přístroje postupně po částech. Všechny přerušované aktivace, které se uskuteční během jednoho časového kroku (v tomto případě je výjimečně jedno, jestli jádra nebo přístroje), jsou započítány jen jednou, právě proto, že stále (během přerušované aktivace) běží jeden časový krok.
- "Počet kroků zpracovaných ve skluzu" — počet kroků přístroje, které byly vykonány později, než bylo plánováno, tedy během skluzu přístroje. Ve správně navržené aplikaci by měl být tento údaj (u všech přístrojů) nulový.
- "Počet zpracovaných zpráv" — údaj, který zobrazuje celkový počet všech zpráv, které přístroj přijal od ovladačů nebo jiných přístrojů (o výjimkách a zprávách pojednává sekce Asynchronní časování a souběh výjimek a kapitola Neperiodické časování). Pokud přístroj budete časovat pouze zprávami od jiných přístrojů (a nepoužijete-li v přístroji žádný přerušovací příkaz — pause, wait, yield — proč se dozvíte v sekci o výjimkách), bude tento údaj shodný s počtem vykonaných časových kroků.
- "Počet časových kroků za 1 sekundu" — okamžitá rychlost aktivace přístroje. "Okno časování" se obnovuje každé dvě sekundy, takže tento údaj vždy zobrazuje počet kroků, které byly během posledních dvou sekund uskutečněny, podělený dvěma. Údaj je okamžitý, takže u přístrojů s periodou delší než dvě sekundy bude většinou zobrazena nula, a pokud se během posledních dvou sekund uskuteční jejich časový krok, objeví se hodnota "0.5".
- "Průměrný čas spotřebovaný v jednom kroku" — údaj, který patří k nejzajímavějším. Vzniká jako podíl času přístrojem spotřebovaného ("Čas spotřebovaný tímto přístrojem") a celkového počtu uskutečněných časových kroků. Údaj velmi přesně zobrazuje, jak rychle je přístroj schopen běžet. Snadno například uvidíte, že přístroje, které něco kreslí, spotřebovávají mnohem (typicky o dva až tři řády!) více času, než přístroje výkonné. Také uvídíte, že operace se soubory (třeba v přístrojích pro archivaci) rovněž nepatří k nejrychlejším. Zkrátka, čas spotřebovaný v jednom kroku přístroje o lečcems vypoví více, než několik stran textu. Z hlediska skluzu a bezproblémového běhu aplikace průměrný spotřebovaný čas nikdy neměl překročit délku periody časování přístroje. Jinak se přístroj (a celá aplikace) okamžitě dostane do skluzu.

#### Zápis výstupních kanálů

Zápisem výsledků shromážděných ve výstupních kanálech do ovladačů časový krok jádra končí (pokud není co zapisovat, skončí dříve). Víme již také, že výstupní kanály mohou být zapsány do technologie dříve, v situaci, kdy jsou přístroje aktivovány přerušovaně. Při postupném zápisu výstupních kanálů můžete odhalit jednu z odlišností v chování vstupních a výstupních kanálů.

Vstupní kanál nikdy není v jednom časovém kroku měřen vícekrát. Je to dáno tím, že vstupní kanál reprezetuje data, která primárně vznikají a existují v technologii. Pokud se daří měřit vstupní kanály určitou rychlostí, nemá smysl se pokoušet vyšším počtem požadavků získat další hodnoty. Technologie a ovladač data rychleji neposkytnou a v mezičase si je nevymyslí. Jádro pracuje s obrazem skutečné veličiny, který je po cestě několikrát časově převzorkován a sáhodlouze komunikován. Bezpečnější je jednou získanou hodnotu uschovat a v jednom časovém kroku ji již neměnit. Další hodnota nemusí být dostupná.

Výstupní kanál naopak primárně vzniká a existuje v aplikaci, zatímco technologie pracuje s obrazem. Výstupní kanál proto musí být do technologie zapisován při každé změně. To znamená, že výstupní kanál (na rozdíl od vstupního) může být během jednoho časového kroku komunikován vícekrát. Sáhodlouhá komunikace a časové převzorkování existují samozřejmě také, ale práci s nimi má příjemce dat, nikoli jádro.

Rozdíl mezi vstupním a výstupním kanálem je možné popsat také jazykem teorie systémů — měření je komunikace klient — server, kdy klient — jádro žádá ovladač — server o data z technologie; zatímco zápis dat probíhá plně v režii jádra — neexistuje žádný server ani klient, ovladač a technologie pouze vykonávají co se jim přikáže — zapisující jádro je systém řídící jiné hierachicky nižší systémy. Pozoruhodné je, že dva natolik diametrálně odlišné přístupy je možné skloubit do jednoho principiálního schématu komunikace a čekání na výsledek. Na první pohled se vůbec nezdá, jaké (poněkud zbytečně akademické) rozebrání komunikací odhalí rozdíly.

Postup jádra při zápisu výstupních hodnot je tedy identický s postupem použitým při měření. Jádro nejprve ovladači oznámí hodnoty všech kanálů, které si přeje zapsat do technologie, poté se s ovladačem dohaduje, zdali již byly kanály zapsány, a nakonec případně čeká do vypršení komunikační prodlevy na potvrzení zápisu. Globální prodleva zápisu kanálů se nastavuje v aplikační sekci settings a jmenuje se output_timeout. Stejně jako vstupní kanály mohou mít i výstupní kanály ve své definici uvedenu specifickou hodnotu prodlevy, která má před globálním nastavením přednost. Výstupní kanály také mají atributy timeout i status, pomocí kterých je možné zápisy detailně řídit.

Prodleva komunikací výstupních kanálů bude většinou nevyužita, neboť princip výstupních kanálů (vznikají v aplikaci) nenutí vždy ověřovat, jestli se zápis zdařil.

Zatím nebyly v této kapitole ani jednou zmíněny obousměrné kanály. Nyní, když již víte, co se děje během časového kroku jádra, je možné vysvětlit potenciální nebezpečí použití těchto kanálů — komunikační překryvy.

Obousměrný kanál je kanál, který je při použití pro vstup dat měřen a při použití pro výstup zapisován. Jádro registruje obousměrný kanál jako jeden prvek, má pro něj tudíž vyhrazen prostor jednoho datového elementu (to je nutné, neboť použití dvou míst v paměti by vedlo na dvojici kanálů — jeden vstupní a druhý výstupní). Všechny zápisy a měření hodnot procházejí tímto jedním paměťovým místem. Uvažme následující situaci:

1. Přístroj požaduje změření obousměrného kanálu
2. Jádro zahájí komunikaci a ovladač nestihne data dodat před vypršením komunikační prodlevy.
3. Jádro pokračuje aktivací přístrojů, přičemž jeden z nich do daného obousměrného kanálu zapíše. Hodnota se zapíše také do vnitřních datových struktur.
4. Aktivace je přerušena, protože jeden z přístrojů požaduje změření nových vstupních kanálů.
5. Protože existují připravené požadavky na zápis (daného kanálu), zahájí se zápis. Ovladač nestihne data zapsat do vypršení komunikační prodlevy.
6. Po zápisu dat pokračuje jádro měřením nově požadovaných kanálů. Při té příležitosti je vyčtena z ovladače změřená hodnota obousměrného kanálu a je uložena do vnitřních datových struktur.
7. Ovladač dokončí zápis do technologie.

Na konci postupu bude ve vnitřních datových strukturách (a tím i v aplikaci!) hodnota změřená, ale zastaralá (neboť do technologie proklouzla hodnota zapsaná). Navíc přístroj, který do kanálu zapsal, bude žít v přesvědčení, že jeho vlastní vnitřní hodnota (původně zapsaná do kanálu) je stejná, jako obsah kanálu.

Uvedený postup není jediný, který vede k překryvu. Zkuste si také v popsaném mechanizmu rozvinout slovo "přístroje" do jednotlivých skutečných přístrojů a sledovat, jakou skutečnou hodnotu kanálu kdy který přístroj použije. Uvážíte-li, že podobné potíže může mít s obsluhou obousměrného kanálu i ovladač (ten zase v různých okamžicích dostává hodnoty a požadavky z jádra i z technologie), vznikne celkem znamenitý zmatek.

Nelze jednoznačně říci, že použití obousměrných kanálů vede vždy k popsaným potížím. Jejich použití není chybou. Kladou však dosti značné nároky na návrh, promyšlení a v neposlední řadě také testování aplikace. V mnoha případech překryvy vůbec nemohou vzniknout, neboť aplikace data komunikuje řízeně (sama si ovládá, kdy se co zapíše a změří). Záleží tedy na způsobu použití obousměrných kanálů. Je možné vyslovit pouze jediné doporučení — pokud vystačíte jen se vstupními a výstupními kanály, nepoužívejte kanály obousměrné. Nasazení obousměrných kanálů by mělo zůstat v záloze až do okamžiku, kdy bude jejich použití nevyhnutelné.

### Procedury a přesné řízení komunikace

Mezi výrazové prostředky zápisu algoritmu v procedurách patří několik příkazů, které v běžných programovacích jazycích nenajdete. S jejich pomocí je možné řídit běh aplikace nebo časovat přístroje. Jiný speciální prostředek — atributy kanálů — umožňují získávat informace o komunikaci. Kombinací obou prvků — procedur a atributů — vznikne velmi mocná možnost detailního řízení komunikace. Upozorňuji, že tak jak je řízení komunikace mocný nástroj, je to také nástroj pokročilý. Pokud momentálně nepotřebujete v aplikaci uchopit komunikaci zcela přesně do svých rukou a doposud popsané mechanizmy vám nadmíru stačí, klidně tuto sekci přeskočte, a vraťte se k ní kdykoli uznáte za potřebné, či vhodné.

Pro řízenou komunikaci je velmi důležitý způsob použití procedury. Všechno, co bude v této sekci vysvětlováno, platí pouze pro procedury aktivované jádrem. To je procedura OnActivate a případně procedury, které "se vyvázaly" použitím přerušovacího příkazu z volání jiného přístroje nebo z volání reagujícího na nějakou událost.

Procedury, které jsou volány jiným přístrojem nebo systémem při vzniku události (například OnMouseDown), je pro popisované použití nejdříve nutné rozběhnout samostatně. Standardně je takové "vyvázání se" ve všech procedurách kromě OnActivate zakázáno (parametr independent_procedure_execution sekce settings je false, a jeho povolování ani není bez pečlivého promyšlení doporučeno. Nicméně, přejete-li si skutečně komunikaci řídit i z jiné procedury, než je OnActivate, je třeba tento parametr nastavit na hodnotu true.

Pro přesné řízení komunikace se v procedurách používají:

- příkaz yield a wait (méně potom pause)
- atributy kanálů timeout, status, value_set

Připomeňme si, že příkazy yield, pause a wait přerušují proceduru a ukončují časový krok přístroje. To je velmi důležitý fakt, který je nutnou podmínkou možnosti řízení komunikace v procedurách. Přístroj bude po vykonání těchto příkazů aktivován opětovně až v následujícím časovém kroku jádra, tedy v situaci, kdy již vstupní kanály mohou obsahovat nové hodnoty. Na přerušovací příkazy je proto možné pohlížet jako na příkazy vyvolávající komunikaci. Není to příliš přesné, neboť dochází k převrácení příčiny a následku, ale je to názorné — přerušení umožňuje jádru pokračovat, takže je možné zahájit další časový krok jádra a v něm provést novou komunikaci, jejíž výsledky přerušený přístroj použije. (Z uvedených tvrzení také vyplývá, že pro řízení komunikace není možné použít mechanizmu přerušované aktivace, který jednak není možné ovlivňovat a jednak nedokáže nikdy změřit novou hodnotu vstupního kanálu.)

Mechanizmus postupné aktivace zaručuje, že momentálně probíhající kód procedury bude pracovat s aktuálními hodnotami vstupních kanálů. Přípravu a měření těchto kanálů vždy uskutečňuje jádro automaticky bez ohledu na nějaké ruční řízení. Řízení komunikací se proto týká hlavně zápisů, tedy výstupních kanálů. Řízení komunikace však automaticky ovlivňuje i kanály vstupní. Přerušovaná aktivace zajistí, že před pokračováním běhu procedury přerušené některým z přerušovacích příkazů budou změřeny všechny vstupní kanály, které procedura obsahuje až do místa výskytu dalšího přerušovacího příkazu nebo místa nejistoty — podmíněného příkazu (i podmínky skryté v příkazech cyklu).

Běh procedury a místa měření vstupních kanálů je nejjednodušší demonstrovat na příkladu (příklad obsahuje rozličné varianty, a ač je krátký, je nabitý informacemi):

    procedure OnActivate();
    begin
      (* před první aktivací jádro změřilo kanály 1, 2 a 3.
         Více změřit nemohlo, protože nemůže předvídat
         výsledek příkazu if channel3 = 100. *)
      a = channel1 + channel2;
      (* Procedura při první aktivaci běží až k místu podmínky,
         kterou vyhodnotí. Načež aktivaci přeruší a požádá jádro o
         změření kanálů 1, 3 a 4 (měl-li kanál 3 hodnotu 100)
         nebo kanálu 5 (neměl-li kanál 3 hodnotu 100). Kanály
         6 a 7 nejsou měřeny, protože jsou za přerušovacími
         příkazy. *)
      if channel3 = 100 then
        (* Jádro změřilo kanál 4, kanály 1 a 3 již mají pro tento
           krok jádra platnou hodnotu a nebyly proto znova měřeny.
           Procedura běží až k příkazu yield, který její běh přeruší. *)
        a = channel1 + channel3 + channel4;
        (* Yield způsobí přerušení běhu procedury a jádro automaticky
           (ve spolupráci s přístrojem) změří kanály 1, 2, 3 a 6.
           Všechny tyto kanály mohou být změřeny najednou, neboť mezi
           nimi není žádný nejistý nebo přerušovací příkaz. *)
        yield;
        (* Kanál 6 byl změřen v této proceduře poprvé, kanály
           1, 2 a 3 již podruhé. *)
        a = channel1 + channel6;
      else
        a = channel5;
        (* Yield způsobí přerušení běhu procedury a jádro automaticky
           (ve spolupráci s přístrojem) změří kanály 1, 2, 3 a 7.
           Všechny tyto kanály mohou být změřeny najednou, neboť
           mezi nimi není žádný nejistý nebo přerušovací příkaz. *)
        yield;
        (* Kanál 6 byl změřen v této proceduře poprvé, kanály
           1, 2 a 3 již podruhé. Kanál 3 bude změřen jednou, a použit
           dvakrát (podruhé při prvním testu příkazu wait. *)
        a = channel1 + channel3 + channel7;
      end;
      a = channel2;
      (* Wait pracuje cyklicky tak dlouho, dokud kanál 3 nemá hodnotu
         100. Wait sám vnitřně přerušuje běh procedury a vynucuje si
         tak měření kanálu 3. Poslední běh příkazu wait (kanál nabude
         hodnoty 100) způsobí pouze přerušení aktivace (ne
         přerušení běhu procedury), v rámci něhož je potřetí v této
         proceduře změřen kanál 1. *)
      wait channel3 = 100;
      a = channel1;
    end_procedure;

Příkazy yield, pause a wait provádějí podobné činnosti a v principu je možné jejich veškerou činnost zapsat pouze s použitím příkazu pause. Uvedená ukázka je teoretická (i když by pracovala) a slouží pouze k lepšímu pochopení činnosti jednotlivých příkazů:

    (* yield *)
      ...
      pause 0;
      ...

      (* wait condition *)
      ...
      while not condition do
        yield;
      end;
      ...
      (* nebo *)
      ...
      while not condition do
        pause 0;
      end;
      ...

Řízenou komunikaci je možné rozdělit do několika kroků:

- připravení kanálů, které mají být zapsány
- přerušení běhu procedury, během něhož proběhne komunikace a změření dále použitých kanálů
- čekání na výsledek komunikace (je-li to třeba)

Příprava kanálů je velmi jednoduchá. Do výstupních kanálů jednoduše zapíšete požadovanou hodnotu, vstupní kanály připravíte jejich použitím v nějakém výraze (stačí jednoduché přiřazení). Výstupní kanály je třeba nastavit před přerušením procedury, vstupní kanály se během přerušení změří a jejich příprava tedy spočívá v jejich zapsání někam za příkaz přerušení:

    channel1 = 10;
    yield;
    a = channel2;

V ukázce je procedura přerušena příkazem yield, zapsán je připravený výstupní kanál channel1 a změřen je připravený vstupní kanál 2. Zároveň vidíte, že druhý krok řízení komunikace — přerušení aktivace — je také velice jednoduchý.

Poslední fáze komunikace je čekání na její výsledek. V principu je možné buď čekání úplně vypustit (například pokud komunikujete s kartou v počítači), nebo použít čekání systémové (bude za vás čekat jádro), nebo čekat na výsledek programově přímo v proceduře, nebo použít kombinace čekání systémového a programového:

1. systémové čekání — jednoduché čekání využívající pouze mechanizmů komunikačních prodlev. Čekání na výsledek se odbude přímo v jádře a do procedury samé není třeba přidávat žádný zvláštní čekací kód. Kanál může mít prodlevu stanovenou staticky (globálně, nebo ve své definici), můžete mu ji však upravovat i dynamicky pomocí atributu timeout:

    channel1:timeout = 2;
    yield;
    a = channel1;
    channel1:timeout = 0;

Kanál channel1 bude změřen, přičemž čekání na výsledek komunikace se protáhne nejdéle na dvě sekundy. Pokud se během těchto dvou sekund kanál nepodaří změřit, zůstane jeho hodnota nezměněna.

2. programové čekání — čekání na výsledek využívající pouze kódu procedury. Prodlevu komunikace v tomto případě nastavíme na nulu, aby se skutečně veškeré čekání odehrálo v režii procedury. Ke zjištění, jestli byl kanál změřen lze použít dvou metod — dvou atributů — jednou atributu status a jednou atributu value_set. Ukázka využití atributu status (bližší popis atributu status obsahuje kapitola Datové elementy a výrazy):

    (* společná část vyvolávající komunikaci *)
    channel1:timeout = 0;
    yield;
    a = channel1;

    (* 1. čekání s využitím bitu stGetWaitACK[3] atributu status *)
    wait bitget( channel1:status, 3 ) = 0;

    (* nebo *) (* 2. čekání s využitím bitu stGetACKed[8] atributu status *)
    wait bitget( channel1:status, 8 ) = 1;

    (* nebo *) (* 3. čekání s využitím bitů stGetACKed[8] a
                     stGetError[9] atributu status *)
    wait ( bitget( channel1:status, 8 ) = 1 ) or
         ( bitget( channel1:status, 9 ) = 1 );

Čekání 1. a 3. jsou totožná, protože jádro zaručuje, že při nastavení bitu stGetACKed nebo stGetError vynuluje bit stGetWaitACK. Čekání druhé nepodchycuje stav, kdy při komunikaci vznikne chyba, a skončí tedy jen v okamžiku, kdy je kanál skutečně správně přečten. Status kanálu obsahuje také bit stGetTimeout, který bude v našem případě vždy nastaven, neboť jádro v důsledku nastavení prodlevy na 0 nikdy nepočká — prodleva (nulová) okamžitě vyprší.

Ukázka čekání s využitím atributu value_set:

    channel1:timeout = 0;
    channel1:value_set = false;
    yield;
    a = channel1;

    wait channel1:value_set;

Atribut value_set systém pouze nastavuje, takže je nutné jej před začátkem komunikace nastavit na hodnotu false. Čekání skončí v případě, že se úspěšně podaří hodnotu změřit, jedná se tedy o ekvivalent druhého čekání z předchozí ukázky.

Popsané programové způsoby čekání nijak nepodchycují délku komunikace. To může být nedostatek, občas je vhodné čekání ukončit, trvá-li již příliš dlouho. Možností, jak zabudovat do čekání prodlevu je několik. Ukázka nabízí jeden z nich:

    start = run_time_msec;
    channel1:timeout = 0;
    yield;
    a = channel1;

    wait ( bitget( channel1:status, 3 ) = 0 ) or
         ( run_time_msec - start &gt; 2000 );

Systémová proměnná run_time_msec obsahuje počet milisekund od startu aplikace, naše ukázka proto čeká na dokončení komunikace nejdéle dvě sekundy.

3. kombinované čekání systémové a programové — přesněji, čekání systémové — zjištení výsledku programové. Je pravděpodobné, že řízená komunikace (bude-li vůbec použita) bude použita právě tímto způsobem. Čekání se nechá na jádře (použije se nějaká prodleva) a procedura pouze otestuje výsledek, podle něhož se rozhodne, co dál. Kombinace obou způsobů je může být velmi efektivní, neboť přesouvá fázi čekání na jádro, které je pro tento účel zkonstruováno. Čekání pomocí příkazu wait je čekání aktivní, přístroj je neustále aktivován, a časové kroky jádra následují jeden za druhým — aplikace vytěžuje systém jak jen to jde. Naopak, čekání jádra je čekání pasivní a aplikace tak nevytěžuje systém skoro vůbec. Jiný rozdíl mezi čekáním jádra a čekáním pomocí wait plyne z principu práce příkazu wait. Každé jeho provedení přerušuje proceduru, ukončuje časový krok přístroje a jádro tak může aktivovat přístroje jiné. Během čekání pomocí wait proběhne velmi mnoho časových kroků jádra a v každém z nich se dostanou ke slovu ostatní přístroje, například periodicky časované. Čekání v jádře se odehraje v rámci jednoho časového kroku, který následuje po kroku jádra, v němž byla procedura přerušena kvůli komunikaci příkazem yield. Jiné přístroje se tedy nedostanou ke slovu, neběží, a mohou se dostat do skluzu.

Jak nakonec procedura bude čekat, jestli pomocí jádra (s minimální spotřebou času, ale bez aktivací přístrojů), nebo příkazem wait (s velkou spotřebou času, ale s normálním během ostatních přístrojů) záleží pouze na vás — tvůrcích aplikace.

Ukažme si, jak může kombinované čekání vypadat:

    channel1:timeout = 0.2;
    channel1:value_set = false;
    attempts = 5;

    loop
      yield;
      a = channel1;
      if channel1:value_set then
        exit;
      end;

      attempts = attempts - 1;
      if attempts = 0 then
        exit;
      end;
    end;

Ukázka čeká pasivně vždy 200 milisekund. Podaří-li se kanál změřit, opouští se měřicí cyklus. V opačném případě (například při chybě komunikace) se pokračuje v měření a to až čtyřikrát.

Ukázky byly sestaveny s použitím vstupních kanálů. Výstupní kanály se obsluhují v principu shodně s jednou výjimkou — u výstupního kanálu nemá smysl používat atribut value_set, neboť během zápisu ke změně hodnoty kanálu nedochází. Druhá metoda používající atribut status je však použitelná bez výhrad, pouze se nesmí zapomenout, že bity signalizující stav zápisu mají jiná jména i čísla — stSetWaitACK (1), stSetACKed (5), stSetTimeout (4) a stSetError (6).

Další důležitá zmínka se váže k příkazu wait. Jeho použití je v našich ukázkách jediné možné, varianta čekání bez přerušování běhu procedury (například v cyklu while channel1:value_set do ... end;) neumožní komunikaci jádra s ovladačem, hodnotu nebude možné doměřit a cyklus while bude nekonečný.

Ukázky řízení komunikace se soustředily na objasnění principu a pro jednoduchost mlčky zanedbaly jakékoli okolí — hlavně jiné přístroje. Každý z těchto jiných přístrojů může do těchto mechanizmů zasahovat a může tak s řízeně komunikovanými kanály pracovat. Ohroženy jsou výstupní a obousměrné kanály použité jako výstupy, neboť, jak již víme, výstupy mohou nabývat během jednoho časového kroku jádra více hodnot. Řízené zapsání výstupu v proceduře může proběhnou excelentně, ale kvůli akci jiného přístroje můžete zapsat a ověřit úplně jinou hodnotu, než jste si původně připravili.

Řízení komunikace je velmi pokročilý způsob, jak komunikovat, a je možné předpokládat, že bude použit pouze v případě obzvláště důležitých kanálů. Rutinní používání tohoto postupu by bylo asi nepraktické, protože samotné jádro dokáže vyhovět aplikaci svými postupy v 99,99 % až 100 % případů. Řízená komunikace v procedurách je třešnička na dortu komunikačních možností systému Control Web.

### Asynchronní časování a souběh výjimek

Přístroje mohou být aktivovány buď periodicky, nebo výjimkami od jiných přístrojů nebo ovladačů. Periodickou aktivaci zajišťuje časovací tok spolu s jádrem podle informací přítomných přímo v přístroji, zatímco aktivaci výjimkami musí vždy způsobit přístroj nebo ovladač (objekty mimo jádro).

Výjimky se nazývají také "zprávy", takže je možné použít například větu "přístroj pošle zprávu...". Jen je třeba rozlišovat mezi zprávami operačního systému (ty se zase častěji nazývají události), které se řadí do fronty vstupních zpráv, a zprávami aplikace systému Control Web, které si navzájem posílají přístroje a ovladače.

Základní rozdíl mezi periodickým časováním a výjimkami spočívá v jejich předpověditelnosti. Zatímco o periodickém časování je vše známo předem, tedy jak perioda, tak jednotlivé okamžiky aktivací přístroje, o výjimkách není předem známo nic, a systém s nimi nemůže dopředu nijak počítat. Tento zásadní rozdíl také vymezuje použití jednotlivých způsobů časování — periodické časování bude použito všude tam, kde je znám související děj, časování výjimkami všude tam, kde předem není dán žádný děj ani časový rámec. Výjimkami se časuje typicky asynchronně (tedy kdykoli), většinou v reakci na vstupní události. Výjimky umožňují programovat aplikaci "událostně" jako sadu akcí, které mohou být v určitý předem neznámý okamžik podle potřeby provedeny.

Výjimku přístroje je v aplikaci možné vyrobit dvěma způsoby:

- Každý přístroj, který slouží k ovládání nebo nastavování hodnot, definuje parametr receivers, který obsahuje seznam přístrojů, jimž se pošle zpráva, provede-li přístroj nějakou akci. Například přístroj switch pošle zprávu přístrojům uvedeným v seznamu receivers po své vlastní aktivaci, při úpravě výstupní hodnoty (například nativní procedurou) nebo v okamžiku stisku tlačítka přístroje pomocí myši nebo klávesnice.
- Procedury definují příkaz send, který můžete použít kdekoli v zapsaném algoritmu, přičemž (na rozdíl od parametru receivers) argumentem tohoto příkazu je vždy jen jeden přístroj.

Výjimky ovladače se do zdrojového textu zapisují trochu jinak (naopak). V přístroji se pomocí parametru driver_exception nedefinuje příjemce zprávy, ale její zdroj — ovladač. Ovladač nemusí umět výjimky generovat, tato vlastnost není součástí specifikace nutných vlastností ovladače. Z toho také plyne určitá volnost v návrhu ovladačů, kdy podle potřeby může každý ovladač výjimku použít k signalizaci naprosto jiné skutečnosti. Například standardní ovladač ASCII-Driver dokáže výjimku generovat v případě, že přijme po sériové lince nějaká data.

Obě výjimky, přístrojová i ovladačová, jsou zpracovány v takovém pořadí, jak přicházejí. Zachycení všech výjimek a jejich shromáždění v pořadí jejich vzniku má na starosti časovací tok. Výjimky jsou asynchronní a časovací tok je proto zpracovává co nejrychleji, obyčejně okamžitě, jakmile jádro dokončí probíhající časový krok. Pokud zrovna časovací tok čeká na probuzení, jsou výjimky zpracovány okamžitě při jejich přijetí.

Časovací tok má dvě možnosti:

- Bez výjimek čekajících na zpracování by tok čekal na probuzení až do okamžiku uplynutí délky nejkratší periody jednoho z přístrojů. Výjimky však musejí být zpracovány, a časovací tok proto vloží mezi periodické časové kroky jádra jeden okamžitý krok navíc. V tomto kroku jsou aktivovány všechny přístroje, kterým někdo poslal zprávu. Vložený časový krok je zvláštní pouze svou asynchronností, všechny děje popsané v oddíle o časovém kroku probíhají beze zbytku identicky.
- Časovací tok by i bez čekajících výjimek okamžitě pokračoval v časování dalším krokem. Za této situace jsou k frontě přístrojů, jimž byla poslána zpráva, přiřazeny navíc všechny přístroje, které mají být krokem periodicky aktivovány. Dojde tedy k logickému sloučení výjimek i periodických aktivací, a žádný zvláštní časový krok se nevkládá. I v tomto případě časovací tok zachovává časovou posloupnost aktivací přístrojů — nejdříve jsou aktivováni příjemci zpráv a po nich teprve přístroje časované periodou.

Velmi snadno může vzniknou situace, kdy jednomu přístroji v jednom časovém kroku jádra pošle zprávu více přístrojů. Popsaný mechanizmus zaručuje, že přístroj dostane zprávu pouze jednu, neboť na výjimky vzniklé v jednom kroku jádra se pohlíží jako na výjimku jednu. Zajímavější situace nastane, pošle-li přístroji zprávu současně přístroj i ovladač, případně čeká-li přístroj na aktivaci výjimkou a ještě jej současně periodicky aktivuje časovací tok (to může nastat v případě, kdy časovací tok slučuje výjimky a periodicky časované přístroje).

I za této situace bude přístroj obeslaný všemi způsoby aktivován pouze jednou — dojde k souběhu výjimek. Způsob aktivace může přístroj velmi zajímat. Několik přístrojů například pracuje tvrdošíjně pouze jsou-li periodicky aktivovány (například PID regulátor), přičemž ostatní způsoby aktivace přehlížejí. Souběh bez informací o výjimkách by způsobil ztrátu informace. Každý přístroj proto dostává při své aktivaci od jádra seznam všech příčin aktivace. Tato informace je dostupná i v proceduře OnActivate s parametry — buď se čtyřmi, které přímo po řadě určují příčinu aktivace, nebo s jedním, který kromě příčin aktivace ještě obsahuje další informace (o proceduře OnActivate se dočtete v kapitole Programování a procedury — OCL). Každý přístroj v aplikaci se tudíž může dozvědět, proč vlastně zrovna pracuje.

Souběh výjimek má ještě jeden aspekt. Víte, že časovací tok zachovává pořadí aktivací přístrojů podle pořadí přijatých zpráv. Přidá-li se k již existující příčině aktivace nějaká další, vznikne souběh. Přístroj zůstane na svém dosaženém pořadí.

V případě souběhu tedy bude přístroj aktivován v okamžiku, který odpovídá vzniku první příčiny aktivace. Například, vznikne-li souběh výjimky a časování periodou, je přístroj připraven pro aktivaci před časovanými přístroji. Přidání časování periodou pořadí přístroje neovlivní, a přístroj proto bude aktivován z důvodu výjimky i uplynutí periody před přístroji aktivovanými pouze z důvodu uplynutí periody.

Mechanizmus výjimek je obecný a je systémem používán také vnitřně. Jistě si pamatujete, že příkazy yield, pause a wait přerušují proceduru a ukončují časový krok přístroje. Bez výjimek by procedura nemohla pokračovat dříve, než v okamžiku další periodické aktivace (nebyl by důvod proceduru aktivovat). Příkaz yield, nebo pause 0 by se tak protáhl třeba na deset sekund. Procedury proto komunikují s časovacím tokem pomocí vnitřních (skrytých) výjimek, pro které však platí všechna popsaná pravidla. Takže není-li potřeba periodicky časovat, vynutí si výjimka vložení časového kroku a procedura může pokračovat po příkazu yield s minimálním časovým zpožděním.

Asynchronnímu časování je věnována samostatná kapitola Neperiodické časování, která na celou problematiku nahlíží z jiného úhlu, než striktně časovacího.

## Rozběh a zastavení aplikace

Veškerý text této kapitoly (kromě malého kousku u periodického časování) zatím předpokládal, že aplikace běží. Po drtivou většinu času provozu aplikace je takový předpoklad správný a bez výhrad platný. Aplikace se však při startu rozbíhá a při zastavení ukončuje, přičemž jak rozběh tak ukončení musejí provádět jiné akce, než jaké jsou typické pro běh. Před vlastním během je třeba legálně nastartovat přístroje, korektně inicializovat vnitřní data a kanály a zajistit plynulý rozběh časování. Zastavení naopak musí bezpečně ukončit časování a komunikace.

### Inicializace dat

Při rozběhu aplikace se musí inicializovat (nastavit na počáteční hodnotu) globální proměnné a výstupní kanály (konstanty také, ale tam se to předpokládá jaksi automaticky). Obojí jsou totiž přístrojům k dispozici okamžitě (bez měření) a jakékoli čtení jejich obsahu musí vždy (již od počátku) poskytnout legální hodnotu. Globální proměnné i výstupní jsou inicializovány ihned při čtení jejich definic.

Výstupní kanály jsou však (na rozdíl od proměnných) spjaty s konkrétními existujícími řídicími prvky a inicializace kanálů by tedy měla ovlivnit i je. Na druhé straně je docela dobře možné chtít výstupní kanál inicializovat "jen tak", než se aplikace rozběhne, a teprve až poté výstupní kanál nastavit na správnou hodnotu vyčtenou z technologie. Nelze rozhodnout, který z obou způsobů je správný — nejspíše bude část aplikací potřebovat inicializovat jak kanál tak technologický prvek, a část nikoli. Aplikace proto definuje parametr skip_init_outputs sekce settings, který se chování inicializací řídí:

- Je-li hodnota parametru true, inicializuje systém pouze vnitřní data kanálu a nezapisuje inicializační hodnotu do technologie.
- Je-li hodnota parametru false (to je také přednastavená hodnota), inicializuje systém jednak vnitřní data kanálu a jednak inicializační hodnotu připravuje k zápisu do technologie. Skutečný zápis (komunikace) kanálu se přitom ještě neuskuteční, neboť hodnota kanálu může být dále ovlivněna jiným způsobem.

Prvotní inicializace proměnných a kanálů probíhá při jejich čtení. Od toho okamžiku jsou oba druhy datových elementů k dispozici přístrojům, které je jednak mohou číst, a jednak do nich mohou zapisovat. Aplikace ještě neběží a nejedná se tedy o běžné výkonné čtení a zápisy — přístroje pouze v rámci své inicializace upravují datové elementy, které jsou jejich výstupem, na svou inicializační hodnotu. Například, přístroj control zapíše při své inicializaci do svého výstupu hodnotu, která je určena jeho parametrem init_value. Po inicializaci kanálů a proměnných jejich počátečními hodnota jsou tedy přístroje druhé v pořadí, kdo ovlivňuje hodnotu datových elementů.

Přístroje při inicializaci svých výstupů zapisují do proměnných i kanálů vždy bez možnosti tuto vlastnost jakkoli vypnout. Pokud je výstupem přístroje výstupní kanál, je jeho hodnota přístrojem změněna, a podle nastavení parametru skip_init_outputs případně také připravena k zápisu. Jinými slovy, hodnota výstupního kanálu uvnitř systému je přístrojem při inicializaci ovlivněna vždy, nicméně vlastní přenos kanálu do techologie může a nemusí být realizován — to již záleží na nastavení parametru skip_init_outputs.

Hodnota datového elementu po inicializaci přístrojů však stále ještě nemusí být konečná.

Třetí v pořadí, kdo může ovlivnit hodnoty výstupních kanálů a proměnných, jsou přístroje backup, které slouží k obnovení zálohovaných veličin. Data zálohovaná přístrojem backup jsou skrytě dosazena do všech přístrojů, které patřičný datový element používají jako svůj výstup — například již zmíněný přístroj control po obnovení dat přístrojem backup automaticky upraví svou hodnotu (svůj vzhled) podle svého výstupu.

Obnovení dat ze zálohy pomocí přístrojů backup je operace, která musí být vždy do aplikace naprogramována a systém ji nikdy neprovádí sám od sebe. Naprogramováním v tomto případě se rozumí pouhá přítomnost přístroje backup v aplikaci. Jelikož je zařazení přístroje backup nutně vždy krokem tvůrce aplikace, není důvod předpokládat, že by si autor data z přístroje backup nepřál obnovit. Proto přístroj backup při obnovení výstupního kanálu automaticky kanál připravuje k zápisu, a hodnota kanálu proto bude vždy komunikována až do technologie. Přístroje backup se tedy neřídí parametrem skip_init_outputs.

Posledním místem, kde můžete počáteční hodnotu datových elementů upravit, je přístroj startup (jeho popis následuje níže). Přístroj startup je normální součástí zdrojového textu aplikace a může obsahovat jakýkoli algoritmus, takže podle potřeby můžete v tomto přístroji jakémukoli datovému elementu nastavit jakoukoli hodnotu. Jelikož je startup poslední v řadě inicializací datových elementů, budou hodnoty v něm nastavené skutečně poslední a čerstvě rozběhnutá aplikace použije právě je.

Inicializace datových elementů v přístroji startup může proběhnout dvojím způsobem:

- Parametr skip_init_outputs má hodnotu true. V tomto případě se první komunikace výstupních kanálů uskuteční po dokončení časového kroku přístroje startup. Hodnoty zapsané do datových elementů v přístroji startup tak přepíší hodnoty z přístrojů backup. Jinými slovy, za tohoto nastavení je startup bezpečným místem, kde můžete ještě před komunikací upravit jakýkoli výstupní kanál.
- Parametr skip_init_outputs má hodnotu false. V tomto případě se první komunikace výstupních kanálů uskuteční před aktivací přístroje startup. Iniciální komunikace tak proběhne ve dvou fázích — nejdříve budou komunikovány všechny výstupní kanály (přičemž jejich hodnota mohla být ovlivněna inicializacemi přístrojů a přístroji backup), po té bude aktivován přístroj startup, a po něm budou komunikovány jen kanály zapsané v přístroji startup.

Počáteční inicializace datových elementů je navržena tak, aby pokryla pokud možno všechny myslitelné varianty. Mechanizmus je možné ovlivnit volbou skip_init_outputs tak, že ve výsledku systém pracuje jedním z následujících způsobů:

Inicializace dat

### Rozběh přístrojů, startup

Současně s inicializací dat se při spouštění průběžně inicializují a k rozběhu připravují jednotlivé přístroje. Každý přístroj během inicializace může ovlivňovat datové elementy (to jste již poznali), může spouštět událostní procedury a může posílat zprávy jiným přístrojům. Aplikace však ještě neběží, a proto všechny akce systém provádí "do zásoby". Některé z nich navíc nemohou být zcela realizovány (například procedura nebude po příkazu yield ihned pokračovat), a odloží se až na dobu běhu.

Přístroje při své inicializaci mohou provádět následující akce, které budou plně uskutečněny až po rozběhu aplikace:

- Přístroje mohou posílat zprávy jiným přístrojům (aktivovat je výjimkami). Již víte, že přístroje v aplikaci posílají zprávy jiným přístrojů dvěma způsoby — pomocí parameteru receivers nebo pomocí příkazu send. Příkaz send je vždy součástí nějaké procedury a proto se uplatní pouze v situaci, kdy přístroj spouští své událostní procedury (tento mechanizmus je popsán v dalším bodě). Výjimky druhé (generované parametrem receivers) přístroje obsluhují samostatně (vnitřně), a provedou se vždy, odpovídá-li to specifikaci přístroje. Například všechny ovládací a řídicí přístroje posílají zprávy v okamžiku nastavení výstupní hodnoty. Jelikož tyto přístroje při inicializaci svůj výstup nastavují, posílají také automaticky zprávy všem definovaným příjemcům. Posílání zpráv při inicializaci však může být na závadu. Aplikace může být navržena tak, že její počáteční definice a nastavení vyhovují, a není tudíž třeba inicializace jednotlivých přístrojů pomocí zpráv jakkoli propagovat. Tento případ podchycuje aplikace parametrem disable_init_messages. Pokud jej nastavíte na hodnotu true, neuplatní se žádné zprávy zaslané během inicializace přístrojů. V opačném případě systém realizuje všechny výjimky tak, jak jsou v aplikaci zapsány.

Všechny zprávy se během inicializace řadí do fronty podle okamžiku vzniku a jsou najednou zpracovány po dokončení běhu přístroje startup před rozběhem ostatních přístrojů. Počáteční zprávy jsou tedy vloženy mezi aktivaci startupu a ostatní počáteční aktivace, neboli jinak řečeno, zprávy přeskočí přístroj startup.

- Přístroje mohou volat své událostní procedury. Opět platí, že okamžiky volání jednotlivých procedur určuje přístroj (jeho specifikace), a je tudíž třeba předem vždy ověřit, jestli bude při inicializaci procedura volána či nikoli. Nejběžnější případ — procedury OnOutput() (a jejich varianty) ovládacích přístrojů jsou například volány vždy při nastavení hodnoty přístroje (podobně jako v této situaci ovládací přístroje posílají zprávy), takže během inicializace vždy. Opět je možné volání procedur za inicializace zamezit — pomocí parametru skip_init_procedures sekce settings. Pokud parametr nastavíte na hodnotu true, budou procedury při inicializaci přeskočeny, v opačném případě se provedou podle specifikací přístroje. Součástí událostní procedury volané během inicializace mohou být příkazy send, které posílají zprávu libovolnému přístroji. Posílání zpráv během inicializace je řízeno nezávisle (parametrem disable_init_messages) a je proto možné, že zpráva nebude poslána. Pokud na jejím vyslání záleží, je třeba parametr disable_init_messages zkontrolovat.

Již jste se (několikrát) dozvěděli, že existuje přístroj startup, který je možné použít (mimo jiné) při inicializaci datových elementů. Jeho postavení v systému je výjimečné, neboť pro něj platí následující speciální pravidla:

- Startup je přístroj, který pojmenujete startup. Systém jej tedy rozlišuje podle jména. Obyčejně bývá startup nějaký přístroj program, nicméně klidně můžete jako startup použít třeba přístroj meter.
- V aplikaci může být pouze jeden přístroj se jménem startup. Tím se zaručí, že systém bude vždy vědět, který přístroj má při rozběhu použít.
- Přístroj startup je při rozběhu aktivován jako první před aktivací jakéhokoli jiného přístroje. V aplikaci tak existuje nástroj, ve kterém můžete ještě před vlastním rozběhem modifikovat libovolná data nebo přístroj.
- Přístroj startup předbíhá zprávy, které byly poslány během inicializace přístrojů. Aplikace tak má možnost v přístroji startup poslat jakékoli další zprávy.
- Přístroj startup je spuštěn vždy v samostatném časovém kroku. Běží tedy sám, a jakmile dokončí svůj časový krok (připomínám, že příkazy pause, wait, stop a yield časový krok přístroje ukončují), rozběhne se normální časování ostatních přístrojů.
- Z předchozího pravidla vyplývá, že periodicky časovaný přístroj startup provede při startu aplikace dva časové kroky. První proto, "že to je startup", a druhý při normálním začátku časování. Stejného výsledku (provedení dvou časových kroků přístroje startup) dosáhnete také výjimkou poslanou například během inicializace přístrojů.
- Přístroj startup může pracovat jako jakýkoli jiný přístroj aplikace. Jeho výjimečnost spočívá pouze v předřazení jeho běhu před jiné přístroje. Je-li přístroj startup aktivován v samostatném kroku při startu aplikace (jako startup), obsahuje parametr jeho procedury OnActivate( ActivateMode : cardinal ) bit 6. Je-li přístroj startup aktivován normálně za běhu aplikace periodicky nebo výjimkou, ActivateMode bit 6 neobsahuje.

O rozběhu aplikace zatím víte, že postupuje následujícími kroky:

- Inicializují se přístroje, přičemž podle nastavení parametru skip_init_procedures se během jejich inicializace volají nebo nevolají událostní procedury.
- Podle nastavení parametru disable_init_messages jsou nebo nejsou akceptovány výjimky generované během inicializace přístrojů.
- Spouští se přístroj startup.
- Zpracovávají se zprávy poslané během inicializace (ty mohly být zakázány parametrem disable_init_messages) a zprávy poslané v přístroji startup.

K úspěšnému rozběhu aplikace již zbývá málo — začít periodicky časovat přístroje. Protože se již o periodickém časování hovořilo v oddíle Časování přístrojů, shrnu na tomto místě pouze skutečnosti, které se vážou k rozběhu aplikace:

- Relativně časované přístroje jsou rozběhnuty (poprvé se aktivují) v časovém kroku jádra, který následuje bezprostředně po prvním samostatném časovém kroku přístroje startup.
- Absolutně časované přístroje jsou rozběhnuty v nejbližším možném okamžiku odpovídajícímu jejich posunuté periodě.
- Definujete-li přístroji periodu časování infinite, bude tento jeho první časový krok také krokem posledním, který bude vyvolán časovacím tokem (výjimky bude přístroj zpracovávat bez omezení).

První časový krok jádra (tedy krok s přístrojem startup) je zároveň krokem, od kterého je možné považovat aplikaci za rozběhnutou, takže veškeré komunikace, výjimky a časování začnou probíhat podle výše obšírně popsaných mechanizmů.

Přístroj není povinnou součástí aplikace a vůbec jej nemusíte používat. Aplikace bez přístroje startup poběží stejně dobře. Celý text se doposud přístrojem startup zabýval, neboť startup patří k rozběhu, a bez jeho zahrnutí (nebo neustálého opakování, že startup může a nemusí existovat) by se popis rozběhových pochodů zbytečně rozmělňoval. Popsané startovací děje probíhají bez přístroje startup shodně, odlišnost spočívá právě v prostém vypuštění přístroje startup i se všemi akcemi, které se ho týkají. Bez přístroje startup nemůžete ovlivňovat výstupní kanály po jejich obnovení přístroji backup, nemůžete zprávami aktivovat přístroje a nemůžete připravit specifické podmínky pro běh aplikace (například přizpůsobit velikost hlavního panelu aktuálním velikostem obrazovky). Podobně vypadá rozběh jádra — bez přístroje startup se žádný zvláštní časový krok nevkládá a časování začne okamžitě krokem jádra, ve kterém se jednak vyřídí inicializační zprávy a jednak poprvé aktivují relativně časované přístroje.

Pokud byste zkusili přístroj startup vyhledat v existujících aplikacích, bude přítomen asi v 80 % případů. Jeho použití je tedy docela časté, ale jde to i bez něj. Doporučení týkající se přístroje startup může být pouze velmi obecné — lepší než trvale komplikovat vztahy mezi přístroji různými podmínkami rozběhu aplikace, je dát na jedno místo v aplikaci vhodný impuls, který se již nikdy později za běhu nezopakuje. Výsledkem bude funkčně shodná aplikace, zmenší se však riziko chyb a zpřehlední se její zápis.

### Ukončení aplikace, terminate

Opakem přístroje startup je přístroj terminate. Spouští se na konci aplikace v okamžiku, kdy již je jasné, že aplikace má být zastavena. Součástí terminate proto mohou být různé operace — odstranění dočasných souborů, dokončení komunikací, zálohování posledních známých dat nebo vypnutí a rozpojení komunikačních kanálů.

Jedná se opět o přístroj speciální, a platí pro něj tedy zvláštní pravidla:

- Terminate je přístroj, který pojmenujete terminate. Stejně jako přístroj startup jej tedy systém rozeznává podle jména, a stejně jako v případě přístroje startup bude terminate většinou přístroj program (i když je možné zvolit jakýkoli přístroj).
- Terminate může být v aplikaci pouze jeden, aby jej systém rozeznal.
- Terminate může být časován, může přijímat výjimky, za běhu se chová jako běžný přístroj.
- V okamžiku začátku zastavení aplikace jádro zruší veškeré periodické časování, dokončí právě probíhající časový krok a rozběhne poslední časový krok (jádra), ve kterém budou nejprve aktivovány přístroje, jimž byla v předposledním kroku zaslána zpráva, a po nich přístroj terminate.
- Periodické časování již nepracuje, takže terminate může aktivovat jiné přístroje pouze pomocí příkazů send. Zároveň platí, že přístroj terminate skončí vlastním doběhnutím.
- Z předchozího bodu vyplývá, že v přístroji terminate můžete aktivovat libovolné přístroje libovolně dlouho, jen při tom terminate nesmí skončit. Součástí terminate v takovém případě bude vždy nějaká smyčka s nějakým přerušovacím příkazem ve svém těle.
- Během přístroje terminate je možné bez omezení komunikovat.
- Aplikace skončí v okamžiku, kdy doběhne terminate a všechny přístroje, které terminate případně aktivoval. Před vlastním definitivním ukončením běhu ještě jádro dokončí rozběhnuté vstupní i výstupní komunikace.

Podobně jako přístroj startup není ani přístroj terminate povinnou součástí aplikace. Pokud jej nepoužijete, systém dokončí právě probíhající časový krok, zastaví peridické časování, vyřeší zaslané zprávy (ty se mohou dále šířit a řešení zpráv proto může spotřebovat několik časových kroků jádra) a dokončí rozběhnuté vstupní i výstupní komunikace. Po té aplikace skončí.

Končící aplikace (ať již obsahuje přístroj terminate nebo ne) signalizuje svůj stav každému aktivovanému přístroji prostřednictvím bitu 9 v parametru procedury OnActivate( ActivateMode : cardinal ). Všechny přístroje se tak mohou dovědět, jestli jsou aktivovány při ukončování, a mohou podle toho přizpůsobovat své chování. Samotný přístroj terminate (aktivovaný jako terminate, neboli jako poslední přístroj) obsahuje v parametru své procedury OnActivate( ActivateMode : cardinal ) bit 7. Je-li přístroj terminate aktivován za chodu aplikace (periodicky nebo výjimkou), ActivateMode uvedený bit 7 neobsahuje.

V obou případech (při použití terminate i bez něj) nemusí být aplikace konečná. První způsob, jak aplikaci nikdy neukončit, je vyrobit nekonečný přístroj terminate — například naprogramujete nekonečný cyklus s jediným příkazem yield v těle cyklu. Druhá možnost je porucha v komunikaci — nemusí se dařit vyřídit všechny existující vstupní nebo výstupní požadavky. Za těchto okolností by aplikace nikdy neskončila.

Systém Control Web proto obsahuje pojistku, která "nekonečné ukončení" odstraní. Použijete-li přístroj terminate, otevře se v okamžiku zastavování aplikace následující okno:

Ukončení aplikace

Terminate tedy může pracovat třeba nekonečně dlouho, nicméně stisk kombinace kláves <Ctrl>+<End> aplikaci jistě ukončí. Terminate sice nedoběhne a komunikace se nedokončí, ale s tím se už nedá nic dělat.

Pokud aplikace terminate neobsahuje, otevírá se uvedené okno automaticky po pěti sekundách od pokynu k zastavení aplikace. Postup je potom shodný — stisk kombinace kláves <Ctrl>+<End> aplikaci ukončí.

Přístroj terminate se používá mnohem méně než přístroj startup. Je to asi dáno tím, že při zastavení má aplikace k dispozici platná data, a nemusí se tudíž příliš starat o jejich obsluhu. Z obecného hlediska je vhodné v přístroji terminate provádět jen nejnutnější akce, které příliš nebudou brzdit zastavení aplikace. Pokud si nepřejete aplikaci zastavit, použijte mechanizmu uživatelských přístupových práv (popsáno v kapitole Systém kontroly uživatelských práv). Po rozběhu přístroje terminate je již pozdě na nějaké rozsáhlé akce. Přeje-li si uživatel aplikaci zastavit, má být aplikace zastavena a ne zdržována přístrojem terminate.

## Rizika a výhody reálného času

Programování aplikací reálného času může být dvojsečnou zbraní. Na jedné straně jsou aplikace reálného času velmi elegantní a velmi mocné, dokážete s nimi splnit jakákoli přání zákazníků (počínaje archivacemi do gigantických databází přes vizualizace velmi rychlých dějů až k přímému řízení strojů). Systém Control Web vás přitom všemožně podporuje a poskytuje vám neobvykle širokou paletu nástrojů (nakonec, všechno řízení, komunikaci i časování můžete takřka zcela převzít do svých rukou).

Na straně druhé však toto velmi benevolentní otevření se a nabídnutá volnost návrhu nutí vás — tvůrce aplikace převzít plně odpovědnost za svou práci. Aplikace reálného času musí být dobře promyšlena, musí se více programovat a musí se pamatovat na to, že program pracuje vždy přesně tak, jak ho programátor vyrobil (a že tudíž nedělá to, co si programátor přeje). Aplikace a systém (jádro a časovací tok) vám dovolí témeř cokoli, ale musíte si být vědomi, že vy jste ta hlavní osoba, která celou aplikační mozaiku ze služeb systému poskládá. Vytvoříte-li chybný obrazec, nebo přesáhnete-li možnosti stroje, programu či fyziky, nedokáže vám v tom aplikace nijak zabránit. To by vás musela omezit a to přece není cílem.

Výhody aplikací reálného času jsou: otevřenost, univerzálnost, škálovatelnost, plná podpora programování na všech úrovních a plná kontrola nad během aplikace.

Rizika aplikací reálného času jsou: otevřenost, univerzálnost, škálovatelnost, plná podpora programování na všech úrovních a plná kontrola nad během aplikace.

Jen vaše práce rozhodne, do které skupiny se vaše aplikace zařadí.

## Shrnutí

- Aplikace systému Control Web mohou být aplikacemi reálného času. Aplikace reálného času má přehled o svém běhu a časování a je schopná se aktivně přizpůsobovat okolním podmínkám.
- Aplikace je za běhu rozdělena na přísnou část — časovací tok, která dbá na přesné časování a která pracuje s vyšší prioritou; a na normální část — jádro, která zajišťuje komunikaci a běh přístrojů.
- Jednotkou běhu aplikace je časový krok jádra, během něhož se uceleně odehrají všechny akce (měření, aktivace přístrojů a zápis výstupů) nezbytné pro funkci aplikace.
- Veškerá aktivita aplikace pochází od přístrojů, které modelují reálné děje. Aplikace proto umí přístroje časovat (periodicky, speciálními přístroji a asynchronně) tak, aby přístroje — modely mohly opakovaně realizovat předepsané úkoly (algoritmy).
- Jádro aplikace zajišťuje všechny operace spojené s komunikací a aktivací přístrojů. Přístroje však mohou libovolnou část těchto operací převzít a samy tak mohou komunikovat nebo časovat.
- Důležitou součástí aplikace reálného času je její řízený rozběh a zastavení. Systém Control Web podporuje řízení startu i zastavení aplikace, přičemž k tomu využívá běžných přístrojů aplikace.
- Aplikace reálného času nabízejí tvůrcům velmi mnoho velmi promyšlených nástrojů, které je třeba s rozmyslem použít. Výsledná podoba a funkčnost aplikace proto záleží jen (jen a pouze) na jejím zdrojovém textu, na jejím tvůrci.