about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorbptato <nincsnevem662@gmail.com>2025-01-11 23:00:30 +0100
committerbptato <nincsnevem662@gmail.com>2025-01-11 23:16:24 +0100
commit7f9c70db17b5dc15aafa142e24d6fdb0da4054ca (patch)
tree070fcb7e2767d9ac9ad9f3907c2c638fe1fbd2b2 /src
parent6551733999a88985aa80c00b646102a267f8575b (diff)
downloadchawan-7f9c70db17b5dc15aafa142e24d6fdb0da4054ca.tar.gz
loader: refcount LoaderBuffer pages
One less unsafe/error prone construct.  Refcounting the page as seq is
unfortunate, but still miles better than zero-filling a non-refcounted
array.  (Plus it works better for base64 decoding.)

The len field is still necessary, because old runtime doesn't support
setLenUninit.  Oh well, it's one wasted word, not the end of the world.

As for the chunks, it looks like the allocator still uses small ones for
the seq, so we're good.
Diffstat (limited to 'src')
-rw-r--r--src/server/loader.nim33
1 files changed, 9 insertions, 24 deletions
diff --git a/src/server/loader.nim b/src/server/loader.nim
index fa983678..a6ddfce5 100644
--- a/src/server/loader.nim
+++ b/src/server/loader.nim
@@ -56,17 +56,15 @@ import utils/twtstr
 const LoaderBufferPageSize = 4016 # 4096 - 64 - 16
 
 type
-  LoaderBufferObj = object
-    page: ptr UncheckedArray[uint8]
-    len: int
-
   CachedItem = ref object
     id: int
     refc: int
     offset: int
     path: string
 
-  LoaderBuffer = ref LoaderBufferObj
+  LoaderBuffer = ref object
+    len: int
+    page: seq[uint8]
 
   LoaderHandle = ref object of RootObj
     registered: bool # track registered state
@@ -148,11 +146,6 @@ type
     configdir*: string
     bookmark*: string
 
-proc `=destroy`(buffer: var LoaderBufferObj) =
-  if buffer.page != nil:
-    dealloc(buffer.page)
-    buffer.page = nil
-
 when defined(debug):
   func `$`*(buffer: LoaderBuffer): string =
     var s = newString(buffer.len)
@@ -181,10 +174,7 @@ template isEmpty(output: OutputHandle): bool =
   output.currentBuffer == nil and not output.suspended
 
 proc newLoaderBuffer(size = LoaderBufferPageSize): LoaderBuffer =
-  return LoaderBuffer(
-    page: cast[ptr UncheckedArray[uint8]](alloc(size)),
-    len: 0
-  )
+  return LoaderBuffer(page: newSeqUninitialized[uint8](size))
 
 proc bufferCleared(output: OutputHandle) =
   assert output.currentBuffer != nil
@@ -252,11 +242,6 @@ proc sendHeaders(handle: InputHandle; headers: Headers) =
     w.swrite(headers)
   handle.output.stream.setBlocking(blocking)
 
-proc recvData(ps: PosixStream; buffer: LoaderBuffer): int {.inline.} =
-  let n = ps.recvData(addr buffer.page[0], buffer.cap)
-  buffer.len = n
-  return n
-
 proc sendData(ps: PosixStream; buffer: LoaderBuffer; si = 0): int {.inline.} =
   assert buffer.len - si > 0
   return ps.sendData(addr buffer.page[si], buffer.len - si)
@@ -628,8 +613,7 @@ proc parseHeaders(handle: InputHandle; buffer: LoaderBuffer): int =
   try:
     if buffer == nil:
       return handle.parseHeaders0(['\n'])
-    assert buffer.page != nil
-    let p = cast[ptr UncheckedArray[char]](buffer.page)
+    let p = cast[ptr UncheckedArray[char]](addr buffer.page[0])
     return handle.parseHeaders0(p.toOpenArray(0, buffer.len - 1))
   except ErrorBrokenPipe:
     handle.parser = nil
@@ -670,9 +654,10 @@ proc handleRead(ctx: LoaderContext; handle: InputHandle;
   while true:
     let buffer = newLoaderBuffer()
     try:
-      let n = handle.stream.recvData(buffer)
+      let n = handle.stream.recvData(buffer.page)
       if n == 0: # EOF
         return hrrUnregister
+      buffer.len = n
       var si = 0
       if handle.parser != nil:
         si = handle.parseHeaders(buffer)
@@ -1037,9 +1022,9 @@ proc loadDataSend(ctx: LoaderContext; handle: InputHandle; s, ct: string) =
     else:
       output.oclose()
     return
-  let buffer = newLoaderBuffer(size = s.len)
+  let buffer = newLoaderBuffer(s.len)
   buffer.len = s.len
-  copyMem(buffer.page, unsafeAddr s[0], s.len)
+  copyMem(addr buffer.page[0], unsafeAddr s[0], s.len)
   case ctx.pushBuffer(output, buffer, 0)
   of pbrUnregister:
     if output.registered: