#line 29 "/home/ubuntu/felix/src/packages/fibres.fdoc"
open class Fibres
{
private gen _start[t]: (t->0)*t->cont = "$1->clone()->call(0,$2)";
gen start[t] (p:t->0) (x:t) = { return _start (p,x); }
private fun _start0: (1->0)->cont = "$1->clone()->call(0)";
gen start (p:1->0) = { return _start0 (p); }
gen mk_thread: cont->fthread = "new(*ptf-> gcp,::flx::rtl::_fthread_ptr_map,false) ::flx::rtl::fthread_t($1)";
proc spawn_fthread(p:1->0)
{
var con = start p;
var fthr = mk_thread con;
svc$ svc_spawn_fthread fthr;
}
proc schedule_fthread(p:1->0)
{
var con = start p;
var fthr = mk_thread con;
svc$ svc_schedule_fthread fthr;
}
proc suicide: 1 = "throw (con_t*)NULL;";
proc chain : cont = "return $1;" requires property "heap_closure";
type fibre_scheduler = "::flx::run::sync_sched*" requires header '#include "flx_sync.hpp"';
ctor fibre_scheduler: bool = """
new(*ptf-> gcp,::flx::run::sync_sched_ptr_map,false)
::flx::run::sync_sched
(
$1,
ptf-> gcp,
new(*ptf-> gcp, ::flx::run::fthread_list_ptr_map, false) ::flx::run::fthread_list(ptf-> gcp)
)
"""
;
ctor fibre_scheduler () =>
fibre_scheduler (Env::getenv "FLX_DEBUG_DRIVER" != "")
;
proc spawn_fibre: fibre_scheduler * fthread = """
$1->active->push_back($2);
""";
proc frun: (1->0) = "::flx::rtl::executil::frun (ptf-> gcp, $1);"
requires header '#include "flx_executil.hpp"'
;
proc run: fibre_scheduler = "$1->frun();";
proc run (p: 1 -> 0) {
var s = fibre_scheduler();
spawn_fthread s p;
s.run;
}
enum fibre_scheduler_state {
terminated,
blocked,
delegated
};
fun get_state : fibre_scheduler -> fibre_scheduler_state = "$1->fs";
proc spawn_fthread (fs:fibre_scheduler) (p:1->0) { spawn_fibre (fs,p.start.mk_thread); }
type async_scheduler = "::flx::run::async_sched*"
requires header '#include "flx_async.hpp"',
package "flx_arun"
;
ctor async_scheduler: bool = """
new
::flx::run::async_sched
(
ptf-> world, // world object
$1, // debug driver flag
ptf-> gcp, // GC profile object
new(*ptf-> gcp, ::flx::run::fthread_list_ptr_map, false) ::flx::run::fthread_list(ptf-> gcp),
::flx::run::async_sched::mainline // temporary hack! thread kind (should be inherited)
)
"""
;
ctor async_scheduler () =>
async_scheduler (Env::getenv "FLX_DEBUG_DRIVER" != "")
;
proc spawn_fibre: async_scheduler * fthread = """
$1->ss->active->push_back($2);
""";
proc spawn_fthread (fs:async_scheduler) (p:1->0) { spawn_fibre (fs,p.start.mk_thread); }
proc prun: async_scheduler = "$1->prun();";
proc async_run (p: 1 -> 0) {
var s = async_scheduler();
spawn_fthread s p;
s.prun;
}
gen step: cont -> cont = "$1->resume()";
proc kill: fthread = "$1->cc = 0;";
proc run: cont = "::flx::rtl::executil::run($1);" requires package "flx_executil";
private proc _send[t]: &cont * t =
"""
{
using namespace ::flx::rtl;
con_t *tmp = *(con_t**)$1.get_data();
// run target until it reaches a service request (or death)
while(tmp && (!tmp->p_svc || tmp->p_svc->variant == svc_yield)) {
try { tmp=tmp->resume(); }
catch (con_t *x) { tmp = x; }
}
// check it is alive and making the expected service request
if (!tmp)
throw flx_exec_failure_t (__FILE__,"send","Send to terminated procedure");
if (!tmp->p_svc)
throw flx_exec_failure_t (__FILE__,"send","Send to unready Procedure");
if (tmp->p_svc->variant != svc_read)
throw flx_exec_failure_t (__FILE__,"send","Send to Procedure which is not trying to read");
// store the message
**(?1**)tmp->p_svc->data= $2;
// clear the service request
tmp->p_svc = 0;
// run the target until the next service request (or death)
while(tmp && (!tmp->p_svc || tmp->p_svc->variant == svc_yield)) {
try { tmp=tmp->resume(); }
catch (con_t *x) { tmp = x; }
}
// save the new continuation
*(con_t**)$1.get_data() = tmp;
}
""";
proc send[t] (p:&cont) (x:t)
{
_send (p,x);
}
}