remove atoms for multithreading
Some checks failed
Build and Deploy / build-linux (push) Failing after 1m42s
Build and Deploy / build-windows (CLANG64) (push) Failing after 6m13s
Build and Deploy / package-dist (push) Has been skipped
Build and Deploy / deploy-itch (push) Has been skipped
Build and Deploy / deploy-gitea (push) Has been skipped

This commit is contained in:
2025-03-11 10:13:15 -05:00
parent 847a3ef314
commit c431f117e9
5 changed files with 455 additions and 521 deletions

View File

@@ -129,7 +129,9 @@ function bare_load(file) {
var res_cache = {}
function console_rec(category, priority, line, file, msg) {
return `[${prosperon.id.substring(0,6)}] ${file}:${line}: [${category} ${priority}]: ${msg}\n`
var now = time.now()
return `[${prosperon.id.substring(0,6)}] [${time.text(now, "mb d yyyy h:nn:ss")}] ${file}:${line}: [${category} ${priority}]: ${msg}\n`
}
io.mkdir('.prosperon')
@@ -276,6 +278,7 @@ globalThis.use = function use(file) {
}
globalThis.json = use('json')
var time = use('time')
function parse_file(content, file) {
if (!content) return {}
@@ -668,6 +671,7 @@ $_.start = function(cb, prg, arg)
"spawn",
"--overling", host.port,
"--id", id,
"--overlingid", prosperon.id
]
if (prg)
@@ -676,6 +680,8 @@ $_.start = function(cb, prg, arg)
if (arg)
argv = argv.concat(cmd.encode(arg))
underlings.add(id)
os.createprocess(argv)
}
$_.start[prosperon.DOC] = `The start function creates a new actor. The callback function receives messages about the new actor, starting with a message containing the new actor's address object.
@@ -691,7 +697,10 @@ $_.stop = function(actor)
if (!actor)
destroyself()
actor_send(actor, {type:"stop"})
if (!underlings.has(actor.id))
throw new Error('Can only call stop on an underling or self.')
actor_send(actor, {type:"stop", id: prosperon.id})
}
$_.stop[prosperon.DOC] = `The stop function stops an underling.`
@@ -718,11 +727,12 @@ var couplings = new Set()
$_.couple = function(actor)
{
console.log(`coupled to ${actor.id}`)
couplings.add(actor.id)
}
$_.couple[prosperon.DOC] = `causes this actor to stop when another actor stops.`
// Shuffles the message to the actor with whatever means available
// Shuffsles the message to the actor with whatever means available
function actor_send(actor, message)
{
if (typeof message !== 'object')
@@ -733,11 +743,18 @@ function actor_send(actor, message)
return
}
console.log(`Getting peer for ${actor.id}`)
var peer = peers[actor.id]
if (!peer) throw new Error(`Could not send message to actor.`)
console.log(`sending message ${json.encode(message)} to ${json.encode(actor)}`)
if (peer) {
peer.send(message)
return
}
try {
os.mailbox_push(actor.id, message)
} catch(e) {
}
throw new Error (`Unable to send message to actor ${json.encode(actor)}`)
}
// Map of reply IDs to functions
@@ -763,14 +780,13 @@ $_.send = function(actor, message, reply)
console.log(`replycc and reply are ${actor[REPLYCC]} and ${actor[REPLY]}`)
actor.id = actor[REPLYCC]
send.return = actor[REPLY]
} else if (peers[actor.id]) {
} else
throw new Error(`Could not send message to actor.`)
}
if (reply) {
var id = util.guid()
replies[id] = reply
send.reply = id
send.id = prosperon.id
}
actor_send(actor, send)
@@ -787,6 +803,9 @@ if (!prosperon.args.id)
else
prosperon.id = prosperon.args.id;
if (prosperon.args.overlingid)
overling = { id: prosperon.args.overlingid }
// now can start the mailbox
os.mailbox_start(prosperon.id);
@@ -800,72 +819,81 @@ var unneeded_timer = $_.delay($_.stop, ar)
function destroyself()
{
console.log('got the message to destroy')
if (overling)
actor_send(overling, { type: "stopped" , id: prosperon.id})
host.flush()
os.exit(0)
}
function handle_actor_disconnect(id)
{
var greeter = greeters[id]
if (greeter) {
greeter({
type: "stopped"
})
// Greeter can now be removed
delete greeters[id]
}
console.log(`actor ${id} disconnected`)
if (couplings.has(id))
$_.stop()
delete peers[id]
delete greeters[id]
}
function handle_message(e)
{
console.log(`handling message ${json.encode(e)}`)
switch (e.data.type) {
case "user":
if (e.data.return) {
console.log(`Message has a return address.`)
var fn = replies[e.data.return]
if (!fn)
throw new Error(`Could not find return function for message ${e.data.return}`)
/*
msg format is:
id: id of the actor that sent the message
reply: reply id for a response
*/
fn(e.data)
delete replies[e.data.return]
function handle_message(msg)
{
switch (msg.type) {
case "user":
if (msg.return) {
console.log(`Message has a return address.`)
var fn = replies[msg.return]
if (!fn)
throw new Error(`Could not find return function for message ${msg.return}`)
fn(msg)
delete replies[msg.return]
return
}
if (receive_fn) {
if (e.data.reply) {
// Doing this here because there is no way for an actor to reply to the message if it doesn't get it in the first place
e.data.data[REPLYCC] = peer2id.get(e.peer)
e.data.data[REPLY] = e.data.reply
console.log(`set replycc and reply to ${e.data.data[REPLYCC]} and ${e.data.data[REPLY]}`)
if (msg.reply) {
msg.data[REPLY] = msg.reply
msg.data[REPLYCC] = msg.id
}
receive_fn(e.data.data)
receive_fn(msg.data)
}
break
case "greet":
peers[e.data.id] = e.peer;
peer2id.set(e.peer, e.data.id);
console.log(`Registered a peer with ${e.data.id}`)
var greeter = greeters[e.data.id]
if (!greeter) return; //throw new Error(`No greeter registered for greet message id ${e.data.id}`)
greeter({
type: "actor_started",
actor: { id: e.data.id }
})
break
case "stop":
if (msg.id !== overling.id)
throw new Error(`Got a message from an actor ${msg.id} to stop, that was not our overling (${overling.id}).`);
destroyself()
break
case "contact":
if (pppfn) pppfn(e.data.data)
if (pppfn) pppfn(msg.data)
break
case "stopped":
handle_actor_disconnect(msg.id)
break
}
}
function handle_connect(e)
{
console.log(`message arrived at ${host.address}:${host.port} from somebody ... ${e.peer.address}:${e.peer.port}`)
var contact = peer2contact.get(e.peer)
if (contact) {
// We have successfully made contact. now send the request.
@@ -878,19 +906,11 @@ function handle_connect(e)
}
// For a local greet
e.peer.send({
type:"greet",
id: prosperon.id
})
e.peer.send({ id: prosperon.id })
}
var hang = 0.001
while (1) {
os.waitevent(e => {
unneeded_timer()
unneeded_timer = $_.delay(unneeded_fn, unneeded_time)
}, hang)
host.service(e => {
unneeded_timer()
switch(e.type) {
@@ -899,14 +919,24 @@ while (1) {
break;
case "receive":
handle_message(e)
if (e.data.id && !peers[e.data.id]) {
// we can hook them up
peers[e.data.id] = e.peer
peer2id.set(e.peer, e.data.id)
// first time they've been seen; if it has a system callback, run it now
var greeter = greeters[e.data.id]
if (greeter)
greeter({
type: "actor_started",
actor: { id: e.data.id }
})
}
handle_message(e.data)
break;
case "disconnect":
var id = peer2id.get(e.peer)
greeters[id]({
type: "actor_stopped"
});
if (!id) throw new Error('A peer disconnected but we had no ID associated with it.')
handle_actor_disconnect(id);
break;
}
@@ -915,6 +945,10 @@ while (1) {
if (portal)
portal.service(portal_fn, hang)
os.mailbox_service(prosperon.id, handle_message)
}
})()

View File

@@ -187,7 +187,7 @@ time.text = function(num, fmt = this.fmt, zone) {
fmt = fmt.replaceAll("h", rec.hour);
fmt = fmt.replaceAll("nn", rec.minute.toString().padStart(2, "0"));
fmt = fmt.replaceAll("n", rec.minute);
fmt = fmt.replaceAll("ss", rec.second.toString().padStart(2, "0"));
fmt = fmt.replaceAll("ss", rec.second.toFixed(2).padStart(2, "0"));
fmt = fmt.replaceAll("s", rec.second);
fmt = fmt.replaceAll("z", zone >= 0 ? "+" + zone : zone);
fmt = fmt.replaceAll(/mm[^bB]/g, rec.month + 1);

File diff suppressed because it is too large Load Diff

View File

@@ -240,7 +240,7 @@ void *value2nota(JSContext *ctx, JSValue v)
nota_buffer_init(&enc->nb, 128);
nota_encode_value(enc, argv[0]);
nota_encode_value(enc, v);
if (enc->cycle) {
JS_FreeValue(ctx, enc->visitedStack);