Skip to content

Instantly share code, notes, and snippets.

@stanleyvarga
Last active April 28, 2020 14:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stanleyvarga/da3d4d4281ef3c94698dac4f8fe5b73c to your computer and use it in GitHub Desktop.
Save stanleyvarga/da3d4d4281ef3c94698dac4f8fe5b73c to your computer and use it in GitHub Desktop.
#!/usr/bin/python
import time
import logging
import threading
logging.basicConfig(format="[%(asctime)s]: %(message)s", level=logging.INFO, datefmt="%H:%M:%S")
class STATE:
def __init__(self):
self.condition = None
self.simulationRun = 1
self.noPaintersToWaitFor = 0
self.paintersMetUntilBreak = 0
self.painterBreakWhenBucketCountIs = 4
self.paintersOnBreak = []
self.totalBuckets = 0
SIMULATION_TIME = 10
NO_PAINTERS = 5
NO_PAINTERS_TO_WAIT_FOR = 2
PAINTERS_BREAK_WHEN_BUCKET_COUNT_IS = 4
PAINTER_TIMING_BREAK = 0.5
PAINTER_TIMING_PAINT = 1
PAINTER_TIMING_BUCKET_GET = 0.5
# maliar pocka maximalne PAINTER_TIMING_WAIT_MAX sekund,
# potom sa unudi a da sa znova do prace
PAINTER_TIMING_WAIT_MAX = 1
class Painter:
def __init__(self, state, name):
self.buckets = 0
self.name = name
self.state = state
def doPainting(self):
logging.info("%s Painting...", self.name)
time.sleep(PAINTER_TIMING_PAINT)
def goGetNewBucket(self):
logging.info("%s Taking Bucket...", self.name)
time.sleep(PAINTER_TIMING_BUCKET_GET)
self.buckets += 1
state.totalBuckets += 1
# Python nam velmi rad pomoze s releasom mutexu, aby sme nan nezabudli
# namiesto mutex/cond.acquire() a potom mutex/cond.release()
# obalime logiku do `with mutex/cond:` -> acquire a release prekladac doplni za nas
with state.condition:
if self.buckets % state.painterBreakWhenBucketCountIs == 0:
# to co robila bariera predtym robime my rucne,
# teda zistujeme kolko vlakien ma este cakat
# + 1 pretoze napr. jeden maliar caka na dalsich dvoch = 3 dokopy
if state.paintersMetUntilBreak != state.noPaintersToWaitFor + 1:
logging.info("%s waiting for %s more painters", self.name, state.noPaintersToWaitFor - state.paintersMetUntilBreak)
# inkrementujeme counter aby sme vedeli kedy uz necakat
state.paintersMetUntilBreak += 1
# vlakno caka, kym nie je splnena podmienka resp. counter
# alebo vyprsi cas
state.condition.wait(PAINTER_TIMING_WAIT_MAX)
# Teraz notify_all povie vsetkym vlaknam, ze toto vlakno je uvolnene
# a teda uz necaka, pokracuje kod nizsie
state.condition.notify_all()
# Resetneme counter bariery aby mohla zacat od znova
state.paintersMetUntilBreak = 0
logging.info("%s Having a break", self.name)
time.sleep(PAINTER_TIMING_BREAK)
def run(self):
while self.state.simulationRun:
self.goGetNewBucket()
self.doPainting()
if __name__ == "__main__":
logging.info("Start Main Thread")
state = STATE()
state.noPaintersToWaitFor = NO_PAINTERS_TO_WAIT_FOR
# threading.Rlock je lepsi ako threaing.Lock v tom,
# ze pokial zabudneme releasnut mutex, RLock nesposobi deadlock
state.condition = threading.Condition(threading.RLock())
painters = []
threads = []
for i in range(NO_PAINTERS):
painters.append( Painter(
state,
"Painter-{}".format(i)
)
)
for i in range(NO_PAINTERS):
threads.append( threading.Thread(
target=painters[i].run,
args=()
)
)
for t in threads:
t.start()
time.sleep(SIMULATION_TIME)
state.simulationRun = 0
for t in threads:
t.join()
logging.info("Total Buckets: %s", state.totalBuckets)
for painter in painters:
logging.info("%s buckets: %s", painter.name, painter.buckets)
logging.info("Exit Main Thread")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment