Thunk - Thunk
V programování počítače , je thunk je podprogram používá k injekci výpočet do jiného podprogramu. Thunky se primárně používají ke zpoždění výpočtu, dokud není potřeba jeho výsledek, nebo k vložení operací na začátek nebo konec druhého podprogramu. Mají mnoho dalších aplikací při generování kódu kompilátoru a modulárním programování .
Termín vznikl jako rozmarná nepravidelná forma „myslet“. Odkazuje na původní použití thunků v kompilátorech ALGOL, které vyžadovalo speciální analýzu (myšlenku) k určení, jaký typ rutiny generovat.
Pozadí
V počátcích výzkumu kompilátoru došlo k rozsáhlému experimentování s různými hodnotícími strategiemi . Klíčovou otázkou bylo, jak sestavit volání podprogramu, pokud argumenty mohou být libovolné matematické výrazy spíše než konstanty. Jeden přístup, známý jako „ volání podle hodnoty “, vypočítá všechny argumenty před voláním a poté předá výsledné hodnoty podprogramu. V konkurenčním přístupu „ volání podle jména “ podprogram obdrží nevyhodnocený argumentový výraz a musí jej vyhodnotit.
Jednoduchá implementace „volání podle jména“ může nahradit kód výrazu argumentu pro každý výskyt odpovídajícího parametru v podprogramu, ale toto může vytvořit více verzí podprogramu a více kopií kódu výrazu. Jako vylepšení může kompilátor generovat pomocný podprogram nazývaný thunk , který vypočítá hodnotu argumentu. Adresa a prostředí tohoto pomocného podprogramu jsou poté předány původnímu podprogramu místo původního argumentu, kde jej lze vyvolat tolikrát, kolikrát je potřeba. Peter Ingerman nejprve popsal thunky v odkazu na programovací jazyk ALGOL 60 , který podporuje vyhodnocení podle jména.
Aplikace
Funkcionální programování
Ačkoli softwarový průmysl do značné míry standardizoval hodnocení podle hodnoty a volání podle odkazu , aktivní studium volání podle jména pokračovalo v komunitě funkcionálního programování . Tento výzkum vytvořil řadu líných programovacích jazyků hodnocení, ve kterých je standardní strategií hodnocení nějaká varianta volání podle jména. Kompilátory pro tyto jazyky, jako je kompilátor Glasgow Haskell , se velmi spoléhaly na thunky, s přidanou funkcí, že thunks ukládají svůj počáteční výsledek, aby se mohli vyhnout jeho přepočítání; toto je známé jako memoization nebo call-by-need .
Funkční programovací jazyky také umožnily programátorům explicitně generovat thunky. To se provádí ve zdrojovém kódu zabalením výrazu argumentu do anonymní funkce, která nemá žádné vlastní parametry. Tím se zabrání vyhodnocení výrazu, dokud přijímající funkce nezavolá anonymní funkci, čímž se dosáhne stejného efektu jako volání podle jména. Díky přijetí anonymních funkcí do jiných programovacích jazyků je tato funkce široce dostupná.
Následuje jednoduchá ukázka v jazyce JavaScript (ES6):
// 'hypot' is a binary function
const hypot = (x, y) => Math.sqrt(x * x + y * y);
// 'thunk' is a function that takes no arguments and, when invoked, performs a potentially expensive
// operation (computing a square root, in this example) and/or causes some side-effect to occur
const thunk = () => hypot(3, 4);
// the thunk can then be passed around without being evaluated...
doSomethingWithThunk(thunk);
// ...or evaluated
thunk(); // === 5
Objektově orientované programování
Thunks jsou užitečné v objektově orientovaného programování platformy, které umožňují třídu pro dědí více rozhraní , což vede k situaci, kdy stejný postup by mohl být volán prostřednictvím některého několik rozhraní. Následující kód ilustruje takovou situaci v C ++ .
class A {
public:
virtual int Access() const { return value_; }
private:
int value_;
};
class B {
public:
virtual int Access() const { return value_; }
private:
int value_;
};
class C : public A, public B {
public:
int Access() const override { return better_value_; }
private:
int better_value_;
};
int use(B *b) { return b->Access(); }
int main() {
// ...
B some_b;
use(&some_b);
C some_c;
use(&some_c);
}
V tomto případě bude kód generovaný pro každou ze tříd A, B a C obsahovat tabulku odeslání, kterou lze použít k volání Accessna objekt tohoto typu prostřednictvím odkazu, který má stejný typ. Třída C bude mít další expediční tabulku, která se používá k volání Accessna objekt typu C prostřednictvím odkazu typu B. Výraz b->Access()bude používat vlastní dispečerskou tabulku B nebo doplňkovou tabulku C, v závislosti na typu objektu, na který b odkazuje. Pokud odkazuje na objekt typu C, kompilátor musí zajistit, aby Accessimplementace C obdržela adresu instance pro celý objekt C, nikoli zděděnou část B tohoto objektu.
Jako přímý přístup k tomuto problému s úpravou ukazatele může kompilátor zahrnout celočíselný posun do každé položky tabulky odeslání. Tento posun je rozdíl mezi adresou odkazu a adresou požadovanou implementací metody. Kód vygenerovaný pro každé volání prostřednictvím těchto dispečerských tabulek pak musí načíst offset a použít ho k úpravě adresy instance před voláním metody.
Právě popsané řešení má problémy podobné dříve naivní implementaci call-by-name popsané dříve: kompilátor generuje několik kopií kódu pro výpočet argumentu (adresy instance) a současně zvyšuje velikosti dispečerské tabulky pro udržení ofsetů. Jako alternativu může kompilátor vygenerovat seřizovač thunk spolu s implementací C, Accesskterá upraví adresu instance o požadovanou částku a poté zavolá metodu. Thunk se může objevit v expediční tabulce C pro B, čímž se eliminuje potřeba, aby si volající sami upravovali adresu.
Numerické výpočty vyžadující vyhodnocení ve více bodech
Rutiny pro výpočty, jako je integrace, potřebují vypočítat výraz ve více bodech. K tomuto účelu bylo použito volání podle jména v jazycích, které nepodporovaly zavírání ani parametry procedur .
Interoperabilita
Thunks byl široce používán k zajištění interoperability mezi softwarovými moduly, jejichž rutiny si nemohou navzájem přímo volat. K tomu může dojít, protože rutiny mají různé konvence volání , běží v různých režimech CPU nebo adresních prostorech nebo alespoň jeden běží ve virtuálním počítači . Kompilátor (nebo jiný nástroj) může tento problém vyřešit vygenerováním thunku, který automatizuje další kroky potřebné k volání cílové rutiny, ať už jde o transformaci argumentů, jejich zkopírování do jiného umístění nebo přepnutí režimu CPU. Úspěšný thunk minimalizuje práci navíc, kterou musí volající provést ve srovnání s běžným hovorem.
Velká část literatury týkající se interoperability thunks se týká různých platforem Wintel , včetně MS-DOS , OS/2 , Windows a .NET , a přechodu z adresování 16bitové na 32bitovou paměť. Vzhledem k tomu, že zákazníci migrovali z jedné platformy na druhou, byly Thunks zásadní pro podporu staršího softwaru napsaného pro starší platformy.
Přechod z 32bitového na 64bitový kód na x86 také používá formu thunkingu (WoW64). Protože je však adresní prostor x86-64 větší než ten, který je k dispozici pro 32bitový kód, starý mechanismus „generic thunk“ nelze použít k volání 64bitového kódu z 32bitového kódu. Jediným případem 32bitového kódu, který volá 64bitový kód, je to, že WoW64 završil Windows API na 32bitové.
Překryvy a dynamické propojení
Na systémech, kterým chybí automatický hardware virtuální paměti , mohou Thunks implementovat omezenou formu virtuální paměti známou jako překryvy . Pomocí překryvů vývojář rozdělí kód programu na segmenty, které lze nezávisle načíst a uvolnit, a identifikuje vstupní body do každého segmentu. Segment, který volá do jiného segmentu, to musí udělat nepřímo prostřednictvím větvící tabulky . Když je segment v paměti, jeho položky tabulky větví skočí do segmentu. Když je segment uvolněn, jeho položky jsou nahrazeny „znovu načíst thunky“, které jej mohou na požádání znovu načíst.
Podobně systémy, které dynamicky propojují moduly programu společně za běhu, mohou k připojení modulů používat thunky. Každý modul může volat ostatní pomocí tabulky hromů, kterou linker vyplní při načtení modulu. Tímto způsobem mohou moduly interagovat bez předchozí znalosti o tom, kde jsou umístěny v paměti.
Viz také
Thunk technologie
- Rozhraní DOS Protected Mode Interface (DPMI)
- Služby chráněného režimu DOS (DPMS)
- J/Přímý
- Microsoft Layer pro Unicode
- Platforma Invocation Services
- Win32s
- Windows na Windows
- WoW64
- libffi
Související pojmy
- Anonymní funkce
- Budoucnosti a sliby
- Vzdálené volání procedury
- Podložka (výpočetní)
- Trampolína (výpočetní technika)
- Redukovatelný výraz