A RobotC programozási nyelv

Párhuzamosság

Mivel már egyszerűbb robotikai feladatoknál is megjelenik az igény a párhuzamosságra, ezt nem kerülhették el a nyelv tervezői sem. A nyelvet ellátták taszkokkal.

Egy RobotC program mindig taszkokból áll, legegyszerűbb esetben csak egyből. A C-ben megszokott main függvény itt egy önálló taszk, mely a programunk indításakor automatikusan elindul.

A nyelv a statikus párhuzamosságot támogatja. Ez abból áll, hogy csak a forráskód szintjén hozhatunk létre folyamatokat, a folyamatok száma fordítási időben meghatározható.

Taskok definiálása

A taszkok definiálásának helyes módja a task kulcsszó segítségével:

task main() { ... return; }

Amint a fenti kódban látható, taszkot egy üres return; utasítással tudunk taszkon belül befejezni.

Taszkok indítása, leállítása, felfüggesztése

A RobotC nyelv taszkjaihoz teljes hozzáférésünk van, nincsenek korlátozások. Bármelyik taszk leállíthatja, vagy szüneteltetheti a többi taszkot akár explicit paranccsal is.
A taszkokon végzett műveletek:

task moveRobot() { while(true) { ... // do some moving around StartTask(scanWithHead); wait1MSec(5000); StopTask(scanWithHead); StartTask(calculateSomeThingBig); } return; } task scanWithHead() { while(true) { ... // scan with the head ... // write the data to some global variable } return; } task calculateSomethingBig() { // instead of waiting // pause all the other tasks // to have full resources hogCPU(); ... releaseCPU(); return; } task main() { StartTask(moveRobot); while(true) { ... // display something on the // robots lcd screen for example } }

Prioritások

A RobotC lehetőséget ad a taszkok prioritásának állítására is.

Egy taszk megmondhatja magáról, mekkora prioritása legyen. Erre lehetőséget a

nSchedulePriority = 2;
módon tehetjük meg. Ez a változó alapértelmezett változója minden taszknak.

A default prioritás minden taszknak 7, amit 0-tól 255-ig változtathatunk.
A prioritások száma nem arányos a kapott ütemezési időszelettel.
Egy prioritásos sor alapján mindig a legnagyobb prioritású taszk kapja meg az ütemezést, ha pedig ezekből több van, a round robin ütemezést használja a futtató rendszer.

Gyakorlati használat, fontos tudnivalók

Egy RobotC program minden változója a globális térben van. Az azonos prioritáson lévő taszkok teljesen aszinkron módon futnak, szinkronizálási lehetőségünk csak a hogCPU() és releaseCPU() parancsokon keresztül van.
Tegyük fel, hogy két taszk ugyanazt a függvény szeretné használni.
Mivel a háttérben minden változó globális, az aszinkron függvényhívások elrontják egymás eredményét.
Az alábbi, nagyon egyszerű példa elromlik egy kedvezőtlen ütemezés esetén.

int add(int a, int b) { int ret = a; return ret+b; } task main() { StartTask(other); motor[motorA] = add(SensorValue(lightSensor), 10); } task other() { motor[motorA] = add(SensorValue(sonarSensor), 20); }

A fenti kód lefuttatásakor nem egyértelmű, hogy melyik szenzor értékét fogjuk figyelembe venni az A motor sebességének meghatározásakor. A szándékosan egyszerűre, de többsorosra írt add() függvény kódját nézve képzeljük el, ahogyan a main() taszk belép a függvénybe, meghatározza a ret értékét, majd elveszi tőle a vezérlést a futtató környezet, és azt odaadja az other() taszknak. Az other() taszk beállítja a ret értékét, és tegyük fel, hogy tőle is elveszi a környezet a vezérlést.
Újra a main() taszk fut, de a ret változóban már az ultrahang szenzor értéke van, nem a fényszenzoré! Hibás értékkel fog visszatérni a függvény.

Általános tanácsként a nyelv tervezői, illetve gyakorlottabb felhasználói ilyen esetekben a függvények inline-osítását javasolják.
A jelenség a futtató környezet heap-nélküliségéből, és butított stack-jéből ered. A nyelv hivatalos fórumán időről-időre felvetődik a probléma, de a tervezők eddig még nem álltak elő semmilyen orvoslattal.

Ökölszabály: ha többszöri átnézés után is nemdeterminisztikusan viselkedik a programunk, gyanakodjunk a párhuzamosságra, és védjük le a kritikusnak számító részeket a hog-release módszerrel.
Óvatosan bánjunk a világ megállításával (hog-release), mert ha túl gyakran alkalmazzunk, szekvencializálódhat tőle az egyébként párhuzamosnak szánt program.