4. Usage examples

4.1. Using the system time

4.1.1. Simple example

This simple example is based on the the execution of 3 tasks. The task #0 is run every 5 seconds, at second beginning, forever. The task #1 is run every second, at the middle of second, forever. The task #2 is run every second, at the middle of second, for 5 times. Each task printouts its task id, nominal runtime and delay of real runtime from nominal runtime, the difference runtime - system time. Task #2 prints also the run number. Since all these tasks make the same output, they all can be inplemented by only one function, the “task” function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import runtask as rt           # task scheduler
import time as tm              # time interface

# set up the time scheduler
sch = rt.RunTask(speed=1.0,tick=0.1)

# a task printing run time and, if not forever, the runs left.
def task(sch):
    now = tm.time()
    task_id, last_runtime, run_count, task_args = sch.task_info()
    runs_left = sch.runs_left()
    if runs_left == -1:
        print 'task','%d %12.3f %10.9f' %(task_id,last_runtime,now-last_runtime)
    else:
        if runs_left == 1:
            print 'task','%d %12.3f %10.9f %d' \
                % (task_id,last_runtime,now-last_runtime,runs_left), \
                    'this is the last run'
        else:
            print 'task','%d %12.3f %10.9f %d' \
                % (task_id,last_runtime,now-last_runtime,runs_left)


# task every 5 seconds, epoch aligned, forever
sch.task(task,([sch],{}),sch.aligned(5.,0.0,-1))

# two tasks every second, half second aligned,
# the first forever, the second 5 times.
sch.task(task,([sch],{}),sch.aligned(1.,0.5,-1))
sch.task(task,([sch],{}),sch.aligned(1.,0.5,5))

# print a start message and start
print 'Schedule 3 tasks for 10 seconds (system time) then terminate.'
print 'Task #0 is scheduled every 5 seconds, epoch aligned, forever.'
print 'Task #1 is scheduled every second, aligned at half second, forever.'
print 'Task #2 is scheduled every second, aligned at half second, for 5 times.'
print 'id     runtime        sys-runtime run number'

sch.start()

# wait 20 seconds then stop scheduler and exit.
tm.sleep(10)
sch.stop()

#### END

This an excerpt from example output. Task with 5 second period has id=0. Tasks with 1 second period have respectively id=1 and id=2.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
Schedule 3 tasks for 10 seconds (system time) then terminate.
Task #0 is scheduled every 5 seconds, epoch aligned, forever.
Task #1 is scheduled every second, aligned at half second, forever.
Task #2 is scheduled every second, aligned at half second, for 5 times.
id     runtime        sys-runtime run number
task 1 1431619393.500 0.000144005
task 2 1431619393.500 0.000193119 4
task 1 1431619394.500 0.000138044
task 2 1431619394.500 0.000178099 3
task 0 1431619395.000 0.000114918
task 1 1431619395.500 0.000138998
task 2 1431619395.500 0.000176907 2
task 1 1431619396.500 0.000140905
task 2 1431619396.500 0.000180006 1 this is the last run
task 1 1431619397.500 0.000129938
task 1 1431619398.500 0.000138998
task 1 1431619399.500 0.000132084
task 0 1431619400.000 0.000137091
task 1 1431619400.500 0.000135899
task 1 1431619401.500 0.000129938
task 1 1431619402.500 0.000140905

It is to be noted that the difference sys-runtime that is the difference between the system time at task call and the nominal run time is always below 0.2 ms. This difference measures the scheduling overhead introduced by RunTask

4.1.2. Capabilities of the periodic timing

This example shows almost all capabilities of the periodic timing. Task #0 is run 15 second after the beginning of each minute, forever. Task #1 is run with period 19/3, phase=0.1, forever. Task #2 is run immediately every 5 seconds. Task #3 is run immediately with period 19/3, forever. Task #4 is run randomly with uniform distribution, period min 8 seconds and max 16 seconds, forever.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import runtask as rt           # task scheduler
import time as tm              # time interface

# set up the time scheduler at the system time
sch = rt.RunTask(speed=1.0,tick=0.01)

# a task printing run time and, if not forever, the runs left.
def task(sch):
    now = tm.time()
    task_id, runtime, run_count, task_args = sch.task_info()
    runs_left = sch.runs_left()
    if runs_left == -1:
        print 'task','%d %12.3f %10.9f' % (task_id,runtime,now-runtime)
    else:
        if runs_left == 1:
            print 'task','%d %12.3f %10.9f %d' \
                % (task_id,runtime,now-runtime,runs_left), \
                    'this is the last run'
        else:
            print 'task','%d %12.3f %10.9f %d' \
                % (task_id,runtime,now-runtime,runs_left)

            
# run task at each minute, 15 seconds after minute beginning, forever
period = 1 * 60.         # (1 min = 1 min * 60 sec)
phase = 15.              # (15 sec = 15 sec)
sch.task(task,([sch],{}),sch.aligned(period,phase))

# run task with period = 19/3, phase=0.1, forever
period = (19,3)
phase = 0.1
sch.task(task,([sch],{}),sch.aligned(period,phase))

# run task immediately with period = 5, forever
period = 5.
sch.task(task,([sch],{}),sch.now(period))

# run task imediately with period = 19/3, forever
period = (19,3)
sch.task(task,([sch],{}),sch.now(period))

# run task randomly with uniform distribution, min period 8, max period 16, forever
period_min = 8 
period_max = 16 
sch.task(task,([sch],{}),sch.uniform(period_min,period_max))

# print a start message and start
print 'Schedule 5 tasks for 60 seconds (system time) then terminate.'
print 'Task 0 is run at each minute, 15 seconds after minute begining. Forever'
print 'Task 1 is run every 19/3 seconds with phase 0.1. Forever'
print 'Task 2 is run every 5 seconds, starting immediately. Forever'
print 'Task 3 is run every 19/3 seconds, starting immediately. Forever'
print 'Task 4 is run randomnly with uniform distribution, period min 8 seconds and max 16 seconds. Forever'
print 'Now is ',tm.asctime()
print 'id     runtime        sys-runtime'

sch.start()

# wait one minute then stop scheduler and exit.
tm.sleep(60)
sch.stop()

#### END

This an excerpt from example output.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Schedule 5 tasks for 60 seconds (system time) then terminate.
Task 0 is run at each minute, 15 seconds after minute begining. Forever
Task 1 is run every 19/3 seconds with phase 0.1. Forever
Task 2 is run every 5 seconds, starting immediately. Forever
Task 3 is run every 19/3 seconds, starting immediately. Forever
Task 4 is run randomnly with uniform distribution, period min 8 seconds and max 16 seconds. Forever
Now is  Mon Jun 29 18:19:28 2015
id     runtime        sys-runtime
task 2 1435594768.880 0.005230904
task 3 1435594768.880 0.005270004
task 4 1435594769.125 0.005057096
task 1 1435594773.767 0.003353596
task 2 1435594773.880 0.000105858
task 3 1435594775.213 0.006676674
task 2 1435594778.880 0.000120878
task 1 1435594780.100 0.000119209
task 3 1435594781.547 0.003341436
task 4 1435594783.187 0.005274773
task 2 1435594783.880 0.000128984
task 1 1435594786.433 0.006687880
task 3 1435594787.880 0.000134945
task 2 1435594788.880 0.000151873
task 4 1435594791.886 0.003555059
task 1 1435594792.767 0.003352642
task 2 1435594793.880 0.000138998
task 3 1435594794.213 0.006690741
task 2 1435594798.880 0.000123978
task 1 1435594799.100 0.000119209
task 3 1435594800.547 0.003340483
task 4 1435594801.305 0.004789829
task 2 1435594803.880 0.000121832
task 1 1435594805.433 0.006679773
task 3 1435594806.880 0.000120878
task 2 1435594808.880 0.000147820
task 1 1435594811.767 0.003352642
task 3 1435594813.213 0.006674528
task 2 1435594813.880 0.000163794
task 0 1435594815.000 0.000119925
task 4 1435594816.165 0.004850388
task 1 1435594818.100 0.000118017
task 2 1435594818.880 0.000125885
task 3 1435594819.547 0.003355265
task 2 1435594823.880 0.000121832
task 1 1435594824.433 0.006678820
task 3 1435594825.880 0.000123978
task 2 1435594828.880 0.000145912

Since this example runs for one minute, task #0 appears only one time in the example output.

Since the scheduler time has tick=0.01, the effective run time of each scheduled task must be a tick multiple. Under some conditions, this can produce a delay between the nominal runtime computed by the time generator and the effective runtime. This effect can be seen for tasks #1, #3 and #4 where the nominal run time is rounded to the nearest and greather tick multiple.

4.1.3. Threading event

This example shows as a Event object from the threading module can be used to schedule the execution of a loop in the main program. The loop is run every second for 10 times.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import runtask as rt           # task scheduler
import time as tm              # time interface
import threading as tg         # thread control


# set up the time scheduler at the system time
sch = rt.RunTask(speed=1.0,tick=0.01)

# create an event object to control main execution
loop = tg.Event()

# schedule each main loop with period = 1, phase=0, for ten times.
# Set the event flag at each schedule time.
period = 1
phase = 0
runs = 10
sch.task(loop,1,sch.aligned(period,phase,runs))

# print a start message and start
print 'Schedule main every second for 10 times, then terminate.'
print 'Now is ',tm.asctime()
print 'id     runtime        sys-runtime'

sch.start()

## main

# loop runs times
while True:

    # wait for run time
    loop.wait()
    loop.clear()

    # print task id, run time, difference from sys time and the runs left.
    task_id, runtime, run_count, task_args = sch.task_info(loop)
    runs_left = sch.runs_left(loop) + 1
    now = tm.time()
    if runs_left == 1:
        print 'task','%d %12.3f %10.9f %d' \
            % (task_id,runtime,now-runtime,runs_left), \
                'this is the last run'
        break
    else:
        print 'task','%d %12.3f %10.9f %d' \
            % (task_id,runtime,now-runtime,runs_left)

# terminate
sch.stop()

#### END

This an excerpt from example output.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Schedule main every second for 10 times, then terminate.
Now is  Sat Aug  1 10:31:38 2015
id     runtime        sys-runtime
task 0 1438417899.000 0.000428915 10
task 0 1438417900.000 0.000403881 9
task 0 1438417901.000 0.000411034 8
task 0 1438417902.000 0.000412941 7
task 0 1438417903.000 0.000389099 6
task 0 1438417904.000 0.000504017 5
task 0 1438417905.000 0.000566006 4
task 0 1438417906.000 0.000412941 3
task 0 1438417907.000 0.000413895 2
task 0 1438417908.000 0.000401974 1 this is the last run

4.1.4. Threading lock

This example shows as a Lock object from the threading module can be used to schedule the execution of a loop in the main program. The loop is run every second for 10 times.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import runtask as rt           # task scheduler
import time as tm              # time interface
import threading as tg         # thread control


# set up the time scheduler at the system time
sch = rt.RunTask(speed=1.0,tick=0.01)

# create an lock object to control main execution
loop = tg.Lock()
loop.acquire(False)

# schedule each main loop with period = 1, phase=0, for ten times: release
# the lock.
period = 1
phase = 0
runs = 10
sch.task(loop,0,sch.aligned(period,phase,runs))

# print a start message and start
print 'Schedule main every second for 10 times, then terminate.'
print 'Now is ',tm.asctime()
print 'id     runtime        sys-runtime'

sch.start()

## main

# loop
while True:

    # wait for run time
    loop.acquire()

    # print task id, run time, difference from sys time and the runs left.
    task_id, runtime, run_count, task_args = sch.task_info(loop)
    runs_left = sch.runs_left(loop) + 1
    now = tm.time()
    if runs_left == 1:
        print 'task','%d %12.3f %10.9f %d' \
            % (task_id,runtime,now-runtime,runs_left), \
                'this is the last run'
        break
    else:
        print 'task','%d %12.3f %10.9f %d' \
            % (task_id,runtime,now-runtime,runs_left)

# terminate
sch.stop()

#### END

This an excerpt from example output.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Schedule main every second for 10 times, then terminate.
Now is  Wed Aug  5 19:47:29 2015
id     runtime        sys-runtime
task 0 1438796850.000 0.000422001 10
task 0 1438796851.000 0.000376940 9
task 0 1438796852.000 0.000379086 8
task 0 1438796853.000 0.000406027 7
task 0 1438796854.000 0.000382900 6
task 0 1438796855.000 0.000379086 5
task 0 1438796856.000 0.000366926 4
task 0 1438796857.000 0.000377893 3
task 0 1438796858.000 0.000384092 2
task 0 1438796859.000 0.000364065 1 this is the last run

4.1.5. Threading semaphore

This example shows as a Semaphore object from the threading module can be used to schedule the execution of a loop in the main program. The loop is run every second for 10 times.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import runtask as rt           # task scheduler
import time as tm              # time interface
import threading as tg         # thread control


# set up the time scheduler at the system time
sch = rt.RunTask(speed=1.0,tick=0.01)

# create an lock object to control main execution
loop = tg.Semaphore()
loop.acquire(False)

# schedule each main loop with period = 1, phase=0, for ten times: release
# the lock.
period = 1
phase = 0
runs = 10
sch.task(loop,0,sch.aligned(period,phase,runs))

# print a start message and start
print 'Schedule main every second for 10 times, then terminate.'
print 'Now is ',tm.asctime()
print 'id     runtime        sys-runtime'

sch.start()

## main

# loop
while True:

    # wait for run time
    loop.acquire()

    # print task id, run time, difference from sys time and the runs left.
    task_id, runtime, run_count, task_args = sch.task_info(loop)
    runs_left = sch.runs_left(loop) + 1
    now = tm.time()
    if runs_left == 1:
        print 'task','%d %12.3f %10.9f %d' \
            % (task_id,runtime,now-runtime,runs_left), \
                'this is the last run'
        break
    else:
        print 'task','%d %12.3f %10.9f %d' \
            % (task_id,runtime,now-runtime,runs_left)

# terminate
sch.stop()

#### END

This an excerpt from example output.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Schedule main every second for 10 times, then terminate.
Now is  Wed Aug  5 19:47:07 2015
id     runtime        sys-runtime
task 0 1438796828.000 0.000421047 10
task 0 1438796829.000 0.000426054 9
task 0 1438796830.000 0.000435114 8
task 0 1438796831.000 0.000443935 7
task 0 1438796832.000 0.000437021 6
task 0 1438796833.000 0.000430107 5
task 0 1438796834.000 0.000451088 4
task 0 1438796835.000 0.000437975 3
task 0 1438796836.000 0.000607967 2
task 0 1438796837.000 0.000441074 1 this is the last run