open_nonblock(3)
π open_nonblock(3) β the Arcan Lua API glow-up π
okay so bestie, we're in the Arcan Lua API and this page is literally your new fave: open_nonblock, the one that opens files in read or write mode for non-blocking I/O β¨ grab a strawberry drink, we're going in π
πΈ NAME πΈ
open_nonblock β open a file in read or write mode for non-blocking I/O. that's it, that's the whole vibe π
β¨ SYNOPSIS β¨
like, here are all the forms, no cap, all of them:
blocktbl
open_nonblock( vid:res )
open_nonblock( vid:res, bool:write )
open_nonblock( vid:res, bool:write, string:identifier=stream )
open_nonblock( vid:res, bool:write, string:identifier=stream,
userdata:nbioud )
open_nonblock( vid:res, table:opts, string:identifier=stream )
open_nonblock( vid:res, table:opts, string:identifier=stream,
userdata:nbioud )
open_nonblock( string:res )
open_nonblock( string:res, bool:write )
π¦ DESCRIPTION π¦
so what it does: it creates or opens the resource that res points at β in read mode by default, or in write mode if a mode is provided. iconic behaviour, honestly π«Ά
if res is a vid connected to a frameserver, one of two things happens: either a streaming fifo session gets set up over the connection, along with the matching _BCHUNK events, or a pre-existing nonblock-io stream (nbioud) gets redirected to that client and the backing descriptor is closed locally. π₯
then the identifier argument is your moment to specify some client-announced type identifier, or one of the reserved ones: "stdin", "stdout", "stderr". yup, the classics π
if res is a string, the very first character decides what gets made: a FIFO (<) or a SOCKET (=). and unless a namespace is explicitly set and that namespace is marked as valid for IPC, both FIFOs and SOCKETs get created in the RESOURCE_APPL_TEMP namespace. for sockets, the write argument decides the direction: outbound when it's =true, listening when it's =false. pick your fighter π
if the identifier starts with a valid namespace identifier plus separator (alphanum:/), that identifier gets matched against a user-defined namespace first β see list_namespaces. iykyk π
and if res is connected to a frameserver, the namespace identifier is fixed and only defined for connections coming from net_open. the default is to target the private store of the authenticated client. to let the server-side controller script decide instead, prefix the identifier with appl:/. main character energy, fr fr β¨
if it all works out: FIFOs and normal resources return a table with a close operation (which gets activated on garbage collection unless you called it in beforehand, just saying π) plus a read or write function depending on the mode the resource was opened in. slay.
the socket table is special though β it allows multiple connections π the initial table for a socket only has a close and an accept function. accept takes no arguments and returns a table in both read and write mode when there's a client waiting. obsessed π
oh and the opts table argument form? that one's for tuning transfer parameters. cute little knobs, love that for us.
π§ NOTES π§
- do note that input processing has soft realtime constraints β so be careful and don't process large chunks of data in one go, because it may affect application responsiveness. not me warning you lovingly π
FIFOs and sockets that were created will be unlinked when theclosemethod is called, or when the table reference gets garbage collected. it's giving cleanup era.- when a nonblocking userdata is handed over to a frameserver, the
writeargument will be ignored and the correspondingBCHUNKevent will match the userdata. this was a bug in a previous version, where thewriteargument was respected and the argument had to be kept to avoid breaking compatibility. legacy lore π
π EXAMPLE π
function open_nonblock0()
a = open_nonblock("test.txt")
if (a == nil) then
return shutdown("couldn't open test.txt");
end
end
function main_clock_pulse()
local line = a:read();
if (line ~= nil) then
print(line);
end
end
β EXAMPLE β
function open_nonblock1()
a = open_nonblock("=test", false)
b = open_nonblock("=test", true)
-- our reader, note the scoping and the closure here
local counter = 20
local dh
dh =
function()
local res, alive = a:read()
if res then
print("read:", res)
counter = counter - 1
if alive and counter > 0 then
a:data_handler(dh)
return
end
end
a:close() -- will close on error or if counter reaches 0
end
a:data_handler(dh)
end
function main_clock_pulse()
if CLOCK % 100 == 0 then
local _, alive = b:write("sent at " .. tostring(CLOCK))
if not alive then
return shutdown()
end
end
end
π SEE ALSO π
resource β go read that one too bestie, it's the lore π«Ά
π that's the whole page! brought to you by the source/version resource, dated October 2026 β mwah, see you in the next manual, bestie π β¨π
π¦ where this page comes from
- nixos 26.05: arcan 0.7.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms