feat: std.http handler carries an opaque ctx word (PLAN-HTTPZ A1 prep)

Server.init(cfg, handler, ctx); the handler signature gains a usize
third argument delivered verbatim per dispatch — typically a pointer
to the app's own state, since the server owns the call site. A bare
(req, resp) handler had no way to reach app state without globals.
examples/1633 pins the round trip.
This commit is contained in:
agra
2026-06-12 21:22:42 +03:00
parent 721793b4bf
commit 3a97019aa7
39 changed files with 10032 additions and 9872 deletions

View File

@@ -7,9 +7,11 @@
PORT :: 18933;
handler :: (req: *http.Request, resp: *http.Response) {
handler :: (req: *http.Request, resp: *http.Response, ctx: usize) {
if req.path == "/hello" {
resp.body = concat("hello ", req.method);
// the ctx word arrives verbatim (init passed 77)
if ctx != 77 { resp.status = 500; resp.body = "ctx lost"; }
return;
}
if req.path == "/echo" {
@@ -105,7 +107,7 @@ main :: () -> i32 {
request_count = 3,
max_conn = 8,
};
srv, se := http.Server.init(cfg, handler);
srv, se := http.Server.init(cfg, handler, 77);
if se { print("server init failed\n"); return 1; }
buf : [4096]u8 = ---;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -897,7 +897,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -1389,7 +1389,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -1405,7 +1405,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

File diff suppressed because one or more lines are too long

View File

@@ -1381,7 +1381,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

File diff suppressed because one or more lines are too long

View File

@@ -1407,7 +1407,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -1383,7 +1383,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -1381,7 +1381,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -1381,7 +1381,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -1381,7 +1381,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -1381,7 +1381,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -1381,7 +1381,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -1381,7 +1381,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -1381,7 +1381,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -1381,7 +1381,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -904,7 +904,7 @@ declare i1 @ascii_ieq(ptr, ptr, ptr) #0
declare ptr @reason_for(ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr }, i32 }), ptr, ptr, ptr) #0
declare void @Server.init(ptr sret({ { { i64, i32, i64, i64, i64, i64, i64 }, { i32 }, i32, ptr, { ptr, ptr, ptr }, ptr, i64 }, i32 }), ptr, ptr, ptr, i64) #0
; Function Attrs: nounwind
declare void @Server.close(ptr, ptr) #0

View File

@@ -145,9 +145,13 @@ Server :: struct {
lfd: i32 = -1;
conns: [*]Conn = null;
own_alloc: Allocator;
handler: (*Request, *Response) -> void;
// The handler's third argument is `ctx`, an opaque word the app
// gave init — typically a pointer to its own state (store handle,
// config), since the server owns the call site.
handler: (*Request, *Response, usize) -> void;
ctx: usize = 0;
init :: (cfg: Config, handler: (*Request, *Response) -> void) -> (Server, !HttpErr) {
init :: (cfg: Config, handler: (*Request, *Response, usize) -> void, ctx: usize) -> (Server, !HttpErr) {
lfd := socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0);
if lfd < 0 { raise error.Bind; }
one : i32 = 1;
@@ -175,7 +179,7 @@ Server :: struct {
}
return Server.{
cfg = cfg, loop = lp, lfd = lfd, conns = slots,
own_alloc = oa, handler = handler,
own_alloc = oa, handler = handler, ctx = ctx,
};
}
@@ -401,7 +405,7 @@ Server :: struct {
// be parsed as a dot-call on a function named `handler`)
h := self.handler;
resp : Response = .{};
h(@req, @resp);
h(@req, @resp, self.ctx);
c.served += 1;
keep := req.keep_alive and c.served < self.cfg.request_count;