aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Melnichenko <mpeterval@gmail.com>2016-10-06 16:51:04 +0300
committerPeter Melnichenko <mpeterval@gmail.com>2016-10-06 16:51:36 +0300
commiteb7427676a2f09556f9d5f19a1a6392fd945e8bc (patch)
tree49c3e583567c40a5173a603dff941dcb6e415992
parentadcba81974979be3763c8d9d46eb2de9a88ff67c (diff)
downloadluarocks-eb7427676a2f09556f9d5f19a1a6392fd945e8bc.tar.gz
luarocks-eb7427676a2f09556f9d5f19a1a6392fd945e8bc.tar.bz2
luarocks-eb7427676a2f09556f9d5f19a1a6392fd945e8bc.zip
Rewrite util.sortedpairs to avoid using coroutines
util.sortedpairs is used in luarocks loader since @6dc745a. Openresty does not like coroutines being used from inside `require`, resulting in "attempt to yield across C-call boundary" error. New version of util.sortedpairs uses a prepared array of ordered keys instead of coroutines. Ref #620.
-rw-r--r--src/luarocks/util.lua79
1 files changed, 43 insertions, 36 deletions
diff --git a/src/luarocks/util.lua b/src/luarocks/util.lua
index 532bea8b..c9fb7d63 100644
--- a/src/luarocks/util.lua
+++ b/src/luarocks/util.lua
@@ -357,52 +357,59 @@ local function default_sort(a, b)
357 end 357 end
358end 358end
359 359
360-- The iterator function used internally by util.sortedpairs. 360--- A table iterator generator that returns elements sorted by key,
361-- to be used in "for" loops.
361-- @param tbl table: The table to be iterated. 362-- @param tbl table: The table to be iterated.
362-- @param sort_function function or nil: An optional comparison function 363-- @param sort_function function or table or nil: An optional comparison function
363-- to be used by table.sort when sorting keys. 364-- to be used by table.sort when sorting keys, or an array listing an explicit order
364-- @see sortedpairs 365-- for keys. If a value itself is an array, it is taken so that the first element
365local function sortedpairs_iterator(tbl, sort_function) 366-- is a string representing the field name, and the second element is a priority table
366 local ks = util.keys(tbl) 367-- for that key, which is returned by the iterator as the third value after the key
367 if not sort_function or type(sort_function) == "function" then 368-- and the value.
368 table.sort(ks, sort_function or default_sort) 369-- @return function: the iterator function.
369 for _, k in ipairs(ks) do 370function util.sortedpairs(tbl, sort_function)
370 coroutine.yield(k, tbl[k]) 371 sort_function = sort_function or default_sort
371 end 372 local keys = util.keys(tbl)
373 local sub_orders = {}
374
375 if type(sort_function) == "function" then
376 table.sort(keys, sort_function)
372 else 377 else
373 local order = sort_function 378 local order = sort_function
374 local done = {} 379 local ordered_keys = {}
375 for _, k in ipairs(order) do 380 local all_keys = keys
376 local sub_order 381 keys = {}
377 if type(k) == "table" then 382
378 sub_order = k[2] 383 for _, order_entry in ipairs(order) do
379 k = k[1] 384 local key, sub_order
385 if type(order_entry) == "table" then
386 key = order_entry[1]
387 sub_order = order_entry[2]
388 else
389 key = order_entry
380 end 390 end
381 if tbl[k] then 391
382 done[k] = true 392 if tbl[key] then
383 coroutine.yield(k, tbl[k], sub_order) 393 ordered_keys[key] = true
394 sub_orders[key] = sub_order
395 table.insert(keys, key)
384 end 396 end
385 end 397 end
386 table.sort(ks, default_sort) 398
387 for _, k in ipairs(ks) do 399 table.sort(all_keys, default_sort)
388 if not done[k] then 400 for _, key in ipairs(all_keys) do
389 coroutine.yield(k, tbl[k]) 401 if not ordered_keys[key] then
402 table.insert(keys, key)
390 end 403 end
391 end 404 end
392 end 405 end
393end
394 406
395--- A table iterator generator that returns elements sorted by key, 407 local i = 1
396-- to be used in "for" loops. 408 return function()
397-- @param tbl table: The table to be iterated. 409 local key = keys[i]
398-- @param sort_function function or table or nil: An optional comparison function 410 i = i + 1
399-- to be used by table.sort when sorting keys, or an array listing an explicit order 411 return key, tbl[key], sub_orders[key]
400-- for keys. If a value itself is an array, it is taken so that the first element 412 end
401-- is a string representing the field name, and the second element is a priority table
402-- for that key.
403-- @return function: the iterator function.
404function util.sortedpairs(tbl, sort_function)
405 return coroutine.wrap(function() sortedpairs_iterator(tbl, sort_function) end)
406end 413end
407 414
408function util.lua_versions() 415function util.lua_versions()