add old lci module

This commit is contained in:
qing committed 2026-08-02 20:15:07 +08:00
1 parent 38a6e815f0
commit 8499631091
171 files changed
+25562

No files matched your search

+312
View File
@@ -0,0 +1,312 @@
package phs
import std.sync.*;
/*
* Status 状态
*
* FIXME: 在枚举中定义操作函数
*/
enum Stat {
SHUT | STOP | START | RUNNING
}
/*
* Finite Status Machine 有限状态机
*
*
* FIXME(TritiumQin): 1. 柯里化
*
* FIXME(qing): 支持自定义状态
*/
open class Fsm {
/* 状态枚举 */
private var stat: Stat = STOP
/* 线程安全 */
private let mtx: Mutex = Mutex()
/*
* 条件变量
*
* FIXME: 我不知道这么写意义何在
*/
private let condition: Condition = synchronized(mtx) {
mtx.condition()
}
/* 辅助条件变量的布尔标志 */
private var flag: Bool = true
/* ---------------------------------------------- */
/*
* 阻塞等待状态改变,可以传入一个谓词,以确定什么时候终止
*
* 在该回调函数中返回true,则等待不会停止
*/
public func wait(keep!: (Stat) -> Bool = {_ => false}) {
synchronized(mtx) {
flag = true
while(flag || keep(stat)) {
condition.wait()
}
}
}
/* ---------------------------------------------- */
/*
* 对状态机进行某种操作,输入一个谓词。
*
* 会激活堵塞线程
*/
public func doc(p: (Stat) -> Stat): Stat {
synchronized(mtx) {
stat = p(stat)
flag= false // 试图唤醒阻塞的线程
condition.notifyAll()
return stat
}
}
/*
* 对状态机进行某种操作,输入一个谓词。
*
* 不会激活堵塞线程
*/
public func dop(p: (Stat) -> Stat): Stat {
synchronized(mtx) {
stat = p(stat)
return stat
}
}
}
/* Controllable Thread 可控制线程
*
* FIXME(花间岛):
* 1. 使用async语法糖
* 2. 封装iocp
*/
open class Th {
/* 持有线程类型 */
private var fut: Option<Future<Int64>> = None
/* 持有状态机类型 */
private let fsm: Fsm = Fsm()
/*----------------------------------------------*/
/* 持有静止事件回调 */
private var StopEvent: Option<() -> Unit> = None
/* 持有唤醒事件回调 */
private var WakeEvent: Option<() -> Unit> = None
/* 持有循环事件回调 */
private var LoopEvent: Option<() -> Unit> = None
/* 持有清理事件回调 */
private var ClearEvent: Option<() -> Unit> = None
/* 持有线程主函数回调 */
private var Main: Option<() -> Int64> = None // 线程主函数
/*----------------------------------------------*/
/* 使用谓词检查线程状态 */
public func chkp(): Stat {
return fsm.dop({ stat => return stat })
}
/*----------------------------------------------*/
/* 进入关闭状态 */
public func shut() {
fsm.doc({ _ => return SHUT })
}
/* 进入静止态 */
public func stop() {
fsm.doc({ _ => return STOP })
}
/* 进入启动状态 */
public func start() {
fsm.doc({ _ => return START })
}
/* 进入运行态 */
public func run() {
fsm.doc({ _ => return RUNNING })
}
/*----------------------------------------------*/
/* 状态机是否处于静止态 */
public func isStop() {
return match( chkp() ) {
case STOP => true
case _ => false
}}
/* 状态机是否处于关闭态 */
public func isShut() {
return match( chkp() ) {
case SHUT => true
case _ => false
}}
/* 状态机是否处于开始状态 */
public func isStart() {
return match( chkp() ) {
case START => true
case _ => false
}}
/* 状态机是否处于运行态 */
public func isRunning() {
return match( chkp() ) {
case RUNNING => true
case _ => false
}}
/*----------------------------------------------*/
/* 扮演函数,即设置线程事件 */
public func Act(
/* 静止事件 */
stop!: Option<() -> Unit> = None,
/* 唤醒事件 */
wake!: Option<() -> Unit> = None,
/* 循环事件 */
loop!: Option<() -> Unit> = None,
/* 清理事件 */
clear!:Option<() -> Unit> = None,
/* 线程主函数 */
mainloop!: Option<() -> Int64>= None
)
{
/* 只有静止态才能进行设置 */
if (!isStop()) { return; }
/* ------------------------------------------------- */
/* 设置静止事件,确保退出了静止态 */
StopEvent = stop ?? {=> fsm.wait(keep: {stat =>
match(stat) {
case STOP => true /* 保持等待 */
case _ => false
}
})}
/* 唤醒事件,默认直接进入运行态 */
WakeEvent = wake ?? {=> this.run()}
/* 循环事件,默认进行延时 */
LoopEvent = loop ?? {=> sleep(100 * Duration.millisecond)}
/* 清理事件,默认什么都不做 */
ClearEvent= clear?? {=> ;}
/* ------------------------------------------------- */
/* 线程主函数 */
Main = mainloop ?? {=>
/* 回字形循环 外层 */
while (!isShut()) {
this.inner()
}
return 0
}
/* ------------------------------------------------- */
}
/* ------------- 回字形循环 内层 -------------- */
private func inner() {
/* 静止状态 */
while(isStop()) { StopEvent.getOrThrow()() }
/* 唤醒事件 */
if (isStart()) { WakeEvent.getOrThrow()() }
/* 运行状态 */
while(isRunning()) { LoopEvent.getOrThrow()() }
/* 清理事件 */
ClearEvent.getOrThrow()()
}
/* --------------------------------------------- */
/*
* 创建资源,可控线程苏醒
*
* 如果在调用中等待线程启动,可能会造成死锁
* 想了想觉得也没有这个必要
*/
public func wake() {
/* 存在微小的冲突可能,所以我不让它进入静止态 */
this.start()
/* 创建卵 */
fut = Some<Future<Int64>>(spawn {
Main.getOrThrow()()
})
/* 等启动
*
* 20251020(qing): 如果线程启动太快,该等待可能会导致死锁
*/
//fsm.wait(keep: {stat => match(stat) {
// case START => true
// case _ => false
//}})
}
/* 等待线程结束 */
public func wait() {
let f = fut.getOrThrow()
return f.get()
}
/*
* 关闭线程,然后等待线程结束
*/
public func shut_and_wait() {
shut()
wait()
}
}
+211
View File
@@ -0,0 +1,211 @@
package phs
import std.io.*;
import std.fs.*;
import std.collection.*;
import std.sync.*;
import std.process.*;
import stdx.net.http.*;
import stdx.encoding.json.*;
const ADDR = "127.0.0.1" /* 监听IP地址 */
const PORT = 5200u16 /* 端口 UInt16类型 */
class Ps {
private let ps = LinkedList<SubProcess>()
private let mtx = Mutex()
/* 创建进程 */
public func create(arr: Array<String>) {
let path = arr[0]
let args = arr[1..]
let subp: SubProcess = launch(path, args,
//stdIn: ProcessRedirect.Discard, /* WINDOWS中不支持输入重定向 */
//stdOut: ProcessRedirect.Discard, /* 加了这行之后就在控制台看不到输出了 */
//stdErr: ProcessRedirect.Discard
)
this.clear() /* 清理进程 */
synchronized(mtx) {
ps.addLast(subp)
return;
}
}
/* 返回进程列表 */
public func list() {
var msg = ""
println('1')
this.clear() /* 清理进程,有锁 */
println('2')
synchronized(mtx) {
println('3')
for (p in ps) {
if (msg != "") { msg += "\n"; }
msg += '${p.pid.toString()}\t'
msg += '${p.command} '
//for (i in p.arguments) { /* 加上这个会失败 */
// msg += '${i} '
//}
/* 启动时间 */
msg += '\t${p.userTime.toString()}'
}
println('4')
}
return msg;
}
/* 杀死已经存在的进程 */
public func kill(pid: Int64) {
this.clear() /* 清理 */
synchronized(mtx) {
for (p in ps) {
if (p.pid == pid) {
p.terminate(force: true)
return
}
}
}
}
/*
* 进程自启动
*
* FIXME: 支持注释
*/
public func autoRun(csvpath: String) {
let file = File(csvpath, Read)
let bytes = readToEnd(file)
let ctt = String.fromUtf8(bytes)
let cmds = ctt.split("\n", removeEmpty: true)
for (cmd in cmds) {
try{
let arr = cmd.split(" ", removeEmpty: true)
this.create(arr)
} catch (exp: Exception) {
;
}
}
file.close()
}
/* 清理已经死去的进程,默认不加锁 */
private func clear() {
synchronized(mtx) {
let len = ps.size
for (i in (len-1)..=0 : -1) {
try {
let p = ps.nodeAt(i).getOrThrow()
println("start...")
p.value.wait(timeout: 1 * Duration.millisecond) /* 进程有没有退出 */
println("end...")
ps.remove(p)
}
catch (exp: TimeoutException) { /* 如果进程没有结束,会运行到这里 */
;
println("skip...")
}
}
}
}
}
/*
* 将JSON数组转为字符串的数组
*
* Json对象的每个元素只能是字符串,否则会报错
*/
func Jarr_to_arr(arr: JsonArray): Array<String> {
let len = arr.size() // Json数组的长度
let ret = Array<String>(len, repeat: "")
for (i in 0..len) {
let option: Option<JsonValue> = arr.get(i)
let jitem: JsonValue = option.getOrThrow()
let jstr: JsonString = jitem.asString()
let str: String = jstr.getValue()
ret[i] = str
}
return ret
}
/* cj命令行参数不包含可执行文件名 */
main(_: Array<String>): Int64 {
/* 进程组 */
let ps = Ps()
ps.autoRun("./init.csv")
/* 创建http服务器 */
let server: Server = ServerBuilder()
.addr(ADDR) /* 设置地址 */
.port(PORT) /* 设置端口 */
.build()
/* 创建进程的HTTP方法 */
server.distributor.register("/api/v2/create", { context =>
if (context.request.method == "POST") {
let content = StringReader(context.request.body).readToEnd() /* 阅读请求体 */
let array = JsonValue.fromStr(content).asArray() /* 解析json格式的请求体 */
let net_args: Array<String> = Jarr_to_arr(array) /* json数组转原生数组 */
ps.create(net_args)
/* ---- 准备响应 ---- */
let Headers = HttpHeaders()
Headers.add("Content-Type", "text/html; charset=utf-8;")
context.responseBuilder.setHeaders(Headers)
context.responseBuilder.body('OK')
}
})
/*
* 输出进程列表的HTTP方法
*/
server.distributor.register("/api/v2/list", { context =>
if (context.request.method == "GET") {
println('a')
/* 准备表单字符串 */
let ret = ps.list()
println('b')
/**** 准备响应 ****/
let Headers = HttpHeaders()
Headers.add("Content-Type", "text/html; charset=utf-8;")
context.responseBuilder.setHeaders(Headers)
context.responseBuilder.body(ret)
println('c')
}
})
/* 杀死一个已经存在的进程 */
server.distributor.register("/api/v2/kill", { context =>
if (context.request.method == "POST") {
let content = StringReader(context.request.body).readToEnd() /* 阅读请求体 */
let target_pid = JsonValue.fromStr(content)
.asObject()
.get("pid")
.getOrThrow()
.asInt()
.getValue()
ps.kill(target_pid)
/**** 准备响应 ****/
let Headers = HttpHeaders()
Headers.add("Content-Type", "text/html; charset=utf-8;")
context.responseBuilder.setHeaders(Headers)
context.responseBuilder.body("done")
}
})
/* 服务器开始运行 */
server.serve()
return 0
}