Implement delays for indexes() and values()

This commit is contained in:
centauri 2025-08-31 20:37:46 +01:00
parent 5262ef711c
commit 4b4db9602e
5 changed files with 332 additions and 188 deletions

View file

@ -27,7 +27,7 @@ local function ROOT_BENCH(name: string, fn: () -> ())
end)()
end
local N = 2^18 -- 262144
local N = 2^20
TITLE "sources"

View file

@ -1625,9 +1625,12 @@ TEST("indexes()", wrap_root(function()
do -- check that `input` allows gc of `output`
local input = source {}
local output = indexes(input, function(v, i)
return v, i
local destroy, output = root(function()
return indexes(input, function(v, i)
return v, i
end)
end)
destroy()
local wref = weak { output }
@ -1731,6 +1734,81 @@ TEST("indexes()", wrap_root(function()
vide.strict = false
end
do CASE "delay"
local input = source {}
local cleaned_counts = {} :: Map<number, number>
local output = indexes(input, function(v, i, present)
cleanup(function()
cleaned_counts[i] = (cleaned_counts[i] or 0) + 1
end)
return { value = v, index = i, present = present }, 1
end)
local function mapped()
local map = {}
local objects = output()
if objects then
for _, object in objects do
map[object.index] = { value = object.value, present = object.present }
end
end
return map
end
------------------------------------------------------------------------
do
CHECK(mapped()[1] == nil)
end
input { 1, 2 }
do
CHECK(mapped()[1].value() == 1)
CHECK(mapped()[1].present())
CHECK(mapped()[2].value() == 2)
CHECK(mapped()[2].present())
end
input { 2 }
step(0.5)
do
CHECK(mapped()[1].value() == 2)
CHECK(mapped()[1].present())
CHECK(mapped()[2].value() == 2)
CHECK(not mapped()[2].present())
end
input { 1, 2 }
step(0.5 + 0.01)
do
CHECK(mapped()[1].value() == 1)
CHECK(mapped()[1].present())
CHECK(mapped()[2].value() == 2)
CHECK(mapped()[2].present())
end
input { 3 }
step(1 + 0.01)
do
CHECK(mapped()[1].value() == 3)
CHECK(mapped()[1].present())
CHECK(not mapped()[2])
CHECK(cleaned_counts[1] == nil)
CHECK(cleaned_counts[2] == 1)
end
end
end))
TEST("values()", wrap_root(function()
@ -1852,6 +1930,80 @@ TEST("values()", wrap_root(function()
CHECK(n0 == n1)
end
do CASE "delay"
local input = source {}
local cleaned_counts = {} :: Map<number, number>
local output = values(input, function(v, i, present)
cleanup(function()
cleaned_counts[v] = (cleaned_counts[v] or 0) + 1
end)
return { value = v, index = i, present = present }, 1
end)
local function mapped()
local map = {}
local objects = output()
if objects then
for _, object in objects do
map[object.value] = { index = object.index, present = object.present }
end
end
return map
end
------------------------------------------------------------------------
do
CHECK(mapped()[1] == nil)
end
input { 1 }
do
CHECK(mapped()[1].index() == 1)
CHECK(mapped()[1].present())
end
input { 2 }
step(0.5)
do
CHECK(mapped()[1].index() == 1)
CHECK(not mapped()[1].present())
CHECK(mapped()[2].index() == 1)
CHECK(mapped()[2].present())
end
input { 1, 2 }
step(0.5 + 0.01)
do
CHECK(mapped()[1].index() == 1)
CHECK(mapped()[1].present())
CHECK(mapped()[2].index() == 2)
CHECK(mapped()[2].present())
end
input { 3 }
step(1 + 0.01)
do
CHECK(not mapped()[1])
CHECK(not mapped()[2])
CHECK(mapped()[3].index() == 1)
CHECK(mapped()[3].present())
CHECK(cleaned_counts[1] == 1)
CHECK(cleaned_counts[2] == 1)
CHECK(cleaned_counts[3] == nil)
end
end
end))
TEST("spring()", wrap_root(function()