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
Post a Comment