Port to greenlet; nix-based dev environment

This commit is contained in:
Jeremy Penner 2020-06-27 15:39:10 -04:00
parent 5ddee41d8a
commit 04963f4512
8 changed files with 108 additions and 9 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
eval "$(lorri direnv)"

1
.gitignore vendored
View file

@ -8,3 +8,4 @@ build
*.h
*.marm
*.marm.*
*.so

View file

@ -35,6 +35,7 @@ rgcolorFg.extend([col | FBRIGHT for col in range(8)])
K_BACKSPACE = chr(8)
K_TAB = chr(9)
K_RETURN = chr(10)
K_NEWLINE = chr(13)
K_DEL = chr(127)
K_LEFT = 256
K_RIGHT = 257

View file

@ -131,7 +131,7 @@ class Terminal(Token):
elif (ansi.FKeyPrintable(key)):
self.stLine = self.stLine[:self.x - self.xLine] + key + self.stLine[(self.x + 1) - self.xLine:]
self.moveTo(self.x + 1, self.y)
elif key == ansi.K_RETURN:
elif key == ansi.K_RETURN or key == ansi.K_NEWLINE:
break
else:
print "weird key", ansi.StrKey(key)

View file

@ -45,13 +45,13 @@ class IntroTerm(Terminal):
self.newLine()
self.client.quit()
class Haxor(object):
def __init__(self):
self.game = GmSimple([AutoJoiner, IntroTerm])
class HaxorGame(Game):
def GetRgclsTokTrans(self):
return [[AutoJoiner, IntroTerm]]
class HaxorRunner(Runner):
def RunGame(self, client):
client.joinGame(self.game)
def RunServer(self):
telnet.RunServer(self.RunGame)
client.joinGame(HaxorGame())
if __name__ == "__main__":
Haxor().RunServer()
HaxorRunner().RunServer()

View file

@ -671,7 +671,7 @@ class PwButton(PwStatic):
def ColFg(self):
return ansi.BLUE | ansi.FBRIGHT
def HandleKey(self, pov, psel, key):
if key == ansi.K_RETURN:
if key == ansi.K_RETURN or key == ansi.K_NEWLINE:
self.dgEnter(self.Value(), psel)
return True
return False

11
shell.nix Normal file
View file

@ -0,0 +1,11 @@
let
pkgs = import <nixpkgs> {};
pyenv = pypkgs: with pypkgs; [
greenlet twisted cython mysqlclient bcrypt
];
in
pkgs.mkShell {
buildInputs = [
(pkgs.python2.withPackages pyenv)
];
}

85
stackless.py Normal file
View file

@ -0,0 +1,85 @@
from greenlet import greenlet
import traceback
from collections import deque
class Scheduler(object):
def __init__(self):
self.running = None
self.rgtasklet = []
self.g = None
def schedule(self, tasklet, *args):
tasklet.args = args
tasklet.scheduled = True
self.rgtasklet.append(tasklet)
def kill(self, tasklet):
if not tasklet.g.dead:
tasklet.g.parent = greenlet.getcurrent()
tasklet.g.throw()
try:
self.rgtasklet.remove(tasklet)
except:
pass
def run(self):
self.g = greenlet.getcurrent()
while len(self.rgtasklet) > 0:
tasklets = self.rgtasklet
self.rgtasklet = []
for tasklet in tasklets:
try:
self.running = tasklet
args = tasklet.args
tasklet.args = None
tasklet.scheduled = False
tasklet.g.parent = self.g
tasklet.g.switch(*args)
except:
traceback.print_exc()
self.kill(tasklet)
self.running = None
self.g = None
def suspend(self):
self.g.switch()
class Tasklet(object):
def __init__(self, cb, scheduler):
self.g = greenlet(cb)
self.args = None
self.scheduler = scheduler
self.scheduled = False
def __call__(self, *args):
self.scheduler.schedule(self, *args)
def kill(self):
self.scheduler.kill(self)
class Channel(object):
def __init__(self, scheduler):
self.queue = deque()
self.tasklet = None
self.scheduler = scheduler
def receive(self):
while len(self.queue) == 0:
self.tasklet = self.scheduler.running
self.tasklet.scheduled = True
self.scheduler.suspend()
self.tasklet = None
return self.queue.popleft()
def send(self, val):
self.queue.append(val)
if self.tasklet:
self.scheduler.schedule(self.tasklet)
scheduler = Scheduler()
def tasklet(cb):
return Tasklet(cb, scheduler)
def channel():
return Channel(scheduler)
def run():
scheduler.run()