1

Téma: Generalizace asynchronního volání funkcí SDS-C

SDS-C program je prováděn synchronně s tím, že volání interních funkcí je vždy neblokující. Tedy funkce, jejichž provádění může trvat delší dobu jsou voláním interní funkce inicializovány a dokončení probíhá jako jiný nezávislý běh. Výsledek provedení funkce se vrací do SDS-C v nějaké systémové proměnné (je potřeba jej ve smyčce kontrolovat). Takové kontroly musejí být "rozesety" pro obsluhu všech takových případů v hlavním cyklu - kód obsluhy konkrétní funkcionality je tak roztroušen nesourodě na více místech.

Navrhuji implementovat možnost volat funkce SDS-C asynchronně a doplnit interní funkce o možnost předávat jako parametr jméno funkce, která má být po jejich vykonání provedena (jednoduchá podpora zpracování událostí). Tím se zpřehlední kód a otevřou se možnost pro další využití mechanizmu asynchronního volání funkcí, např. RPC, funkční bloky časovačů, atp.

Nebo (to by bylo ještě srozumitelnější pro vývojáře navyklé na synchronní programování) něco jako protothready - možnost spustit více vláken kódu současně a při volání blokující funkce prostě vyčkat do jejího dokončení přičemž ostatní vlákna budou prováděny dále. Inspirace:
http://zolertia.sourceforge.net/wiki/in … i_Lesson_0
http://www.sics.se/~adam/contiki/contik … 00269.html

2

Re: Generalizace asynchronního volání funkcí SDS-C

Já vím, bude to otřepaná a neoblíbená fráze - jde to realizovat už s tím, co SDS-C umí teď.

Podívejte se na zdrojové kódy Protothreadů od Adam Dunkelse - v podstatě viz uvedené odkazy. Není to o ničem jiném, než že se jedná o "hezčí" způsob zápisu vlastních kousků kódu do if-then a switch konstrukcí. Prakticky se jedná o #define jednotlivých částí switch deklarace, a spolupracujícího kódu, takže ve výsledku je možné spustit více "vláken" "najednou".
Výhodou pak je, že programátor se nemusí zabývat s psaním všeho kolem, ale jen rychle dá dohromady samotný svůj kód.

S trochou invence lze totéž napsat v SDS-C, potřeba bude pro každé vlákno definovat si jedinou stavovou proměnnou (nahrazující funkci "pt" u Protothreads) a pak pomocí několika if-ů napsat obsah funkce konkrétního vlákna. Potom ve smyčce např. ve funkci main neustále dokola volat jednotlivé funkce jednotlivých threadů, které se pak vždy podle své stavové proměnné zařídí tak, jak je aktuálně potřeba (např. provedou kus kódu, nebo pokud se čeka na něco tak return, a tak dále). Díky tomu budou všechny tyto vlákna fungovat společně, je to jen o tom, jak se to tomu kterému programátorovi podaří napsat.

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

3

Re: Generalizace asynchronního volání funkcí SDS-C

Ano, v rámci SDS-C prostředí to jde udělat, ale těžkopádně (nečitelně, s velmi omezenou znovupoužitelností, bez jasného design paternu) - jak píšete. Proto použitelnost pro nemalou část vývojářů bude malá. Většinou stojíte před problémem typu - vyplatí se investovat čas do nové vlastnosti XYZ, aby to pomohlo podstatné části vývojářů či obecně použitelnosti produktové řady SDS ?  Tato generalizace (a odlišný přístup při zpracování více smyček=vláken) za to možná bude stát ;-)

Problém ovšem nastává při interakci mezi vlákny a ostatními částmi SDS. Pokud ostatní části SDS nebudou API (a způsob zpracování) vláken podporovat, těžko se budou doplňovat např. funkční bloky časovačů, WEB RPC se bude muset implementovat (pokud je budete implementovat) čistě jen pro tento účel atd.

4

Re: Generalizace asynchronního volání funkcí SDS-C

Je potřeba začít postupně... uděláme to tak, že zavedeme vyhrazený název pro funkce, kde každá s tímto názvem bude představovat vlákno.

Dá se to zřejmě v příští verzi SDS-C.

Příklad:

thread
{
   //nejaky test
   if (sys[1234] != 0) return;
   //akce
   sys[5678] = 100;  
}

thread
{
   if (sys[1111] == ram[123])
   {
      sys[1234] = 888;
   }  
}

main
{
   // toto je bráno jako další thread, jen to má název main,
   // platí zde stejná pravidla jako pro další thready
}

Takto bude možno definovat více funkcí, každá však bude muset mít jméno thread.

Tyto funkce budou systémem spouštěny neustále dokola, systémem round-robin.

Pokud některý thread zavolá nějakou funkci, bude systém zablokován, dokud konkrétní thread nedojde svého konce funkce. Stejně tak jako např. u pT nelze použít smyčky v threadech, protože by se pak systém zablokoval v daném threadu. Celé je to však velmi elegantně řešitelné, pomocí správného zápisu kódu (viz v příkladu výše, kde je ten if - v běžném programu by tam byla smyčka, ale takhle ji "rozpadneme" a tím umožníme život i ostatním paralelním vláknům).

Pozn. přístup k sys[] a ram[] je atomický, takže tady problém nebude.

Co se týká případných funkčních bloků, tak když bude například k dispozici jediným (např. PID), tak zkrátka bude jediný a bude jej moct používat vždy jen jeden thread. Pokud by do toho zasahovalo více threadů, pak je to smůla programátora... ale zase, cokoliv si může realizovat sám... viz příklad realizace PID regulátoru v SDS-C na WiKi.

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

5

Re: Generalizace asynchronního volání funkcí SDS-C

Vyhrazený název pro funkce je výborný nápad, jen by nešel stejný zápis použít pro WEB RPC. Co třeba použít typ ?

Blokování v případě volání funkce v SDS-C je také rozumný postup.

Ovšem případný zmatek u funkčních bloků ala interních funkcí (echo, http_get, ping, smtp_send, ... a při případní nových časovače, pid, ...) je méně akceptovatelný.
Přehlednější (a méně náchylné na chyby) může být blokování příslušného "threadu" (doporučuji pojmenovat spíše "part" nebo jinak aby se nezaměňovalo s funkčností threadů či tasků) do doby ukončení příslušné interní funkce.

Zápis co navrhujete sice elegantně řeší jednopodmínkové "čekání", ale u více sekvenčních podmínek se stává stejně nepřehledným. Např. při posílání více emailů - oč jednodušší by bylo prostě za sebou zavolat smtp_send než ošetřovat čekání na dokončení ... (či http_get, obsluha sériového portu, ...).

Při omezeném počtu threadů a interních funkcí (bloků) nebude obsluha takového mechanizmu náročná a umožní navíc jednoduchou synchronizaci threadů (pokud je necháte pojmenovány, aby se na ně dalo odkazovat) s pomocí primitivních interních funkcí:
- pause(thread_name)
- continue(thread_name)
Bylo by třeba zařídit přeskakování v round-robin, asociovat prováděnou interní funkci s threadem po dobu jejího provádění, kontrolovat zda thread nečeká na aktuálně obsazenou interní funkci a uchovávat pozici pro pokračování v SDS-C pro každý thread. Pokud by stejnou interní funkci volal jiný thread, byl by systémově zastaven do doby než bude funkce uvolněna.

Při inicializaci by všechny byly v pause stavu a v init se pustily jen ty, co mají být prováděny kontinuálně.
Ty co jsou jen jednorázové (např. při nějaké události) se pak dají snadno spustit a samy sebe mohou na konci uspat.

Pokud budete chtít držet kompatibilitu, tak volání interních funkcí z non-thread funkcí zůstane neblokující.

Jak se Vám to jeví ?

Je to sice trochu více práce na implementaci, ale výsledek za to možná stojí.