Vyšlo v týdeníku Computerworld č. 11/95 v roce 1995
Vytištěno z adresy: http://www.earchiv.cz/a95/a511c120.php3

Reentrant

Jeden moudrý pán kdysi dávno prohlásil, že nelze dvakráte vstoupit do téže řeky. Měl tím na mysli, že věci se mění, čas plyne, a nic není přesně takové, jaké to bývalo někdy dříve. Mohli bychom ale obdobnou moudrost aplikovat i na programy, například ve smyslu: „Nelze dvakráte vstoupiti do téhož kódu"? Co by to ale přesně znamenalo, a byla by to pravda, nebo nebyla?

Ujasněme si nejprve, co by znamenalo „vstoupiti dvakráte do téhož kódu". Jak jsme si již uvedli v předminulém příspěvku této rubriky, na téma „Subroutine vs. Coroutine", existuje zásadní a principiální rozdíl mezi kódem jako takovým (který je statického charakteru), a jeho dynamickou instancí (exemplářem), která vzniká voláním příslušného kódu. Z tohoto pohledu pak „vstoupiti do kódu" neznamená nic jiného, než předání řízení (skokem či voláním) příslušnému kódu a vytvoření jeho dynamické instance. Takže otázka tedy zní: je možné opakovaně volat určitý kus kódu, resp. opakovaně mu předat řízení formou skoku? Odpověď pak bude záležet na tom, zda od příslušného kódu může existovat více jeho dynamických instancí či nikoli. A to zase závisí na tom, jak je příslušný kód napsán.

Ukažme si to na typickém příkladu podporogramu, který odpovídá nějaké proceduře či funkci vyššího programovacího jazyka (např. vznikl překladem takovéto procedury či funkce). Má-li tato procedura či funkce nějaké lokální proměnné, pak tyto jsou charakteristické právě svou „lokálností" v daném procedurálním bloku - což znamená nejen to, že vně bloku jsou nepřístupné, ale především to, že vznikají až se spuštěním bloku, a s jeho ukončením zase zanikají. Jsou tedy právě tím, co tvoří relevantní část dynamické instance (dynamického exempláře) příslušného procedurálního bloku. Nyní ale velmi záleží na tom, jak konkrétně je napsán kód tohoto bloku. Pokud by si své lokální proměnné vytvářel (tzv. alokoval) na předem pevně daném místě v paměti - například v oblasti, kterou si pro tento účel vyhradil přímo uprostřed sebe sama, „vynecháním" dostatečného počtu bytů - pak by se děly zajímavé věci. Při prvním spuštění bloku (prvním předání řízení) by vše proběhlo hladce, a blok by si vytvořil své lokální promněnné na patřičném místě korektním způsobem. Stejně by ale postupoval při každém svém dalším volání - opět by si na předem pevně daném místě vytvořil novou sadu svých lokálních proměnných. Pokud by ale šlo například o rekurzi (či jiný způsob nového volání, ke kterému dojde ještě před ukončením přechozího volání), pak by si náš podprogram sám přepsal své vlastní lokální proměnné!

Podstatné je tedy to, jakým způsobem si určitý procedurální blok („kus kódu") alokuje své lokální proměnné, resp. kde a jakým způsobem si vytváří svou dynamickou instanci. Pokud to dělá tak nešikovně, že vytvořením jedné své dynamické instance přepíše či jinak zničí své případné jiné instance, pak je zřejmě na místě říci, že „do tohoto kódu nelze vstoupit vícekrát", míněno současně. V odborné počítačové terminologii se takovýto kód označuje jako nereentrantní (angl.: non-reentrant). Jeho opakem je pak kód reentrantní. Ten si své lokální proměnné (dynamickou instanci) alokuje obvykle na zásobníku, takže si je ani při opakovaném volání nepřepisuje. Do takovéhoto kódu tedy lze „vstupovat vícekrát", bez jakýchkoli omezení.

Reentrantnost určitého kódu je například nezbytnou podmínkou pro možnost přímé i nepřímé rekurze, resp. rekurzivního volání podprogramu. Stejně tak je reentrantnost nutnou podmínkou k tomu, aby jeden a tentýž kód mohlo současně sdílet více procesů, programů či úloh, provozovaných ve víceuživatelském či alespoň víceúlohovém prostředí. Přitom režie, potřebná za zajištění reentrantnosti (připadající např. na použití zásobníku místo pevných míst v paměti) je většinou tam malá, že ji obvykle lze zcela zanedbat. Mohlo by se tedy zdát, že nereentrantní kód by měl být spíše výjimkou než pravidlem.

Existuje však jeden velmi významný příklad nereentrantního kódu, který touto svou vlastností komplikuje život mnoha lidem - zejména pak programátorům. Jde o „starý špatný" operační systém MS DOS. Jak mnozí začínající programátoři s hrůzou zjišťují, a mnohdy až na základě osobních praktických zkušeností, do tohoto operačního skutečně „nelze vstoupit vícekrát". Problémy to způsobuje především těm, kteří pro tento operační systém píší nejrůznější rezidentní programy - pokud tyto rezidentní programy chtějí používat služby operačního systému MS DOS, musí postupovat velmi obezřetně. Musí si vždy nejprve zjistit, zda v daném okamžiku DOS právě „běží" (provádí nějakou svou systémovou službu) nebo nikoli. Pokud ano, musí rezidentní program poníženě počkat, až se nereentrantní veličenstvo DOS uráčí skončit.

Jste-li programátory, a chcete-li se o nereentrantnosti DOSu dozvědět více, stejně tak jako o technikách obcházení této nepříjemnosti, obraťte se raději na jinou než oficiální odbornou literaturu. V té byste totiž hledali marně.