diff options
author | Peter Melnichenko <mpeterval@gmail.com> | 2016-10-06 16:51:04 +0300 |
---|---|---|
committer | Peter Melnichenko <mpeterval@gmail.com> | 2016-10-06 16:51:36 +0300 |
commit | eb7427676a2f09556f9d5f19a1a6392fd945e8bc (patch) | |
tree | 49c3e583567c40a5173a603dff941dcb6e415992 | |
parent | adcba81974979be3763c8d9d46eb2de9a88ff67c (diff) | |
download | luarocks-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.lua | 79 |
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 |
358 | end | 358 | end |
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 |
365 | local 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 | 370 | function 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 |
393 | end | ||
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. | ||
404 | function util.sortedpairs(tbl, sort_function) | ||
405 | return coroutine.wrap(function() sortedpairs_iterator(tbl, sort_function) end) | ||
406 | end | 413 | end |
407 | 414 | ||
408 | function util.lua_versions() | 415 | function util.lua_versions() |