python - Threading of Periodic Update to Class Member -


what method updating class member in python while still being used other methods in class?

i want rest of class continue processing using old version of member until updated , switch processing new version once update complete.

here toy example illustrate use case, self.numbers class member needs safely threaded periodic updating using logic in updatenumbers(), want called in non-blocking way runcounter().

from time import sleep, time  class simpleupdater(object):     def __init__(self):         self.i = 5         self.numbers = list(range(self.i))         self.lastupdate = time()         self.updatedelta = 10      def timepast(self):         = time()         delta = self.lastupdate -         return (delta > self.updatedelta)      def updatenumbers(self):         print('starting update', flush=true)         self.numbers = list(range(self.i))         # artificial calculation time         sleep(2)         print('done updating', flush=true)      def runcounter(self):         j in self.numbers:             print(j, flush=true)             sleep(0.5)         self.i += 1         if self.timepast:             ## spin off calculation!! (and safely transfer new value)             self.updatenumbers()  if __name__ == '__main__':     s = simpleupdater()     while true:         s.runcounter() 

the desired behavior if self.numbers being iterated on in loop, should finish loop old version before switching new version.

you create new thread every call updatenumbers more common way type of thing have 1 thread running infinite loop in background. should write method or function infinite loop, , method/function serve target background thread. kind of thread daemon, doesn't have be. i've modified code show how might done (i've fixed few small bugs in example code).

from time import sleep, time import threading   class numbers(object):     def __init__(self, numbers):         self.data = numbers         self.lastupdate = time()   class simpleupdater(object):     def __init__(self):         self.i = 5         self.updatedelta = 5         self.numbers = numbers(list(range(self.i)))         self._startupdatethread()      def _startupdatethread(self):         # call function once         update_thread = threading.thread(target=self._updateloop)         update_thread.daemon = true         update_thread.start()      def _updateloop(self):         print("staring update thread")         while true:             self.updatenumbers()             sleep(.001)      def updatenumbers(self):         numbers = self.numbers         delta = time() - numbers.lastupdate         if delta < self.updatedelta:             return          print('starting update')         # artificial calculation time         sleep(4)         numbers = numbers(list(range(self.i)))         self.numbers = numbers         print('done updating')      def runcounter(self):         # take self.numbers once, use local `numbers`.         numbers = self.numbers         j in numbers.data:             print(j)             sleep(0.5)         # more numbers         self.i += 1   if __name__ == '__main__':     s = simpleupdater()     while true:         s.runcounter() 

notice have not used locks :). away without using locks because access numbers attribute of simpleupdater class using atomic operations, in case simple assignments. every assignment self.numbers associated new numbers object attribute. every time access attribute should expect different object, if take local reference object @ beginning of method, ie numbers = self.numbers, numbers refer same object (till goes out of scope @ end of method), if background thread updates self.numbers.

the reason i've created numbers class can , set "volatile" members in single (atomic) assignment (the numbers list , lastupdated value). know lot keep track of, , might smarter , safer use locks :), wanted show option well.


Comments