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