Skip to content

Instantly share code, notes, and snippets.

@matklad
Created October 31, 2016 19:34
Show Gist options
  • Save matklad/f5f076bc24a474a0e5bdb78fc1011013 to your computer and use it in GitHub Desktop.
Save matklad/f5f076bc24a474a0e5bdb78fc1011013 to your computer and use it in GitHub Desktop.
import heapq
import random
import time
from threading import Thread
def alarm(span, count):
for _ in range(count):
time.sleep(span)
print(span)
def make_tasks(n, span, count):
result = []
for _ in range(n):
s = random.randrange(span)
result.append((s, count))
return result
###########
# Threads #
###########
def thread_execute(tasks):
for task in tasks:
Thread(target=alarm, args=task).start()
##################
# State machines #
##################
class AlarmTask:
def __init__(self, span, count):
self.left = count
self.span = span
self.started = False
def next(self):
if self.left == 0:
return ("Stop", None)
if self.started:
print(self.span)
self.left -= 1
self.started = True
return ("Sleep", self.span)
def run_to_completion(tasks):
work = [(0, i, t) for (i, t) in enumerate(tasks)]
heapq.heapify(work)
while work:
t = time.time()
(wakeup, id, a) = heapq.heappop(work)
to_sleep = wakeup - t
if to_sleep > 0:
time.sleep(to_sleep)
(cmd, span) = a.next()
if cmd == "Sleep":
wakeup = time.time() + span
heapq.heappush(work, (wakeup, id, a))
def fsm_execute(tasks):
run_to_completion([AlarmTask(*t) for t in tasks])
##############
# Generators #
##############
def task(f):
class T:
def __init__(self, *args):
self.g = f(*args)
def next(self):
try:
return next(self.g)
except StopIteration:
return ("Stop", None)
return T
@task
def async_alarm(span, count):
for _ in range(count):
yield ("Sleep", span)
print(span)
def async_execute(tasks):
run_to_completion([async_alarm(*t) for t in tasks])
# tasks = make_tasks(10, 10, 3)
tasks = make_tasks(10**4, 10**4, 3)
# thread_execute(tasks)
# fsm_execute(tasks)
async_execute(tasks)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment