code: purgatorio

ref: a600cca5ff367ca7e7c64a14a8e87ba376780f6d
dir: /appl/alphabet/grid/remote.b/

View raw version
implement Remote, Gridmodule;
include "sys.m";
	sys: Sys;
include "draw.m";
include "sh.m";
include "alphabet/reports.m";
	reports: Reports;
	report, quit, Report: import reports;
include "alphabet/endpoints.m";
	endpoints: Endpoints;
	Endpoint: import endpoints;
include "alphabet/grid.m";
	grid: Grid;
	Value: import grid;

Remote: module {};

types(): string
{
	return "ef-as";
}

init()
{
	sys = load Sys Sys->PATH;
	reports = checkload(load Reports Reports->PATH, Reports->PATH);
	endpoints = checkload(load Endpoints Endpoints->PATH, Endpoints->PATH);
	endpoints->init();
	grid = checkload(load Grid Grid->PATH, Grid->PATH);
	grid->init();
}

run(nil: chan of string, r: ref Reports->Report,
		opts: list of (int, list of ref Grid->Value), args: list of ref Grid->Value): ref Grid->Value
{
	addr := "local";
	if(opts != nil)
		addr = (hd (hd opts).t1).s().i;
	f := (hd args).f().i;
	spawn remoteproc(ec := chan of Endpoint, f, addr, r.start("remote"));
	return ref Value.Ve(ec);
}

Noendpoint: con Endpoint(nil, nil, nil);

remoteproc(ec: chan of Endpoint, f: chan of ref Sys->FD, addr: string, errorc: chan of string)
{
	(fd1, ep) := endpoints->create(addr);
	if(fd1 == nil){
		report(errorc, "error: remote: cannot create endpoint at "+addr+": "+ep.about);
		ec <-= Noendpoint;
		<-f;
		f <-= nil;
		quit(errorc);
	}
	fd0 := <-f;
	if(fd0 != nil)
		ep.about = sys->sprint("local(%#q)", sys->fd2path(fd0));
	else
		ep.about = "local(pipe)";
	ec <-= ep;
	f <-= fd1;
	quit(errorc);
}

#	sys->pipe(p := array[2] of ref Sys->FD);
#	f <-= p[1];
#	p[1] = nil;
#	buf := array[Sys->ATOMICIO] of byte;
#	while((n := sys->read(p[0], buf, len buf)) > 0){
#		if(sys->write(fd, buf, n) == -1){
#			report(errorc, sys->sprint("write error: %r"));
#			break;
#		}
#	}exception{
#	"write on closed pipe" =>
#		report(errorc, "got write on closed pipe");
#	}
#	sys->write(fd, array[0] of byte, 0);
#	quit(errorc);
#}

checkload[T](m: T, path: string): T
{
	if(m != nil)
		return m;
	raise sys->sprint("fail:cannot load %s: %r", path);
}