• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lunarmodules / copas / 23646249946

27 Mar 2026 12:29PM UTC coverage: 85.443% (+0.8%) from 84.693%
23646249946

push

github

web-flow
feat(future): add a future to allow waiting for async results (#181)

54 of 55 new or added lines in 2 files covered. (98.18%)

1 existing line in 1 file now uncovered.

1397 of 1635 relevant lines covered (85.44%)

75413.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/copas/future.lua
1
local copas = require("copas")
7✔
2
local semaphore = require("copas.semaphore")
7✔
3

4
local pcall = pcall
7✔
5
if _VERSION == "Lua 5.1" and not jit then  -- obsolete: only for Lua 5.1 compatibility
7✔
NEW
6
  pcall = require("coxpcall").pcall
1✔
7
end
8

9

10
-- nil-safe versions for pack/unpack
11
local _unpack = unpack or table.unpack
7✔
12
local unpack = function(t, i, j) return _unpack(t, i or 1, j or t.n or #t) end
126✔
13
local pack = function(...) return { n = select("#", ...), ...} end
91✔
14

15

16

17
-- Module table
18

19
local M = {}
7✔
20

21
M.SUCCESS = true
7✔
22
M.PENDING = false
7✔
23
M.ERROR   = "error"
7✔
24

25
setmetatable(M, {
14✔
26
  __index = function(_, k)
27
    error("unknown field 'future." .. tostring(k) .. "'", 2)
7✔
28
  end,
29
})
30

31

32

33
-- Future class
34

35
local future = {}
7✔
36
future.__index = future
7✔
37

38
-- calling on the future executes the `get` method
39
future.__call = function(self, ...) return self:get(...) end
14✔
40

41

42
local function new_future()
43
  local self = setmetatable({
168✔
44
    results = nil, -- results will be stored here in a 'packed' table (pcall-style: true/false prefix)
60✔
45
    sema = semaphore.new(9999, 0, math.huge),
108✔
46
    coro = nil -- the coroutine that will execute the task
60✔
47
  }, future)
84✔
48

49
  return self
84✔
50
end
51

52

53
-- Waits for the task to complete.
54
-- Returns like pcall: true + results on success, false + errmsg on error.
55
function future:get()
7✔
56
  if not self.results then
112✔
57
    self.sema:take(1, math.huge) -- wait until the result is ready
98✔
58
  end
59
  return unpack(self.results)
112✔
60
end
61

62

63
-- Non-blocking check on the future status.
64
-- Returns:
65
--   M.PENDING (false)             -- task not yet complete
66
--   M.SUCCESS (true), results...  -- task completed successfully
67
--   M.ERROR ("error"), errmsg     -- task failed with an error
68
function future:try()
7✔
69
  if not self.results then
28✔
70
    return M.PENDING
7✔
71
  end
72
  if self.results[1] then
21✔
73
    return M.SUCCESS, unpack(self.results, 2)
9✔
74
  else
75
    return M.ERROR, self.results[2]
14✔
76
  end
77
end
78

79

80
-- Cancels the task if it has not yet completed.
81
-- Returns true if cancelled, false if already done.
82
function future:cancel()
7✔
83
  if self.results then
21✔
84
    return false  -- already done (or already cancelled)
7✔
85
  end
86
  self.results = pack(false, "cancelled")
18✔
87
  self.sema:give(self.sema:get_wait())
18✔
88
  copas.removethread(self.coro)
14✔
89
  return true
14✔
90
end
91

92

93

94
-- Module implementation
95

96
-- Mimics copas.addnamedthread but returns a future instead of the coroutine.
97
function M.addnamedthread(name, func, ...)
7✔
98
  local f = new_future()
84✔
99

100
  f.coro = copas.addnamedthread(name, function(...)
168✔
101
    local results
102
    local ok, err = pcall(function(...) results = pack(true, func(...)) end, ...)
172✔
103
    if not ok then
70✔
104
      results = pack(false, err)
18✔
105
    end
106
    if not f.results then  -- don't overwrite a cancel
70✔
107
      f.results = results
70✔
108
      f.sema:give(f.sema:get_wait())
90✔
109
    end
110
  end, ...)
238✔
111

112
  return f
84✔
113
end
114

115

116
-- Mimica copas.addthread but returns a future instead of the coroutine.
117
function M.addthread(func, ...)
7✔
118
  return M.addnamedthread(nil, func, ...)
77✔
119
end
120

121

122
return M
7✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc