You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
2.8 KiB
106 lines
2.8 KiB
import bin #this is at the end of the script in case any functions from bin |
|
#depend on anything here |
|
from fibonaccios.exceptions import * |
|
from fibonaccios.apploader import get_app |
|
import fibonaccios.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() |
|
|
|
|
|
|