Az DBase nyelv család

Párhuzamosság

Párhuzamosság

Clipper:

A Clipper nyelv még monotaskos operációs rendszerre lett tervezve (DOS), nem támogatja a párhuzamosságot. Ennek ellenére a kódblokk adattípus segítségével meg lehetett valósítani nem valós, de annak tűnő többszálúságot nem preemptív ütemezéssel.

Az alapgondolat

Általánosságban elmondható, hogy a legtöbb Clipperben írt program saját billentyű bekérési függvényt implementál, hogy képernyőkímélőt és más szolgáltatásokat tudjon nyújtani. Ha jobban megvizsgáljuk, a program ebben a függvényben áll 99%-ban (amikor nem valamilyen felhasználói interakcióra reagál). Ez lehetőséget ad rá, hogy ebben a függvényben futtassunk előre megadható kódblokkokat, amik a program futása alatt attól függetlenül futhassanak, hogy éppen a program melyik részén járunk!

A megvalósítás

static aThreadList := {} //Az aThreadList tömb pozíció konstansai #define TLPOS_THREADID 1 //A szál azonosítója #define TLPOS_CODEBLOCK 2 //A futtatandó kódblokk #define TLPOS_NAME 3 //A szál neve #define TLPOS_NEXTRUNDATE 4 //A következő lefutás dátuma #define TLPOS_NEXTRUNTIME 5 //A következő lefutás időpontja #define TLPOS_REPEATINTERVALL 6 //Az ismétlődési periódus ideje //A NewThread() visszatérő hibakódjai #define NTRET_THREADLIMITERR -1 //A szálszám túllépése hiba function NewThread(bThread, sName, dFirstRunDate, cFirstRunTime, nRepeatIntervall) local nThreadId if len(aThreadList) <= 4095 //Szálazonosító képzés if empty(aThreadList) nThreadId := 1 else nThreadId := aThreadList[len(aThreadList), TLPOS_THREADID] endif //Szál adatainak tárolása aadd(aThreadList, {nThreadId, bThread, sName, dFirstRunDate, cFirstRunTime, nRepeatIntervall}) else //Ha nem lehet létrehozni, -1-el visszatérni (hibakód) nThreadId := NTRET_THREADLIMITERR endif return nThreadId function KillThread(nThreadId) local lRet, nPos := ascan(aThreadList, {|x| x[TLPOS_THREADID] = nThreadId}) if nPos > 0 //Ha létezik adel(aThreadList, nPos) asize(aThreadList, len(aThreadList) - 1) lRet := .T. else lRet := .F. endif return lRet function RunThreads() local i, aCurrThread, dNextDay, cNextTime for i := 1 to len(aThreadList) aCurrThread := aThreadList[i] if aCurrThread[TLPOS_NEXTRUNDATE] <= date() .and.; aCurrThread[TLPOS_NEXTRUNTIME] <= time() //Futtat s eval(aCurrThread[TLPOS_CODEBLOCK]) //Ha még kell futtatni, megállapítani a következő időpillanatot if aCurrThread[TLPOS_REPEATINTERVALL] > 0 //Meg llapˇtani az Łj id‹pontot AddSec(aCurrThread[TLPOS_NEXTRUNDATE], aCurrThread[TLPOS_NEXTRUNTIME],; aCurrThread[TLPOS_REPEATINTERVALL], @dNextDay, @cNextTime) //Letárolni az új értékeket aCurrThread[TLPOS_NEXTRUNDATE] := dNextDay aCurrThread[TLPOS_NEXTRUNTIME] := cNextTime else //Hacsak egyszer kellett lefutnia, törölni KillThread(aCurrThread[TLPOS_THREADID]) loop //mivel ki lett törölve, ugyanezen a pozíción levő szállal kell folytatni az aThreadList-ben endif else exit endif next //újrarendezni a tömböt asort(aThreadList, , ,; {|x, y| dtos(x[TLPOS_NEXTRUNDATE]) + x[TLPOS_NEXTRUNTIME] < dtos(y[TLPOS_NEXTRUNDATE]) + y[TLPOS_NEXTRUNTIME]}) return NIL

Megjegyzések

Az itt vázolt implementáció erősen épít rá, hogy a kódblokkokban megadott szálak rövid ideig tartó folyamatot végeznek, pl.: óra kirajzolása, dátum váltás figyelése, stb. Amennyiben olyan funkcionalitást teszünk ilyen szálba, ami jelentősebb ideig megfogja a vezérlést, akkor a felhasználó számára az adatbevitel lelassulhat.
Mivel az implementáció nem preemptív ütemezést valósít meg, ha egy szál végtelen ciklusba kerül, akkor a program további futása sem lesz lehetséges, és kívülről véletlenszerű helyeken fog a programunk „lefagyni”. Ennek megelőzésére ciklusokat csak óvatosan használjunk a szálakban!

FoxPro

A nyelv nem támogatja a párhuzamosságot.