C - Mi az std

Én elég ismerős összetevőinek std :: menet. std :: aszinkron és std :: jövőbeli szabvány standard könyvtár (például, lásd. Ez a válasz), amelyek egyenes vonalú.







Ugyanakkor nem értem, hogy mit jelent std :: ígéretet. mit csinál, és milyen helyzetekben a legjobb, ha használni. A szabványos dokumentum nem tartalmaz sok információt túli szinopszis, és egyikük sem nem könnyű. menet.

Tud valaki kérem, hogy egy rövid, tömör példa arra, hogy mikor kell std :: ígéretet, és ahol ez a leginkább köznyelvi megoldás?

A szavai [futures.state] std :: jövőben - ez egy aszinkron visszatérési objektum ( „objektumot, amely beolvassa az eredményeket az általános állapot”) és std :: ígéret - ez egy aszinkron szolgáltató ( „objektum, amely az eredmény az általános állapot”) ez egy ígéret - ez valami, hogy telepítve van az eredmény, így lehet kapni azt a jövőben.

Aszinkron szolgáltató - az, hogy kezdetben olyan közös állapot, amelyre a jövőben. std :: ígéret - egy olyan típusú aszinkron szolgáltató, std :: packaged_task - a többi, és a belső tag std :: aszinkron - más. Mindegyikük lehet létrehozni egy közös állapot és az Ön std :: jövőben, aki osztja ezt az állapotot, és lehet, hogy egy vagyont kész.

std :: aszinkron - a közüzemi magasabb szintű eszköz, amely megadja az aszinkron eredmény objektumot, és belsőleg gondoskodik létrehozása az aszinkron szolgáltató, valamint az általános felkészültségi állapotáról a befejezése a feladat. Emulálhatja használatával std :: packaged_task (vagy std :: kötődnek és std :: ígéret) és std :: téma, de ez biztonságosabb és könnyebb használni std :: aszinkron.

std :: ígéret - valamivel alacsonyabb szinten, mert ha el szeretné küldeni egy aszinkron eredményeként a jövőben, de a kód, ami az eredmény kész, nem lehet kitölteni egy függvény, amely alkalmas az átmenetet egy std :: aszinkron. Például, akkor van egy sor több ígéret s és a kapcsolódó jövőbeni s és egy szál, amely elvégzi több számítást és az eredmény minden ígéretét. aszinkron csak lehetővé teszi, hogy visszatérjen egy eredmény, hogy visszatérjen egy pár, akkor kell ismételten hívja a aszinkron hívás, ami azt eredményezheti, hogy nem a források.

A C ++, két különböző, de rokon fogalmak: aszinkron számítás (jellemző, hogy az úgynevezett máshol), és a párhuzamos végrehajtás (az áramlás valamit, ami működik ugyanabban az időben.). Ez a két ortogonális koncepciói. Az aszinkron számítás - ez csak egy jó függvényhívásba, míg flow - a végrehajtási környezetet. Szálak alkalmasak magukat, de arra a célra ez a vita, azt fogja kezelni őket, mint egy végrehajtási részletesen.

Van egy hierarchia az absztrakció aszinkron számítás. Tegyük fel például, hogy van egy funkciója, amely néhány érv:

Először is, van egy std :: jövő minta. amely képviseli a jövőbeli értékét típusú T értéket keresztül lehet hozzájutni a tag funkció get (). amely hatékonyan szinkronizálja a program várakozik. Egy másik változat szerint a jövőben is támogatni wait_for (). amelyet fel lehet használni annak ellenőrzésére, hogy az eredmény már rendelkezésre áll. Futures kell tekinteni, mint egy aszinkron csere helyettesítik a hagyományos típusú visszatérés. A mi példaértékű funkció várunk std :: jövő.

Most, a hierarchia, a legmagasabbtól a legalacsonyabb szinten:

std :: aszinkron. A legkényelmesebb és közvetlen módon, hogy végre egy aszinkron számítás - keresztül aszinkron funkció sablon. amely azonnal visszaadja a megfelelő jövőbeni:

Jelenleg nagyon kevés ellenőrzést a részleteket. Különösen azt nem is tudom, ha a funkció végrehajtásakor egyidejűleg, egymást követően get () vagy bármely más fekete mágia. Azonban az eredmény könnyen beszerezhetők, ha szükséges:

Most, hogy hogyan lehet végrehajtani valamit, mint aszinkron. de hogy mi vezérelt. Például tudjuk azt állítják, hogy a funkciója egy külön téma. Azt már tudjuk, hogy biztosítani tudjuk a másik szálat egy osztály std :: menet.

A következő alacsonyabb absztrakciós szinten pontosan ezt teszi: std :: packaged_task. Ez egy minta, amely becsomagolja a funkciót, és egy olyan jövőt a visszatérési értéke a funkció, de a tárgy maga okozza, és nagy kihívás - a felhasználó döntése alapján. Mi lehet beállítani az alábbiak szerint:

A jövőben lesz kész a hívás után célkitűzéseit és hívásvégződtetési. Ez egy ideális munka egy külön áramot. Csak meg kell bizonyosodni arról, hogy mozog a feladat, hogy a stream:

Az adatfolyam azonnal elindul. Mi lehet akár le őt, vagy csatlakozzanak hozzá a végén hatályát, vagy minden alkalommal (például a scoped_thread Anthony Williams, aki tényleg kell a standard könyvtár). Ugyanakkor a részleteket a std :: szál nem érint bennünket; Csak légy biztos, hogy csatlakozzon, vagy húzza ki őket. Fontos, hogy ha egy függvény hívás véget ér, mi az eredmény kész:

Most le a legalsó szinten: hogyan kell végrehajtani egy batch feladatot? Itt van, hogy jön std :: ígéretet. Promise - építőeleme a jövőben a kommunikáció. Mérföldkövek:

A hívó szál tesz ígéretet.

A hívó kap áramot a jövő ígéreteit.

Promise funkciók együtt érvek átvisszük egy külön áramot.

Az új szál végrehajtja a funkció és a töltés a Promise.







Eredmény visszatér tápáram.

Például itt van a saját „csomagolt kihívás”:

Az ezzel a sablon alapvetően ugyanaz, mint az std :: packaged_task. Megjegyezzük, hogy a mozgás az egész probléma kihozza az ígéretet. A bonyolultabb helyzetekben is, akkor is kifejezetten azt ígéri, hogy mozog az objektum egy új szál, és azt a funkcionális érv a menet funkció, de csomagolópapír feladatokat, mint a fenti, úgy tűnik, hogy rugalmasabbá és kevésbé tolakodó megoldás.

Művészet kivételek

Ígéretek szoros kapcsolatban vannak kivételek. Interfész az ígéretek nem elegendőek a teljes közvetíteni az állapota, így kivételt dobott, amikor ígéretet művelet nincs értelme. Minden kivétel típusú std :: future_error. amely abból std :: logic_error. Először is, egy leírást bizonyos korlátozások:

Alapértelmezett épült ígéretet inaktív. Inaktív ígéretek elpusztulhatnak következmények nélkül.

Az ígéret válik aktívvá, amikor a jövő fordul a get_future (). Azonban csak akkor kap egy jövő!

Az ígéret kell végezni akár set_value () vagy a telepítés set_exception () kell állítani set_exception () kifejezés az élet ha a jövőben fel kell használni. Elégedett ígéret die következmények nélkül, és kap () lesz elérhető a jövőben. Ígérd kivéve emelés kivételével tárolja a hívás get () a jövőben. Ha megígéri, hogy nem hal meg, vagy az érték vagy kizárással, hogy () hívás a jövőben vezet kizárásával „ígéretek”.

Itt egy kis sorozat vizsgálatok, amelyek kimutatták a rendkívül változatos intézkedéseket. Először is, a kábelköteg:

Most a teszteket.

1. eset: Az inaktív ígéret

2. eset: Aktív ígéretek nem használt

3. eset: Túl sok határidős

4. eset: Találkozás az ígéret

5. eset: Túl sok elégedettség

Ugyanez kivétel set_value ha egynél több értéket vagy set_value set_exception.

6. eset: kizárása

7. eset: egy ígéret

C ++ végrehajtás osztja határidős meghatározott kis blokkok

Std. prom - az egyik ezek a részek.

Promise - egy továbbító eszköz a visszatérési értéket (vagy kizárás) az áramlás, amely elvégzi a feladatát egy patak, amely a jövőben a funkciót.

Jövőbeli szinkronizálás tárgy köré épül a fogadó végén az ígért csatornát.

Tehát, ha szeretné használni a jövőben, akkor kap az ígéretet, amit használ, hogy az eredmény aszinkron feldolgozás.

Példa az oldalról:

Ennek durva közelítéssel akkor úgy std :: ígérnek a másik végét a std :: jövő (ez nem igaz. De ahhoz, hogy bemutassa, amit gondol, mintha). A fogyasztói oldalon a link fogja használni std :: jövőben az adatok felhasználása az általános állapot, míg a termelő szál használja std :: ígérnek, hogy írjon az általános állapot.

std :: ígéret - csatornát, illetve útvonalat a visszaadott információkat a aszinkron funkciót. std :: jövőben - ez a szinkronizációs mechanizmus, ami a hívó várja meg, amíg visszatér a visszatérési érték átadott std :: ígéret (azaz, hogy be van állítva funkció).

Az aszinkron feldolgozás területén 3 fő célja. Jelenleg a C ++ 11 összpontosít ketten.

A főbb jellemzői szükséges aszinkron logikai:

  1. A probléma (logika, csomagolt tárgy, a funktorhoz), melyik lesz „valahol”.
  2. Tényleges feldolgozó egység - folyamattal, és így tovább D., amely kiváltja ezt a funkciót, amikor a számukra rendelkezésre álló .. Nézd meg a mintázat «Command», hogy egy ötlet, hogyan teszi a fő medence munkás szálak.
  3. Processzor eredményt. valaki szükséges ezt az eredményt, és szüksége volt egy tárgyat, hogy lesz nekik. A PFSZ és egyéb okok miatt, minden várakozás és szinkronizálási kell elvégezni az API e leíró.

C ++ 11 az, amit mondok, hogy (1) std :: ígéretet. valamint (3) std :: jövőben. std :: szál - az egyetlen dolog, ami elérhető az állami (2). Ez azért is sajnálatos, mert a valódi programok szükségesek, hogy ellenőrizzék a áramlását az erőforrások és a memória, és a legtöbbjük szeretné futtatni feladatokkal medencék, patakok, ahelyett, és elpusztítja a menet minden kis probléma (csaknem mindig okoz felesleges képeket az előadás is, és könnyen teremt erőforrások böjtölés még rosszabb).

Mint egy utolsó pont a párt ígéretet / jövőben létrehozott std. get_future () és std :: jövő (létrehozott std get_future () segítségével get_future ().) - ez a másik végpont. Ez egy egyszerű egylépéses módszer, amely lehetővé teszi, hogy szinkronizálja a két áram egy stream adatáramlást egy másik üzenet.

Azt lehet gondolni rá, mint egy szál létrehoz egy ígéret, hogy az adatok, és a másik szál összegyűjti az ígéret a jövőre nézve. Ez a mechanizmus csak egyszer lehet felhasználni.

A mechanizmus az ígéretek / a jövő - ez csak egy az áramlás irányát, amely felhasználja set_value () metódus a std :: ígéret set_value () a menet, amely a get () STD :: jövő adatgyűjtést. Kivételt keletkezik, ha a get () metódus a jövőben az úgynevezett többször.

Ha egy menet std :: ígéret set_value () nem használható set_value (), hogy teljesítse ígéreteit, amikor a második menet felhívja a get () az std :: jövő gyűjteni ígéretet, a második folyam készenléti állapotban marad, amíg az ígéret végzi az első áramlás alkalmazásával std :: ígéret set_value () használata során set_value () metódus adatokat küldeni.

Egy megjegyzés a példában - a késedelem adunk különböző helyeken. Ezek a késések kerültek csak annak biztosítása érdekében, hogy a különböző üzeneteket a konzolra std :: cout. egyértelműek, és a szöveg több szál nem keverhető.

Az első rész a main () létrehoz három további áramlás és használja std :: ígéret és std :: jövő adatok küldésére szálak között. Érdekes kérdés, hogy az áramlás a fő áramlási kezdődik, T2, amely megvárja az adatokat a fő áramlási, valamit csinálni, majd küldje el az adatokat a harmadik folyam T3, ami aztán, hogy tegyen valamit, és elküldi az adatokat vissza a fő áramlását.

A második rész a fő () hoz létre a két szál, és egy várakozási sor készletre vonatkozóan, hogy több üzenetet a fő szál által létrehozott minden egyes két folyamban továbbítjuk. Nem tudjuk használni std :: ígéret és std :: jövőben ezt, mert az ígéret / következő duo - egy lövés, és nem lehet újra felhasználni.

Forrás Sync_queue osztály Stroustrup C ++ programozási nyelv: 4. kiadás.

Ez az egyszerű alkalmazás generálja a következő kimenetet.

Promise - a másik végét a drót.

Képzeljük el, hogy meg kell, hogy az érték a jövőben. számított aszinkron módszer. Azonban, ha nem akarja, hogy kell kiszámítani egy szál, és akkor nem is hozzon létre egy patak „most” - talán a szoftver célja az volt, hogy kiválassza az áramlás a medencét, így nem tudni, ki lesz végez semmilyen leállás végén számítás.

Most, hogy adja át ezt a (még ismeretlen) áramlása / osztály / egység? Nem adja át a jövőben. mivel ez az eredmény. Azt szeretnénk átadni valamit, ami együtt jár a jövőben, és a másik végét a drót. így akkor csak kérjen jövő ismerete nélkül, hogy ki valójában valami számító / írni.

Ez az ígéret. Ez a kar van társítva a jövőben. Ha a jövőben - a hangszóró. és a get () elkezdi hallgatni, amíg meg nem jelenik egy hang, megígérem - ez egy mikrofon; De nem csak a mikrofont egy mikrofon csatlakoztatható egy vezetéket a hangszóró, amit összefogva tart. Akkor tudom, ki a másik végén, de akkor nem kell tudni, hogy ez - csak add fel, és várja meg, amíg a másik fél nem mondott semmit.