107 lines
2.8 KiB
Python
107 lines
2.8 KiB
Python
import bin #this is at the end of the script in case any functions from bin
|
|
#depend on anything here
|
|
from circuitos.exceptions import *
|
|
from circuitos.apploader import get_app
|
|
import circuitos.apploader # apploader hack
|
|
import time
|
|
import usb_cdc
|
|
|
|
class App:
|
|
def __init__(self, os, pid, name, *argv):
|
|
self.os = os
|
|
self.pid = pid
|
|
self.name = name
|
|
self.store = {}
|
|
self.next_function = 'main'
|
|
self.run_at = -1
|
|
self.argv = (self,) + argv
|
|
self.waiting_for = -1
|
|
|
|
def iterate(self):
|
|
if time.monotonic() >= self.run_at and not self.waiting_for in self.os.apps:
|
|
getattr(self, f'F_{self.next_function}')()
|
|
|
|
@property
|
|
def console(self):
|
|
if self.pid == self.os.controllers[-1]:
|
|
return self.os.console
|
|
else:
|
|
raise NotConsoleController(self.os.controllers[-1])
|
|
|
|
def transfer_console(self, recipient):
|
|
if self.pid == self.os.controllers[-1]:
|
|
self.os.controllers.append(recipient)
|
|
else:
|
|
raise NotConsoleController(self.os.controllers[-1])
|
|
|
|
def jump(self, function):
|
|
self.next_function = function
|
|
|
|
def sleep(self, seconds):
|
|
self.run_at = time.monotonic() + seconds
|
|
|
|
def exec(self, command, *argv):
|
|
self.os.apps[self.pid] = get_app(command)(self.os, self.pid, command, *argv)
|
|
|
|
def wait(self, pid):
|
|
self.waiting_for = pid
|
|
|
|
def end_wait(self):
|
|
self.waiting_for = -1
|
|
|
|
def on_exit(self):
|
|
pass
|
|
|
|
def exit(self):
|
|
del self.os.apps[self.pid]
|
|
|
|
apploader.App = App # apploader hack
|
|
|
|
class OS:
|
|
def __init__(self):
|
|
self.apps = {}
|
|
self.next_new = 0
|
|
self.controllers = [0]
|
|
self.console = usb_cdc.console
|
|
usb_cdc.console.timeout = 0
|
|
self.next_pidi = 0
|
|
self.launch('init')
|
|
|
|
def iterate(self):
|
|
pid = list(self.apps.keys())[self.next_pidi]
|
|
function = self.apps[pid].iterate
|
|
|
|
function()
|
|
|
|
try:
|
|
self.apps[pid]
|
|
# If this succeds, the app did not exit and next_pidi should
|
|
# be incremented
|
|
self.next_pidi += 1
|
|
except KeyError:
|
|
# If self.apps[pid] failed, the app exited and next_pidi
|
|
# should not be incremented
|
|
pass
|
|
self.next_pidi = self.next_pidi % len(self.apps)
|
|
|
|
while not self.controllers[-1] in self.apps.keys():
|
|
self.controllers.pop()
|
|
|
|
def launch(self, app, *argv):
|
|
self.apps[self.next_new] = get_app(app)(self, self.next_new, app, *argv)
|
|
self.next_new += 1
|
|
return self.next_new - 1
|
|
|
|
def kill(self, pid):
|
|
try:
|
|
del self.apps[pid]
|
|
except KeyError:
|
|
raise(NoSuchProcess(pid))
|
|
|
|
def run():
|
|
os = OS()
|
|
while True:
|
|
os.iterate()
|
|
|
|
|