next up previous
Next: Ein einfaches Beispiel mit Up: Sprachmittel zur Synchronisierung Previous: Bedingungen

Scheduling

Während für das Scheduling von Threads und Prozessen das Betriebssystem zuständig ist, muß dies bei Koroutinen von der Programmiersprache oder der Bibliothek gelöst werden. In der Ulmer Oberon-Bibliothek ist die Schnittstelle hierfür Tasks, wobei es möglich ist, selbst eigene Scheduler zu definieren und sogar mehrere gleichzeitig zu verwenden in Form einer hierarchischen Struktur. Im Normalfall dürften allerdings die Voreinstellungen reichen, die einen Scheduler auf Basis des Round-Robin-Schemas vorsehen[*]

Da Koroutinen nicht durch die Bibliothek verwaltet werden, gibt es für den Scheduler handhabbare konkurrierende Einheiten den Datentyp Tasks.Task. Normalerweise ist eine Task direkt einer Koroutine zugeordnet - aber dies muß nicht sein, da auch häufig Koroutinen kreiert werden, die den Schedulern nicht direkt bekannt sind.[*] Wenn eine Koroutine mit Tasks.Create zur Task erhoben und damit einem Scheduler bekannt gemacht wird, dann ist es nicht mehr notwendig, sich um die Aktivierung dieser Koroutine zu kümmern, da dies dann in der Verantwortung des Schedulers liegt.


 
Abbildung:  Zustandsübergänge für Tasks
\begin{figure}
\epsfig {file=task-states.eps}
\end{figure}

Verbunden mit dem Leben einer Task sind folgende Grundoperationen, die jeweils zu Zustandsübergängen führen, die in Abbildung 7.4 dargestellt sind:

Tasks.Create
kreiert eine Task, die zunächst mit der gegebenen Koroutine assoziiert ist, deren Aktivierung von nun an in der Verantwortung des Schedulers liegt. Ihr Zustand ist zunächst ready, d.h. sie ist rechenbereit, aber zur Zeit noch nicht aktiv.

Tasks.Dispatch
wird von dem Scheduler aufgerufen, um eine Task zu aktivieren - sie ist anschließend im Zustand running.

Tasks.WaitFor
erlaubt dann das Suspendieren einer Task, bis eine Bedingung wahr wird. Alternativ können auch Tasks.WaitForOneOf oder Tasks.Select verwendet werden. Eine Task ist dann im Zustand waiting.

Conditions.Test
ist die wichtigste Operation um später festzustellen, ob eine Task wieder aufgeweckt werden kann, da ihre Wartebedingung erfüllt ist.

Tasks.Suspend
ermöglicht einen Zustandsübergang von running zu ready. Dies wird nur in Fällen rechenintensiver Tasks verwendet, um etwas Fairneß den anderen Tasks gegenüber zu üben.

Tasks.Terminate
terminiert die aufrufende Task und führt sie in den Zustand terminated. Wichtig ist hier, daß eine Task nur sich selbst terminieren kann - eine zu dem UNIX-Systemaufruf kill() vergleichbare Operation ist nicht vorgesehen, da damit die Nachweisbarkeit eines korrekten Programmablaufs unglaublich erschwert wird.

next up previous
Next: Ein einfaches Beispiel mit Up: Sprachmittel zur Synchronisierung Previous: Bedingungen
Andreas Borchert
2/2/1998