Module copas-async
Copas-friendly true asynchronous threads, powered by Lua Lanes.
When loaded this module will initialize LuaLanes by calling
lanes.configure() without arguments. If you don't want/need that, then
call lanes.configure before loading/requiring this module.
Usage:
local async = require "copas.async" local function sometask() -- do something that takes a while return ok, err end local ok, err = async(sometask)
Info:
- Copyright: Copyright (c) 2016 Hisham Muhammad, 2022-2026 Thijs Schreijer
- License: MIT, see LICENSE.md.
- Author: Hisham Muhammad
Fields
| cancel_timeout | Timeout in seconds before a cancelled lane is force-killed. |
Class future
| future:cancel () | Cancels the future if the task has not yet completed. |
| future:get () | Waits until the async thread finishes (without locking other Copas coroutines) and obtains the result values of the async thread function. |
| future:try () | Obtains the result value of the async thread function if it is already available,
or returns async.PENDING if it is still running. |
Async module
| async.addthread (fn) | Runs a function in its own thread, and returns a future. |
| async.io_popen (command[, mode="r"]) | Convenience function that runs io.popen(command, mode) in its own async thread. |
| async.os_execute (command) | Convenience function that runs an os command in its own async thread. |
| async.run (fn) | Runs a function in its own thread, and waits for the results. |
Fields
- cancel_timeout
-
Timeout in seconds before a cancelled lane is force-killed.
After
future:cancel()the underlying Lanes thread is soft-cancelled first. If it is still running after this many seconds it will be hard-killed (pthread_cancel). Set to math.huge to never force-kill.
Class future
- future:cancel ()
-
Cancels the future if the task has not yet completed.
Returns true if cancelled, false if already done.
Any coroutines blocked in
get()will be released and return false+"cancelled".The underlying Lanes thread is soft-cancelled immediately. If it is still running after
async.cancel_timeoutseconds (e.g. blocked inside a C function such assocket.sleepor os.execute), it will be force-killed. The Copas side is always cancelled immediately; any result produced by the thread afterwards is discarded.Returns:
-
true if cancelled, false if already done
- future:get ()
-
Waits until the async thread finishes (without locking other Copas coroutines) and
obtains the result values of the async thread function.
Calling on the future object is a shortcut to this get method. Multiple coroutines may call get concurrently; all will be released when the result arrives.
Returns:
-
like pcall: true + results on success, false + errmsg on error
Usage:
local msg = "hello" copas(function() -- schedule a thread using LuaLanes local future = async.addthread(function() os.execute("for i in seq 5; do echo 'thread says "..msg.." '$i; sleep 1; done") return 123 end) -- The following will wait for the thread to complete (5 secs) -- Note: calling
future()is the same asfuture:get()local ok, result = future() assert(ok and 123 == result, "expected exit code 123") end) - future:try ()
-
Obtains the result value of the async thread function if it is already available,
or returns
async.PENDINGif it is still running. This function always returns immediately.Returns:
-
async.PENDING(false) when still running -
async.SUCCESS(true) + results when complete -
async.ERROR("error") + errmsg when the task failed
Usage:
local msg = "hello" copas(function() -- schedule a thread using LuaLanes local future = async.addthread(function() os.execute("for i in seq 5; do echo 'thread says "..msg.." '$i; sleep 1; done") return 123 end) -- loop to wait for result local done, result while not done do copas.sleep(0.1) done, result = future:try() end if done == async.ERROR then print("oops... something went wrong: " .. result) else assert(123 == result, "expected exit code 123") end end)
-
Async module
- async.addthread (fn)
-
Runs a function in its own thread, and returns a future.
Note that the function runs in its own Lanes context, so upvalues are copied into the function. When modified in that function, it will not update the original values living Copas side.
Parameters:
- fn function the function to execute async
Returns:
-
a future
- async.io_popen (command[, mode="r"])
-
Convenience function that runs
io.popen(command, mode)in its own async thread. This allows you to easily run long-lived commands in your own coroutine and get their output (async) without affecting the Copas scheduler as a whole.This function returns (immediately) a descriptor object with an API that matches that of the object returned by io.popen. When commands are issued, this causes the current coroutine to wait until the response is returned, without locking other coroutines (in other words, it uses future internally). Only the methods
fd:read,fd:write,fd:close, andfd:linesare currently supported.
Note:fd:linesis not supported on PuC Rio Lua 5.1 (yield across C boundary errors will occur)Parameters:
- command string The command to pass to io.popen in the async thread
- mode string The mode to pass to io.popen in the async thread (default "r")
Returns:
-
descriptor object
- async.os_execute (command)
-
Convenience function that runs an os command in its own async thread.
This allows you to easily run long-lived commands in your own coroutine without
affecting the Copas scheduler as a whole.
This function causes the current coroutine to wait until the command is finished, without blocking other coroutines (in other words, it internally runs
get()in its future).Parameters:
- command string The command to pass to os.execute in the async thread
Returns:
-
like pcall: true + os.execute results on success, false + errmsg on error
- async.run (fn)
-
Runs a function in its own thread, and waits for the results.
This will block the current thread, but will not block other Copas threads.
Returns like pcall: true + results on success, false + errmsg on error.
Parameters:
- fn function the function to execute async
Returns:
-
true + the function's return values, or false + errmsg
Usage:
-- assuming a function returning a value or nil+error, normally called like this; -- -- local result, err = fn() -- -- Can be called non-blocking like this: local ok, result, err = async.run(fn) -- or even shorter; local ok, result, err = async(fn)