Xentara v1.2.1
User Manual
Loading...
Searching...
No Matches
Scheduling Tasks

Xentara provides a sophisticated mechanism for scheduling and coordinating tasks. Tasks are provided by different elements in the Xentara model.

Tasks can be executed in two different ways:

  • at regular intervals using a timer, or
  • in response to an event, like a change in the value of a data point.

Execution Pipelines

Structure of a Pipeline

Tasks are grouped together into pipelines. Each pipeline is attached to a single timer or event, and executed when the timer elapses or the event fires.

An execution pipeline consists of a number of check points connected by segments Each segment consists of one or more tasks, executed in sequence. The simplest possible pipeline just consists of a single segment joining two check points:

Image 1: simple pipeline

Pipelines support parallel execution of segments. A pipeline using parallel execution may look like this, for example:

Image 2: parallel pipeline

Pipelines can have multiple check points. A more complex pipeline may look like this:

Image 3: complex pipeline

Pipeline Segments

A pipeline segment ist just a bunch of tasks that are executed one after the other in a single thread. A pipeline segment always starts and ends at a check point.

In image 3 above, there are three pipeline segments:

  1. Segment 1: Task 1a 🠖 Task 1b 🠖 Task 1c
  2. Segment 2: Task 2a 🠖 Task 2b
  3. Segment 3: Task 3a 🠖 Task 3b

Individual segments (like Segment 1 and Segment 2) can be executed in parallel. The tasks within each segment are always executed sequentially, however.

Segments are executed using a thread pool located the corresponding execution track (see below). The number of threads in the thread pool determine how many pipeline segments can be executed in parallel. If the thread pool does not have enough threads, some pipeline segments will be executed sequentially, even if the structure of the pipeline would otherwise allow them to be executed in parallel.

Check Points

A check point is a synchronization point that waits for a number of pipeline segments to all be finished. It then starts another group of segments. In image 3 above, there are three check points:

  1. Check Point 1: This check point starts Segment 1 and Segment 2 in parallel
  2. Check Point 2: This check point waits for Segment 1 and Segment 2 to finish, and then starts Segment 3
  3. Check Point 3: This check points waits for Segment 3 to finish

After the last check point (Check Point 3) has been reached, the pipeline is finished, and the next pipeline can start.

Segments can skip check points, if desired:

Image 4: segment that skips a check point

In the image above, Segment 4 extends between Check Point 1 and Check Point 3, skipping Check Point 2. Check Point 2 will start Segment 3 even if the new Segment 4 has not completed yet. Check Point 3 will then wait for Segment 3 and Segment 4 to finish, before ending the pipeline.

Execution Tracks

The individual pipelines are divided into one or more execution tracks. The pipelines within each track are alwas executed one after the other, and are never allowed to overlap. Pipelines in different tracks are allowed to execute simultaneousy.

Image 5: separate execution tracks

The image above shows two separate execution tracks, each with a timer. The pipelines of the two timers are allowed to overlap, because they are in different tracks. The event pipeline, however, does not overlap the timer in the same track. Instead, the event pipeline is delayed until the timer pipeline has finished. Similarly, the next execution of the timer pipeline is delayed until the event pipeline has finished.

The execution track also contains the thread pool used to execute the individual pipelines.

Timers

A timer allows you to execute tasks at regular intervals. You can define any number of timers, each with different scheduling parameters.

Timing Parameters

Timers are scheduled using two parameters:

  • The period determines how often the timer will fire.
  • The offset determines when exactly the timer will fire relative to other timers.

The offset is used to define exactly when the timer will fire. A timer with a period of 1 second, for example, might always fire at the full second, so at 12:00:00.000, 12:00:01.000, 12:00:02.000, etc. Or, it might fire on every half second, so at 12:00:00.500, 12:00:01.500, 12:00:02.500, etc. Both these timers would have the same period, but different offsets.

A timer with an offset of 0 will be scheduled as if it had started at exactly midnight, January 1, 2001, UTC. For example, a timer with a period of 1 second and an offset of 0 will always fire on the whole second, a timer with a period of 1 minute and an offset of 0 will always fire on the whole minute, and a timer with a period of 1 hour and an offset of 0 will always fire on the whole hour. A timer with a period of 200ms and an offset of 0 will always fire on the whole second, and at 200ms, 400ms, 600ms, and 800ms after each full second, and so on.

A timer with a positive offset will fire that much later than the same timer with an offset of 0. For example, a timer with a period of 1 second and an offset of 10ms will always fire 10ms after each second, so at 12:00:00.010, 12:00:01.010, 12:00:02.010, etc. A timer with a negative offset will fire before the same timer with an offset of 0. For example, a timer with a period of 1 second and an offset of -10ms will always fire 10ms before each second, so at 11:59:59.990, 12:00:00.990, 12:00:01.990, etc.

A timer triggers the execution of a pipeline of tasks when it fires.

Execution Sequence of Concurrent Timers

If two timers in the same track are scheduled to fire at the same time, their pipelines are not executed in parallel, but sequentially one after the other.

By default, timers with shorter periods are executed first, and timers with longer periods afterwards. For example, if a track contains one timer scheduled to fire every second, and another timer scheduled to fire every 10 seconds, then the timers will fire together once every ten seconds. In that case, the pipeline of the one-second timer will be executed before the pipeline of the 10-second timer, because it has a shorter period.

You can influence the order in which timers are run by assigning a sequence number to the timer. Timers with lower sequence numbers are always executed before timers with higher sequence numbers, regardless of period. For example, timers with a sequence number of -1 will run before timers with sequence number 0, which will in turn run before timers with sequence numbers of 1 or higher.

Sequence numbers are 32-bit signed integers, and can be negative, zero, or positive. By default, timers have a sequence number of 0.

Timers in different tracks are independent of each other, and their pipelines will run in parallel if they are scheduled for the same time.

Events

An Event triggers the execution of a pipeline whenever a certain event is raised by a certain element in the Xentara model.