## io-startup-and-shutdown--premicrothread.pkg
#
# This package tracks open I/O streams and
# does startup/shutdown stuff like closing
# them on exit.
#
# NOTE: there is currently a problem with removing
# the at-functions for streams that get dropped
# by the application, but the system limit on
# open files will limit this. XXX BUGGO FIXME
# Compiled by:
#
src/lib/std/src/standard-core.sublibstipulate
package at = run_at__premicrothread; # run_at__premicrothread is from
src/lib/std/src/nj/run-at--premicrothread.pkgherein
package io_startup_and_shutdown__premicrothread
: Io_Startup_And_Shutdown__Premicrothread # Io_Startup_And_Shutdown__Premicrothread is from
src/lib/std/src/io/io-startup-and-shutdown--premicrothread.api {
Tag = Ref( Void ); # Here we use refcells as ids, taking advantage of the fact that every refcell equals itself but does not equal any other refcell:
# saves us the bother of setting up a counter to issue unique small integers, protecting that counter with a mutex etc etc.
Stream_Startup_And_Shutdown_Actions
=
{
tag: Tag, # Unique ID for this cleaner.
init: Void -> Void, # Called for at::STARTUP_PHASE_5_CLOSE_STALE_OUTPUT_STREAMS
flush: Void -> Void, # Called for at::SHUTDOWN_PHASE_6_FLUSH_OPEN_FILES
close: Void -> Void # Called for at::SHUTDOWN_PHASE_6_CLOSE_OPEN_FILES
};
per_stream_startup_and_shutdown_actions
=
REF ([]: List( Stream_Startup_And_Shutdown_Actions ));
# 'note_stream_startup_and_shutdown_actions'?
fun note_stream_startup_and_shutdown_actions { init, flush, close }
=
{ tag = REF ();
#
per_stream_startup_and_shutdown_actions
:=
{ tag, init, flush, close } ! *per_stream_startup_and_shutdown_actions;
tag;
};
fun get_tag ( { tag, ... } : Stream_Startup_And_Shutdown_Actions) # Internal function.
=
tag;
# 'change_stream_startup_and_shutdown_actions'?
fun change_stream_startup_and_shutdown_actions (t, { init, flush, close } )
=
per_stream_startup_and_shutdown_actions := f *per_stream_startup_and_shutdown_actions
where
fun f (x ! r)
=>
{ t' = get_tag x;
#
if (t' == t) { tag=>t, init, flush, close } ! r;
else x ! f r;
fi;
};
f [] => raise exception DIE "change_stream_startup_and_shutdown_actions: tag not found";
end;
end;
fun drop_stream_startup_and_shutdown_actions tag
=
per_stream_startup_and_shutdown_actions
:=
f *per_stream_startup_and_shutdown_actions # Should really just use filter/remove from
src/lib/std/src/list.api where
fun f (cleaner ! rest) => if (get_tag cleaner == tag) rest; # Drop actions from action list.
else cleaner ! f rest; # Keep actions in action list, process rest of list recursively.
fi;
f [] => []; # Done!
end;
end;
fun run_action_on_all_known_streams field_fn
=
loop *per_stream_startup_and_shutdown_actions
where
fun loop (x ! r)
=>
{ ((field_fn x) ())
except
_ = ();
loop r;
};
loop [] => ();
end;
end;
# run_at__premicrothread is from
src/lib/std/src/nj/run-at--premicrothread.pkg# case (winix__premicrothread::process::get_env "FOO") THE string => ... ; NULL => ... esac;
my _ =
at::schedule
(
"io-startup-and-shutdown--premicrothread.pkg: .close streams", # Text label for debugging displays.
[ at::SHUTDOWN_PHASE_6_CLOSE_OPEN_FILES ], # When to run the function.
\\ _ = { # Ignored arg is at::SHUTDOWN_PHASE_6_CLOSE_OPEN_FILES.
log::log_note__hook := NULL; # Try to stop us from crashing on write-to-dead-fd on "mythryl.log".
log::log_warn__hook := NULL; # Try to stop us from crashing on write-to-dead-fd on "mythryl.log".
# log::log_fatal__hook := NULL; # Commented out because it is no longer Null_Or(...)
# log is from
src/lib/std/src/log.pkg# print "FUBAR: run_action_on_all_known_streams .close; -- io-startup-and-shutdown--premicrothread.pkg/at::SHUTDOWN_PHASE_6_CLOSE_OPEN_FILES/AAA\n";
run_action_on_all_known_streams .close;
# print "FUBAR: run_action_on_all_known_streams .close; -- io-startup-and-shutdown--premicrothread.pkg/at::SHUTDOWN_PHASE_2_CLOSE_OPEN_FILES/ZZZ\n";
}
);
my _ =
at::schedule
(
"io-startup-and-shutdown--premicrothread.pkg: .flush streams", # Text label for debugging displays.
[ at::SHUTDOWN_PHASE_6_FLUSH_OPEN_FILES ], # When to run the function.
\\ _ = { # Ignored arg is at::SHUTDOWN_PHASE_6_FLUSH_OPEN_FILES.
# print "FUBAR: run_action_on_all_known_streams .flush; -- io-startup-and-shutdown--premicrothread.pkg/at::STARTUP_PHASE_4_FLUSH_OPEN_FILES/AAA\n";
run_action_on_all_known_streams .flush;
# print "FUBAR: run_action_on_all_known_streams .flush; -- io-startup-and-shutdown--premicrothread.pkg/at::STARTUP_PHASE_4_FLUSH_OPEN_FILES/ZZZ\n";
}
);
my _ =
at::schedule
(
"io-startup-and-shutdown--premicrothread.pkg: .init streams", # Text label for debugging displays.
[ at::STARTUP_PHASE_5_CLOSE_STALE_OUTPUT_STREAMS ], # When to run the function.
\\ _ = { # Ignored arg is at::STARTUP_PHASE_5_CLOSE_STALE_OUTPUT_STREAMS
# print "FUBAR: run_action_on_all_known_streams .init; -- io-startup-and-shutdown--premicrothread.pkg/at::STARTUP_PHASE_5_CLOSE_STALE_OUTPUT_STREAMS/AAA\n";
run_action_on_all_known_streams .init;
# print "FUBAR: run_action_on_all_known_streams .init; -- io-startup-and-shutdown--premicrothread.pkg/at::STARTUP_PHASE_5_CLOSE_STALE_OUTPUT_STREAMS/ZZZ\n";
}
);
}; # package io_startup_and_shutdown__premicrothread
end;