Difference between revisions of "Lib/sequencer offers Multitasking"

From Liberty Eiffel Wiki
Jump to navigation Jump to search
(still translating)
m
 
(34 intermediate revisions by 3 users not shown)
Line 1: Line 1:
[[Category:Book]]
+
[[Category: Library]]
  +
The <tt>lib/sequencer</tt> library implements an event-driven, priority-based, cooperative multitasker. The sequencer library does not start new threads or any other separate processes. Unlike "pure" cooperative multitasking, a task cannot stop at any time (using a hypothetical <tt>yield</tt> feature) but only in known and stable states. The sequencer library does it this way to retain conformance to Eiffel principles.
*** OK, I'm translating that --[[User:Cadrian|Cyril]] 14:34, 4 Jan 2006 (CET)
 
   
  +
The sequencer library concepts:
The <tt>lib/sequencer</tt> library implements one kind of cooperative multi-tasking of the event-driver kind. Unlike "pure" cooperative multi-tasking, a task cannot stop at any time (using an hypothetic <tt>yield</tt> feature) but only in lnown and stable states. That is conform to the Eiffel principles.
 
   
  +
* the class [[library_class:LOOP_STACK|<tt>LOOP_STACK</tt>]] manages the multitasking;
The principle is:
 
  +
* the class [[library_class:JOB|<tt>JOB</TT>]] represents a task. The task core is the <tt>continue</tt> feature, during the execution of which the task controls the whole system;
  +
* the class [[library_class:EVENTS_SET|<tt>EVENTS_SET</tt>]] describes the condition(s) in which a task can be executed.
   
  +
We will successively document each of these concepts:
* the class [[library_class:LOOP_STACK|<tt>LOOP_STACK</tt>]] manages the multi-tasking;
 
* the class [[library_class:JOB|<tt>JOB</TT>]] represents a task. The task core is the <tt>continue</tt> feature, in which the task controls the whole system;
 
* the class [[library_class:READY_DESCRIPTION|<tt>READY_DESCRIPTION</tt>]] allows to describe in which conditions a task can be executed.
 
   
  +
== The multitasking manager ==
We will successively see each of those concepts.
 
  +
The class [[library_class:LOOP_STACK|<tt>LOOP_STACK</tt>]] is in charge of managing the multitasking. It is used in two steps:
 
  +
* initialization: creation of the <tt>LOOP_STACK</tt> object and adding the task(s) to be executed
== The multi-tasking manager ==
 
The class [[library_class:LOOP_STACK|<tt>LOOP_STACK</tt>]] is in charge of managing the multi-tasking. It is used in two steps:
 
* initialisation: creation of the <tt>LOOP_STACK</tt> object, and adding of the tasks to execute
 
 
* execution: execution of the <tt>run</tt> feature
 
* execution: execution of the <tt>run</tt> feature
   
Of course, tasks can be added during the execution. The manager can also be stopped, thanks to the <tt>break</tt> feature.
+
Of course, additional tasks can be added during the execution. The manager can also be stopped, thanks to the <tt>break</tt> feature.
  +
  +
Note that the loop stack contains many execution loops ([[library_class:LOOP_ITEM|<tt>LOOP_ITEM</tt>]]). This allows, for instance, the implementation of a kind of ''modality'' (e.g. the modal windows in [[lib/vision|Vision]]).
   
  +
== Tasks ==
Also, the loops stack is composed of many execution loops ([[library_class:LOOP_ITEM|<tt>LOOP_ITEM</tt>]]). This allows, for instance, the implementation of a kind of ''modality'' (see the modal windows in [[lib/vision|Vision]]).
 
   
  +
A task has a life cycle represented by the features executed by the manager (indeed a [[library_class:LOOP_ITEM|<tt>LOOP_ITEM</tt>]] hence the export clauses of those features).
<!--
 
== Les tâches ==
 
   
  +
# <tt>prepare</tt> allows preparing the task; in this phase, the task sets the events upon which it wants to be activated. The [[library_class:EVENTS_SET|<tt>EVENTS_SET</tt>]] object is an object upon which one can set conditions (thanks to its <tt>expect</tt> feature).
Une tâche a un cycle de vie qui se représente par les méthodes qui sont exécutées par le gestionnaire (en fait un [[library_class:LOOP_ITEM|<tt>LOOP_ITEM</tt>]] d'où les clauses d'export de ces fonctions).
 
  +
# <tt>is_ready</tt> allows to test if the task has really been activated. The [[library_class:EVENTS_SET|<tt>EVENTS_SET</tt>]] object is an object upon which one can test conditions (thanks to its <tt>event_occurred</tt> feature).
  +
# <tt>continue</tt> contains the execution body of the task, and is executed upon task activation.
  +
# <tt>done</tt> tells if the task has finished its execution. If so, it will be removed from the execution loop. Otherwise, the cycle begins again.
  +
# <tt>restart</tt> allows reinserting a task in the execution loop.
   
  +
The <tt>restart</tt> feature is seldom useful. See [[lib/vision|Vision]] for some use cases.
# <tt>prepare</tt> permet de préparer la tâche&nbsp;; dans cette phase, la tâche positionne les événements sur lesquels elle souhaite être activée. L'objet [[library_class:READY_DESCRIPTION|<tt>READY_DESCRIPTION</tt>]] est un objet sur lequel on peut positionner des conditions (grâces à ses méthodes <tt>when_*</tt>).
 
# <tt>is_ready</tt> permet de tester si la tâche a vraiment été activée. L'objet [[library_class:READY_DESCRIPTION|<tt>READY_DESCRIPTION</tt>]] est un objet sur lequel on peut tester des conditions (grâces à ses méthodes <tt>is_*</tt>).
 
# <tt>continue</tt> contient le corps de l'exécution de la tâche, si celle-ci est effectivement activée.
 
# <tt>done</tt> permet de dire si la tâche a terminé de s'exécuter. Dans ce cas, elle sera supprimée de la boucle d'exécution. Dans le cas contraire, le cycle recommence.
 
# <tt>restart</tt> permet de réinjecter une tâche dans la boucle d'exécution.
 
   
  +
== Execution conditions ==
La fonction <tt>restart</tt> est rarement utile. Voir [[lib/vision|Vision]] pour des exemples d'utilisation.
 
   
  +
The class [[library_class:EVENTS_SET|<tt>EVENTS_SET</tt>]] allows to set and test conditions ([[library_class:EVENT_DESCRIPTOR|<tt>EVENT_DESCRIPTOR</tt>]]s).
== Conditions d'exécution ==
 
   
  +
The possible conditions are:
La classe [[library_class:READY_DESCRIPTION|<tt>READY_DESCRIPTION</tt>]] permet de positionner des conditions et de les tester. Les conditions possibles sont&nbsp;:
 
   
* '''Le temps'''&nbsp;: ceci permet de créer des tâches périodiques. Voir les classes [[library_class:PERIODIC_JOB|<tt>PERIODIC_JOB</tt>]] et [[library_class:BACKGROUND_JOB|<tt>BACKGROUND_JOB</tt>]]&nbsp;;
+
* '''Time''': this allows to create periodic tasks. See the classes [[library_class:PERIODIC_JOB|<tt>PERIODIC_JOB</tt>]], [[library_class:BACKGROUND_JOB|<tt>BACKGROUND_JOB</tt>]], and [[library_class:TIME_EVENTS|<tt>TIME_EVENTS</tt>]];
* '''Les entrées-sorties'''&nbsp;:
+
* '''Input-output''':
  +
** ''Data on an input stream'': this allows to build tasks that wait for input data to be available (feature [[library_class:INPUT_STREAM|<tt>INPUT_STREAM</tt>]]<tt>.event_can_read</tt>),
** ''Les données sur un flux d'entrée''&nbsp;: ceci permet de créer des tâches en attente sur la disponibilité de données en entrée (méthodes <tt>when_data</tt> et <tt>is_data</tt>),
 
  +
** ''Data on an output stream'': this allows to build tasks that wait until they can write on an output stream (feature [[library_class:OUTPUT_STREAM|<tt>OUTPUT_STREAM</tt>]]<tt>.event_can_write</tt>);
** ''Les données sur un flux de sortie''&nbsp;: ceci permet de créer des tâches qui ne s'activent que quand elles peuvent écrire sur un flux de sortie (méthodes <tt>when_free</tt> et <tt>is_free</tt>)&nbsp;;
 
  +
* '''Network''': this allows to build tasks waiting network connections (feature [[library_class:SOCKET_SERVER|<tt>SOCKET_SERVER</tt>]]<tt>.event_connection</tt>).
* '''Le réseau'''&nbsp;: ceci permet de créer des tâches en attente d'une connection réseau (méthodes <tt>when_connection</tt> et <tt>is_connection</tt>).
 
   
  +
== Tasks scheduling ==
== Le déroulement des tâches ==
 
   
  +
The manager implements the following cycle:
Le gestionnaire implante le cycle suivant&nbsp;:
 
   
* appel de la méthode [[library_class:READY_DESCRIPTION|<tt>READY_DESCRIPTION</tt>]].<tt>reset</tt>&nbsp;;
+
* call to the feature [[library_class:EVENTS_SET|<tt>EVENTS_SET</tt>]]<tt>.reset</tt>;
* appel de la méthode <tt>prepare</tt> sur chaque tâche&nbsp;;
+
* call to the feature [[library_class:JOB|<tt>JOB</tt>]]<tt>.prepare</tt> on each task;
* appel de la méthode [[library_class:READY_DESCRIPTION|<tt>READY_DESCRIPTION</tt>]].<tt>wait</tt> pour attendre qu'au moins une des conditions se réalise&nbsp;;
+
* call to the feature [[library_class:EVENTS_SET|<tt>EVENTS_SET</tt>]]<tt>.wait</tt> to wait for at least one condition to happen;
* appel de la méthode <tt>is_ready</tt> sur chaque tâche&nbsp;;
+
* call to the feature [[library_class:JOB|<tt>JOB</tt>]]<tt>.is_ready</tt> on each task;
* pour chaque tâche prête, appel de la méthode <tt>continue</tt>&nbsp;;
+
* for all the ready tasks, call to the feature [[library_class:JOB|<tt>JOB</tt>]]<tt>.continue</tt>;
  +
* for those tasks, call to the feature [[library_class:JOB|<tt>JOB</tt>]]<tt>.done</tt> and if relevant, remove the task;
* sur ces mêmes tâches, appel de la méthode <tt>done</tt> et le cas échéant, suppression de la tâche de la boucle&nbsp;;
 
  +
* and back to the beginning.
* et on recommence.
 
   
== Les priorités ==
+
== Priorities ==
   
  +
Tasks execution is by priority order. Only the ready task with the ''lowest'' priority is executed. All other tasks, even if ready, will have to wait until no other task with a lower priority is ready.
Les tâches sont exécutées par ordre de priorité. Seules les tâches prêtes les plus prioritaires sont exécutées. Les autres, même si elles sont prêtes, devront attendre un futur tour où d'autres tâches plus prioritaires ne seront pas prêtes.
 
   
  +
-note: we need to document how many priority levels <br> are supported and how the scheduling works when multiple or all tasks were given<br> an identical priority level. Would the scheduler then resort to some sort<br> of round-robin method? By what rules? Apparently '''not''' by evaluating the duration of the<br> wait for next execution, see the '''LOOP_ITEM.run''' method. /HZ
'''Noter''' que les tâches les plus prioritaires sont celles qui ont le ''plus petit numéro''.
 
   
  +
== Libraries using the sequencer ==
== Bibliothèques utilisant le séquenceur ==
 
   
* [[lib/net]]&nbsp;: les serveurs permettent en général d'accepter plusieurs connections simultanées. Ceci est implanté grâce à un séquenceur.
+
* [[lib/net]]: servers usually allow many simultaneous connections. This is implemented with the sequencer library.
   
* [[lib/vision]]&nbsp;: la boucle de gestion d'événements est implantée grâce à un séquenceur.
+
* [[lib/vision]]: the event manager loop is implemented with a sequencer.
-->
 

Latest revision as of 12:25, 1 January 2022

The lib/sequencer library implements an event-driven, priority-based, cooperative multitasker. The sequencer library does not start new threads or any other separate processes. Unlike "pure" cooperative multitasking, a task cannot stop at any time (using a hypothetical yield feature) but only in known and stable states. The sequencer library does it this way to retain conformance to Eiffel principles.

The sequencer library concepts:

  • the class LOOP_STACK manages the multitasking;
  • the class JOB represents a task. The task core is the continue feature, during the execution of which the task controls the whole system;
  • the class EVENTS_SET describes the condition(s) in which a task can be executed.

We will successively document each of these concepts:

The multitasking manager

The class LOOP_STACK is in charge of managing the multitasking. It is used in two steps:

  • initialization: creation of the LOOP_STACK object and adding the task(s) to be executed
  • execution: execution of the run feature

Of course, additional tasks can be added during the execution. The manager can also be stopped, thanks to the break feature.

Note that the loop stack contains many execution loops (LOOP_ITEM). This allows, for instance, the implementation of a kind of modality (e.g. the modal windows in Vision).

Tasks

A task has a life cycle represented by the features executed by the manager (indeed a LOOP_ITEM hence the export clauses of those features).

  1. prepare allows preparing the task; in this phase, the task sets the events upon which it wants to be activated. The EVENTS_SET object is an object upon which one can set conditions (thanks to its expect feature).
  2. is_ready allows to test if the task has really been activated. The EVENTS_SET object is an object upon which one can test conditions (thanks to its event_occurred feature).
  3. continue contains the execution body of the task, and is executed upon task activation.
  4. done tells if the task has finished its execution. If so, it will be removed from the execution loop. Otherwise, the cycle begins again.
  5. restart allows reinserting a task in the execution loop.

The restart feature is seldom useful. See Vision for some use cases.

Execution conditions

The class EVENTS_SET allows to set and test conditions (EVENT_DESCRIPTORs).

The possible conditions are:

  • Time: this allows to create periodic tasks. See the classes PERIODIC_JOB, BACKGROUND_JOB, and TIME_EVENTS;
  • Input-output:
    • Data on an input stream: this allows to build tasks that wait for input data to be available (feature INPUT_STREAM.event_can_read),
    • Data on an output stream: this allows to build tasks that wait until they can write on an output stream (feature OUTPUT_STREAM.event_can_write);
  • Network: this allows to build tasks waiting network connections (feature SOCKET_SERVER.event_connection).

Tasks scheduling

The manager implements the following cycle:

  • call to the feature EVENTS_SET.reset;
  • call to the feature JOB.prepare on each task;
  • call to the feature EVENTS_SET.wait to wait for at least one condition to happen;
  • call to the feature JOB.is_ready on each task;
  • for all the ready tasks, call to the feature JOB.continue;
  • for those tasks, call to the feature JOB.done and if relevant, remove the task;
  • and back to the beginning.

Priorities

Tasks execution is by priority order. Only the ready task with the lowest priority is executed. All other tasks, even if ready, will have to wait until no other task with a lower priority is ready.

-note: we need to document how many priority levels 
are supported and how the scheduling works when multiple or all tasks were given
an identical priority level. Would the scheduler then resort to some sort
of round-robin method? By what rules? Apparently not by evaluating the duration of the
wait for next execution, see the LOOP_ITEM.run method. /HZ

Libraries using the sequencer

  • lib/net: servers usually allow many simultaneous connections. This is implemented with the sequencer library.
  • lib/vision: the event manager loop is implemented with a sequencer.