0

I have an array of events and their polling time like this. [{"A":5,"B":7,"C":9}]

So event A (some function) needs to be called every x seconds, in the above example A function needs to be called every 5th second from now (not just once, but keep on repeating)

and B function needs to be called every 7th second from now and so on.

At 35th second Both A and B would be called(considering function A and B returns almost instantaneously assume printf() )

Is there a standard algorithm for this?if not any pointers on how to achieve this?

something on this line,(doesnt work though)

import threading
class A():
    def A():
        printf "A"
    def B():
        printf "B"
    def __init__(self, *args, **kwargs):
        self.iteration = 1
    def execute(self,arr):
        for key in arr[0]:
            print key, arr[key]
            t1 = threading.Timer(arr[key], key).start()
            t2 = threading.Timer(arr[key], key).start()


A().execute([{"A":5,"B",7}])
rahul
  • 1

2 Answers2

0

First of all, you should convert the list of timers to a dictionary, with the function as key and the interval as value. Then you could integrate a counter that counts the time in seconds after each sleep(1) call. Alternatively you could use the datetime module to find the time delta between now and startup time.

import time    
def a():
    pass
def b():
    pass
timers = {a:9, b:3}
time_counter = 0
while True:
    time.sleep(1)
    time_counter += 1
    for function in timer.keys():
        if time_counter % timer[function] is 0:
            function()

Obviously, you have to change the code I wrote a bit, but the principle should be similiar

El Sholz
  • 121
  • 1
  • 5
0

My version is basically the same as El Shotz' but I prevent the counter from becoming very large (which would eventually manifest as a memory leak, if not a precision error) as follows:

from functools import reduce
from operator import mul
from time import sleep

def a():
    print("I am A")

def b():
    print("I am B")

def c():
    print("I am C")

my_dict ={a:5,b:7,c:9}

numerator = reduce(mul, my_dict.values(), 1)
while True:
    for counter in range(numerator):
        for k, v in my_dict.items():
            if counter%v == 0:
                k()
        sleep(1)

numerator is the product of all the wait values, so when the counter loop finishes we are synchronized at 0 with everything in the right place to start again.

There's a slight problem with this, which is that if any of the functions take significant time to execute, our internal clock will start to drift. If you need to absolutely run everything on the second then you will need to do something more complicated to ensure that you are waiting the right amount of time.

Rob Bricheno
  • 4,467
  • 15
  • 29
  • thanks!, i am planning to use monotonic time and instead of making the thread sleep for 1 second, i would make it sleep for 1-(time_for_operations) to avoid drifiting. – rahul May 21 '18 at 07:35