aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES11
-rw-r--r--CMakeLists.txt5
-rw-r--r--Lanes.sln42
-rw-r--r--Lanes.vcxproj366
-rw-r--r--Makefile2
-rw-r--r--Shared.makefile2
-rw-r--r--deep_userdata_example/deep_userdata_example.cpp16
-rw-r--r--deep_userdata_example/deep_userdata_example.vcxproj221
-rw-r--r--deep_userdata_example/deeptest.lua2
-rw-r--r--docs/index.html151
-rw-r--r--lanes-4.0.0-0.rockspec4
-rw-r--r--src/allocator.cpp2
-rw-r--r--src/allocator.hpp4
-rw-r--r--src/cancel.cpp140
-rw-r--r--src/compat.cpp50
-rw-r--r--src/compat.hpp138
-rw-r--r--src/deep.cpp28
-rw-r--r--src/intercopycontext.cpp189
-rw-r--r--src/keeper.cpp113
-rw-r--r--src/keeper.hpp3
-rw-r--r--src/lane.cpp424
-rw-r--r--src/lane.hpp10
-rw-r--r--src/lanes.cpp126
-rw-r--r--src/lanes.lua42
-rw-r--r--src/lanesconf.h8
-rw-r--r--src/linda.cpp169
-rw-r--r--src/linda.hpp24
-rw-r--r--src/lindafactory.cpp16
-rw-r--r--src/nameof.cpp34
-rw-r--r--src/state.cpp18
-rw-r--r--src/threading.cpp150
-rw-r--r--src/threading.hpp14
-rw-r--r--src/tools.cpp101
-rw-r--r--src/tools.hpp3
-rw-r--r--src/tracker.cpp2
-rw-r--r--src/uniquekey.hpp6
-rw-r--r--src/universe.cpp105
-rw-r--r--src/universe.hpp18
-rw-r--r--tests/appendud.lua2
-rw-r--r--tests/basic.lua17
-rw-r--r--tests/error.lua7
-rw-r--r--tests/finalizer.lua4
-rw-r--r--tests/func_is_string.lua13
-rw-r--r--tests/irayo_closure.lua2
-rw-r--r--tests/launchtest.lua4
-rw-r--r--tests/linda_perf.lua7
-rw-r--r--tests/perftest.lua4
-rw-r--r--tests/pingpong.lua8
-rw-r--r--tests/rupval.lua6
-rw-r--r--tests/tobeclosed.lua5
-rw-r--r--unit_tests/UnitTests.vcxproj237
-rw-r--r--unit_tests/UnitTests.vcxproj.filters38
-rw-r--r--unit_tests/deep_tests.cpp11
-rw-r--r--unit_tests/embedded_tests.cpp12
-rw-r--r--unit_tests/init_and_shutdown.cpp89
-rw-r--r--unit_tests/lane_tests.cpp250
-rw-r--r--unit_tests/linda_tests.cpp160
-rw-r--r--unit_tests/scripts/_utils.lua20
-rw-r--r--unit_tests/scripts/_utils54.lua30
-rw-r--r--unit_tests/scripts/coro/basics.lua97
-rw-r--r--unit_tests/scripts/coro/cancelling_suspended.lua31
-rw-r--r--unit_tests/scripts/coro/collect_yielded_lane.lua64
-rw-r--r--unit_tests/scripts/coro/error_handling.lua6
-rw-r--r--unit_tests/scripts/coro/index_suspended.lua28
-rw-r--r--unit_tests/scripts/coro/join_suspended.lua24
-rw-r--r--unit_tests/scripts/coro/linda_in_close_handler.lua43
-rw-r--r--unit_tests/scripts/coro/regular_function.lua38
-rw-r--r--unit_tests/scripts/coro/resume_basics.lua40
-rw-r--r--unit_tests/scripts/coro/yielding_in_non_coro_errors.lua28
-rw-r--r--unit_tests/scripts/lane/body_is_a_c_function.lua28
-rw-r--r--unit_tests/scripts/lane/cooperative_shutdown.lua16
-rw-r--r--unit_tests/scripts/lane/tasking_cancelling.lua27
-rw-r--r--unit_tests/scripts/lane/tasking_join_test.lua16
-rw-r--r--unit_tests/scripts/lane/tasking_send_receive_code.lua18
-rw-r--r--unit_tests/scripts/lane/uncooperative_shutdown.lua2
-rw-r--r--unit_tests/scripts/linda/send_receive_func_and_string.lua13
-rw-r--r--unit_tests/scripts/linda/wake_period.lua5
-rw-r--r--unit_tests/scripts/misc/deeptest.lua161
-rw-r--r--unit_tests/shared.cpp56
-rw-r--r--unit_tests/shared.h2
80 files changed, 3114 insertions, 1314 deletions
diff --git a/CHANGES b/CHANGES
index ccfa923..17a79f7 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,11 +1,12 @@
1CHANGES: 1CHANGES:
2 2
3CHANGE 2: BGe 27-Nov-24 3CHANGE 2: BGe 05-Jun-25
4 * Internal changes 4 * Internal changes
5 - Lanes is implemented in C++20: thread, condition_variable, mutex, string_view, variant, lambdas, templates, and more! 5 - Lanes is implemented in C++20: thread, condition_variable, mutex, string_view, variant, lambdas, templates, and more!
6 - Almost all platform-specific code is gone (only a small bit for thread priority and affinity remains). 6 - Almost all platform-specific code is gone (only a small bit for thread priority and affinity remains).
7 - Decoda support inactive by default. 7 - Decoda support inactive by default.
8 - Deep userdata interface fully revamped to C++20 too. 8 - Deep userdata interface fully revamped to C++20 too.
9 - Supports Lua 5.5
9 * Lanes API changes 10 * Lanes API changes
10 - Version is now 4.0.0 11 - Version is now 4.0.0
11 - Lanes module: 12 - Lanes module:
@@ -16,6 +17,7 @@ CHANGE 2: BGe 27-Nov-24
16 - new function lanes.finally(). Installs a function that gets called at Lanes shutdown after attempting to terminate all lanes. 17 - new function lanes.finally(). Installs a function that gets called at Lanes shutdown after attempting to terminate all lanes.
17 If some lanes still run after the finalizer, Universe::__gc with raise an error or freeze, depending on its return value. 18 If some lanes still run after the finalizer, Universe::__gc with raise an error or freeze, depending on its return value.
18 - new function lanes.collectgarbage(), to force a full GC cycle in the keeper states. 19 - new function lanes.collectgarbage(), to force a full GC cycle in the keeper states.
20 - new function lanes.thread_priority_range(), to query the valid range of priorities.
19 - Configuration settings: 21 - Configuration settings:
20 - Boolean parameters only accept boolean values. 22 - Boolean parameters only accept boolean values.
21 - allocator provider function is called with a string hint to distinguish internal allocations, lane and keeper states. 23 - allocator provider function is called with a string hint to distinguish internal allocations, lane and keeper states.
@@ -26,6 +28,8 @@ CHANGE 2: BGe 27-Nov-24
26 - verbose_errors removed. Use lane error_trace_level instead. 28 - verbose_errors removed. Use lane error_trace_level instead.
27 - with_timers is false by default. 29 - with_timers is false by default.
28 - Non-deep full userdata are processed during module registration just like ordinary module C functions, making them valid transferable (up)values (for example: io.stdin). 30 - Non-deep full userdata are processed during module registration just like ordinary module C functions, making them valid transferable (up)values (for example: io.stdin).
31 - thread API errors cause a Lua error instead of aborting the program.
32 - thread priorities can now be set using the native range of values, if desired.
29 - Lanes: 33 - Lanes:
30 - Can no longer be "killed" by hard-stopping their thread without any resource cleanup (see lane:cancel()). 34 - Can no longer be "killed" by hard-stopping their thread without any resource cleanup (see lane:cancel()).
31 - lanes.gen() settings: 35 - lanes.gen() settings:
@@ -34,10 +38,9 @@ CHANGE 2: BGe 27-Nov-24
34 - name added. Can be used to set the name early (before the lane body calls lane_threadname()). 38 - name added. Can be used to set the name early (before the lane body calls lane_threadname()).
35 - New generator lanes.coro() to start a lane as a coroutine. 39 - New generator lanes.coro() to start a lane as a coroutine.
36 - New __close metamethod that calls join(). 40 - New __close metamethod that calls join().
37 - lane:join() 41 - lane:join() returns nil, error in case of problem, else returns true followed by the lane body return values.
38 - Returns nil, error in case of problem.
39 - Forces lane function body must return a non-nil first value on success because of the above.
40 - lane:get_debug_threadname() renamed get_threadname(). 42 - lane:get_debug_threadname() renamed get_threadname().
43 - cancel_test() returns "soft"/"hard" instead of true when a cancellation request is active.
41 - Lindas: 44 - Lindas:
42 - lanes.linda() 45 - lanes.linda()
43 - Arguments can be provided in any order. 46 - Arguments can be provided in any order.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index be6a2f2..2c5c66f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,9 +3,10 @@
3# Redistribution and use of this file is allowed according to the terms of the MIT license. 3# Redistribution and use of this file is allowed according to the terms of the MIT license.
4# For details see the COPYRIGHT file distributed with LuaDist. 4# For details see the COPYRIGHT file distributed with LuaDist.
5# Please note that the package source code is licensed under its own license. 5# Please note that the package source code is licensed under its own license.
6CMAKE_MINIMUM_REQUIRED(VERSION 3.18)
7PROJECT(lanes CXX)
8set (CMAKE_CXX_STANDARD 20)
6 9
7PROJECT(lanes C)
8CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
9 10
10 11
11FIND_PACKAGE(Lua51 REQUIRED) 12FIND_PACKAGE(Lua51 REQUIRED)
diff --git a/Lanes.sln b/Lanes.sln
index b5c1d89..bc88a79 100644
--- a/Lanes.sln
+++ b/Lanes.sln
@@ -30,6 +30,9 @@ Global
30 Debug 5.4|Prospero = Debug 5.4|Prospero 30 Debug 5.4|Prospero = Debug 5.4|Prospero
31 Debug 5.4|x64 = Debug 5.4|x64 31 Debug 5.4|x64 = Debug 5.4|x64
32 Debug 5.4|x86 = Debug 5.4|x86 32 Debug 5.4|x86 = Debug 5.4|x86
33 Debug 5.5|Prospero = Debug 5.5|Prospero
34 Debug 5.5|x64 = Debug 5.5|x64
35 Debug 5.5|x86 = Debug 5.5|x86
33 Release 5.1|Prospero = Release 5.1|Prospero 36 Release 5.1|Prospero = Release 5.1|Prospero
34 Release 5.1|x64 = Release 5.1|x64 37 Release 5.1|x64 = Release 5.1|x64
35 Release 5.1|x86 = Release 5.1|x86 38 Release 5.1|x86 = Release 5.1|x86
@@ -42,6 +45,9 @@ Global
42 Release 5.4|Prospero = Release 5.4|Prospero 45 Release 5.4|Prospero = Release 5.4|Prospero
43 Release 5.4|x64 = Release 5.4|x64 46 Release 5.4|x64 = Release 5.4|x64
44 Release 5.4|x86 = Release 5.4|x86 47 Release 5.4|x86 = Release 5.4|x86
48 Release 5.5|Prospero = Release 5.5|Prospero
49 Release 5.5|x64 = Release 5.5|x64
50 Release 5.5|x86 = Release 5.5|x86
45 Release LuaJIT|Prospero = Release LuaJIT|Prospero 51 Release LuaJIT|Prospero = Release LuaJIT|Prospero
46 Release LuaJIT|x64 = Release LuaJIT|x64 52 Release LuaJIT|x64 = Release LuaJIT|x64
47 Release LuaJIT|x86 = Release LuaJIT|x86 53 Release LuaJIT|x86 = Release LuaJIT|x86
@@ -74,6 +80,12 @@ Global
74 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.4|x64.Build.0 = Debug 5.4|x64 80 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.4|x64.Build.0 = Debug 5.4|x64
75 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.4|x86.ActiveCfg = Debug 5.4|Win32 81 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.4|x86.ActiveCfg = Debug 5.4|Win32
76 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.4|x86.Build.0 = Debug 5.4|Win32 82 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.4|x86.Build.0 = Debug 5.4|Win32
83 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.5|Prospero.ActiveCfg = Debug 5.5|Prospero
84 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.5|Prospero.Build.0 = Debug 5.5|Prospero
85 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.5|x64.ActiveCfg = Debug 5.5|x64
86 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.5|x64.Build.0 = Debug 5.5|x64
87 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.5|x86.ActiveCfg = Debug 5.5|Win32
88 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Debug 5.5|x86.Build.0 = Debug 5.5|Win32
77 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.1|Prospero.ActiveCfg = Release 5.1|Prospero 89 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.1|Prospero.ActiveCfg = Release 5.1|Prospero
78 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.1|Prospero.Build.0 = Release 5.1|Prospero 90 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.1|Prospero.Build.0 = Release 5.1|Prospero
79 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.1|x64.ActiveCfg = Release 5.1|x64 91 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.1|x64.ActiveCfg = Release 5.1|x64
@@ -98,6 +110,12 @@ Global
98 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.4|x64.Build.0 = Release 5.4|x64 110 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.4|x64.Build.0 = Release 5.4|x64
99 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.4|x86.ActiveCfg = Release 5.4|Win32 111 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.4|x86.ActiveCfg = Release 5.4|Win32
100 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.4|x86.Build.0 = Release 5.4|Win32 112 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.4|x86.Build.0 = Release 5.4|Win32
113 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.5|Prospero.ActiveCfg = Release 5.5|Prospero
114 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.5|Prospero.Build.0 = Release 5.5|Prospero
115 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.5|x64.ActiveCfg = Release 5.5|x64
116 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.5|x64.Build.0 = Release 5.5|x64
117 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.5|x86.ActiveCfg = Release 5.5|Win32
118 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release 5.5|x86.Build.0 = Release 5.5|Win32
101 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release LuaJIT|Prospero.ActiveCfg = Release LuaJIT|Prospero 119 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release LuaJIT|Prospero.ActiveCfg = Release LuaJIT|Prospero
102 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release LuaJIT|Prospero.Build.0 = Release LuaJIT|Prospero 120 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release LuaJIT|Prospero.Build.0 = Release LuaJIT|Prospero
103 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release LuaJIT|x64.ActiveCfg = Release LuaJIT|x64 121 {1DB7D861-EEFD-49DC-A8E2-3FC2BD6AD49D}.Release LuaJIT|x64.ActiveCfg = Release LuaJIT|x64
@@ -134,6 +152,12 @@ Global
134 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.4|x64.Build.0 = Debug 5.4|x64 152 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.4|x64.Build.0 = Debug 5.4|x64
135 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.4|x86.ActiveCfg = Debug 5.4|Win32 153 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.4|x86.ActiveCfg = Debug 5.4|Win32
136 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.4|x86.Build.0 = Debug 5.4|Win32 154 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.4|x86.Build.0 = Debug 5.4|Win32
155 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.5|Prospero.ActiveCfg = Debug 5.5|Prospero
156 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.5|Prospero.Build.0 = Debug 5.5|Prospero
157 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.5|x64.ActiveCfg = Debug 5.5|x64
158 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.5|x64.Build.0 = Debug 5.5|x64
159 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.5|x86.ActiveCfg = Debug 5.5|Win32
160 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Debug 5.5|x86.Build.0 = Debug 5.5|Win32
137 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.1|Prospero.ActiveCfg = Release 5.1|Prospero 161 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.1|Prospero.ActiveCfg = Release 5.1|Prospero
138 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.1|Prospero.Build.0 = Release 5.1|Prospero 162 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.1|Prospero.Build.0 = Release 5.1|Prospero
139 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.1|x64.ActiveCfg = Release 5.1|x64 163 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.1|x64.ActiveCfg = Release 5.1|x64
@@ -158,6 +182,12 @@ Global
158 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.4|x64.Build.0 = Release 5.4|x64 182 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.4|x64.Build.0 = Release 5.4|x64
159 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.4|x86.ActiveCfg = Release 5.4|Win32 183 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.4|x86.ActiveCfg = Release 5.4|Win32
160 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.4|x86.Build.0 = Release 5.4|Win32 184 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.4|x86.Build.0 = Release 5.4|Win32
185 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.5|Prospero.ActiveCfg = Release 5.5|Prospero
186 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.5|Prospero.Build.0 = Release 5.5|Prospero
187 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.5|x64.ActiveCfg = Release 5.5|x64
188 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.5|x64.Build.0 = Release 5.5|x64
189 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.5|x86.ActiveCfg = Release 5.5|Win32
190 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release 5.5|x86.Build.0 = Release 5.5|Win32
161 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release LuaJIT|Prospero.ActiveCfg = Release LuaJIT|Prospero 191 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release LuaJIT|Prospero.ActiveCfg = Release LuaJIT|Prospero
162 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release LuaJIT|Prospero.Build.0 = Release LuaJIT|Prospero 192 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release LuaJIT|Prospero.Build.0 = Release LuaJIT|Prospero
163 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release LuaJIT|x64.ActiveCfg = Release LuaJIT|x64 193 {AED7F42F-139A-46BA-80FE-16E062EA1345}.Release LuaJIT|x64.ActiveCfg = Release LuaJIT|x64
@@ -194,6 +224,12 @@ Global
194 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.4|x64.Build.0 = Debug 5.4|x64 224 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.4|x64.Build.0 = Debug 5.4|x64
195 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.4|x86.ActiveCfg = Debug 5.4|Win32 225 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.4|x86.ActiveCfg = Debug 5.4|Win32
196 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.4|x86.Build.0 = Debug 5.4|Win32 226 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.4|x86.Build.0 = Debug 5.4|Win32
227 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.5|Prospero.ActiveCfg = Debug 5.5|Prospero
228 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.5|Prospero.Build.0 = Debug 5.5|Prospero
229 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.5|x64.ActiveCfg = Debug 5.5|x64
230 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.5|x64.Build.0 = Debug 5.5|x64
231 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.5|x86.ActiveCfg = Debug 5.5|Win32
232 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Debug 5.5|x86.Build.0 = Debug 5.5|Win32
197 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.1|Prospero.ActiveCfg = Release 5.1|Prospero 233 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.1|Prospero.ActiveCfg = Release 5.1|Prospero
198 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.1|Prospero.Build.0 = Release 5.1|Prospero 234 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.1|Prospero.Build.0 = Release 5.1|Prospero
199 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.1|x64.ActiveCfg = Release 5.1|x64 235 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.1|x64.ActiveCfg = Release 5.1|x64
@@ -218,6 +254,12 @@ Global
218 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.4|x64.Build.0 = Release 5.4|x64 254 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.4|x64.Build.0 = Release 5.4|x64
219 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.4|x86.ActiveCfg = Release 5.4|Win32 255 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.4|x86.ActiveCfg = Release 5.4|Win32
220 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.4|x86.Build.0 = Release 5.4|Win32 256 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.4|x86.Build.0 = Release 5.4|Win32
257 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.5|Prospero.ActiveCfg = Release 5.5|Prospero
258 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.5|Prospero.Build.0 = Release 5.5|Prospero
259 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.5|x64.ActiveCfg = Release 5.5|x64
260 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.5|x64.Build.0 = Release 5.5|x64
261 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.5|x86.ActiveCfg = Release 5.5|Win32
262 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release 5.5|x86.Build.0 = Release 5.5|Win32
221 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release LuaJIT|Prospero.ActiveCfg = Release LuaJIT|Prospero 263 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release LuaJIT|Prospero.ActiveCfg = Release LuaJIT|Prospero
222 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release LuaJIT|Prospero.Build.0 = Release LuaJIT|Prospero 264 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release LuaJIT|Prospero.Build.0 = Release LuaJIT|Prospero
223 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release LuaJIT|x64.ActiveCfg = Release LuaJIT|x64 265 {4C40BD18-3BAB-46D7-8F14-602A6FBE5910}.Release LuaJIT|x64.ActiveCfg = Release LuaJIT|x64
diff --git a/Lanes.vcxproj b/Lanes.vcxproj
index 89a1652..3d49d9e 100644
--- a/Lanes.vcxproj
+++ b/Lanes.vcxproj
@@ -49,6 +49,30 @@
49 <Configuration>Debug 5.4</Configuration> 49 <Configuration>Debug 5.4</Configuration>
50 <Platform>x64</Platform> 50 <Platform>x64</Platform>
51 </ProjectConfiguration> 51 </ProjectConfiguration>
52 <ProjectConfiguration Include="Debug 5.5|Prospero">
53 <Configuration>Debug 5.5</Configuration>
54 <Platform>Prospero</Platform>
55 </ProjectConfiguration>
56 <ProjectConfiguration Include="Debug 5.5|Win32">
57 <Configuration>Debug 5.5</Configuration>
58 <Platform>Win32</Platform>
59 </ProjectConfiguration>
60 <ProjectConfiguration Include="Debug 5.5|x64">
61 <Configuration>Debug 5.5</Configuration>
62 <Platform>x64</Platform>
63 </ProjectConfiguration>
64 <ProjectConfiguration Include="Release 5.5|Prospero">
65 <Configuration>Release 5.5</Configuration>
66 <Platform>Prospero</Platform>
67 </ProjectConfiguration>
68 <ProjectConfiguration Include="Release 5.5|Win32">
69 <Configuration>Release 5.5</Configuration>
70 <Platform>Win32</Platform>
71 </ProjectConfiguration>
72 <ProjectConfiguration Include="Release 5.5|x64">
73 <Configuration>Release 5.5</Configuration>
74 <Platform>x64</Platform>
75 </ProjectConfiguration>
52 <ProjectConfiguration Include="Release LuaJIT|Prospero"> 76 <ProjectConfiguration Include="Release LuaJIT|Prospero">
53 <Configuration>Release LuaJIT</Configuration> 77 <Configuration>Release LuaJIT</Configuration>
54 <Platform>Prospero</Platform> 78 <Platform>Prospero</Platform>
@@ -183,6 +207,12 @@
183 <PlatformToolset>v143</PlatformToolset> 207 <PlatformToolset>v143</PlatformToolset>
184 <UseDebugLibraries>true</UseDebugLibraries> 208 <UseDebugLibraries>true</UseDebugLibraries>
185 </PropertyGroup> 209 </PropertyGroup>
210 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'" Label="Configuration">
211 <ConfigurationType>DynamicLibrary</ConfigurationType>
212 <CharacterSet>NotSet</CharacterSet>
213 <PlatformToolset>v143</PlatformToolset>
214 <UseDebugLibraries>true</UseDebugLibraries>
215 </PropertyGroup>
186 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'" Label="Configuration"> 216 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'" Label="Configuration">
187 <ConfigurationType>DynamicLibrary</ConfigurationType> 217 <ConfigurationType>DynamicLibrary</ConfigurationType>
188 <CharacterSet>NotSet</CharacterSet> 218 <CharacterSet>NotSet</CharacterSet>
@@ -201,6 +231,12 @@
201 <PlatformToolset>v143</PlatformToolset> 231 <PlatformToolset>v143</PlatformToolset>
202 <WholeProgramOptimization>true</WholeProgramOptimization> 232 <WholeProgramOptimization>true</WholeProgramOptimization>
203 </PropertyGroup> 233 </PropertyGroup>
234 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'" Label="Configuration">
235 <ConfigurationType>DynamicLibrary</ConfigurationType>
236 <CharacterSet>NotSet</CharacterSet>
237 <PlatformToolset>v143</PlatformToolset>
238 <WholeProgramOptimization>true</WholeProgramOptimization>
239 </PropertyGroup>
204 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'" Label="Configuration"> 240 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'" Label="Configuration">
205 <ConfigurationType>DynamicLibrary</ConfigurationType> 241 <ConfigurationType>DynamicLibrary</ConfigurationType>
206 <CharacterSet>NotSet</CharacterSet> 242 <CharacterSet>NotSet</CharacterSet>
@@ -225,6 +261,12 @@
225 <PlatformToolset>v143</PlatformToolset> 261 <PlatformToolset>v143</PlatformToolset>
226 <UseDebugLibraries>true</UseDebugLibraries> 262 <UseDebugLibraries>true</UseDebugLibraries>
227 </PropertyGroup> 263 </PropertyGroup>
264 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'" Label="Configuration">
265 <ConfigurationType>DynamicLibrary</ConfigurationType>
266 <CharacterSet>NotSet</CharacterSet>
267 <PlatformToolset>v143</PlatformToolset>
268 <UseDebugLibraries>true</UseDebugLibraries>
269 </PropertyGroup>
228 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'" Label="Configuration"> 270 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'" Label="Configuration">
229 <ConfigurationType>DynamicLibrary</ConfigurationType> 271 <ConfigurationType>DynamicLibrary</ConfigurationType>
230 <CharacterSet>NotSet</CharacterSet> 272 <CharacterSet>NotSet</CharacterSet>
@@ -243,6 +285,12 @@
243 <PlatformToolset>v143</PlatformToolset> 285 <PlatformToolset>v143</PlatformToolset>
244 <WholeProgramOptimization>true</WholeProgramOptimization> 286 <WholeProgramOptimization>true</WholeProgramOptimization>
245 </PropertyGroup> 287 </PropertyGroup>
288 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'" Label="Configuration">
289 <ConfigurationType>DynamicLibrary</ConfigurationType>
290 <CharacterSet>NotSet</CharacterSet>
291 <PlatformToolset>v143</PlatformToolset>
292 <WholeProgramOptimization>true</WholeProgramOptimization>
293 </PropertyGroup>
246 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'" Label="Configuration"> 294 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'" Label="Configuration">
247 <ConfigurationType>DynamicLibrary</ConfigurationType> 295 <ConfigurationType>DynamicLibrary</ConfigurationType>
248 <CharacterSet>NotSet</CharacterSet> 296 <CharacterSet>NotSet</CharacterSet>
@@ -275,6 +323,10 @@
275 <PlatformToolset>Clang</PlatformToolset> 323 <PlatformToolset>Clang</PlatformToolset>
276 <ConfigurationType>DynamicLibrary</ConfigurationType> 324 <ConfigurationType>DynamicLibrary</ConfigurationType>
277 </PropertyGroup> 325 </PropertyGroup>
326 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Prospero'" Label="Configuration">
327 <PlatformToolset>Clang</PlatformToolset>
328 <ConfigurationType>DynamicLibrary</ConfigurationType>
329 </PropertyGroup>
278 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'"> 330 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'">
279 <PlatformToolset>Clang</PlatformToolset> 331 <PlatformToolset>Clang</PlatformToolset>
280 <ConfigurationType>DynamicLibrary</ConfigurationType> 332 <ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -291,6 +343,10 @@
291 <PlatformToolset>Clang</PlatformToolset> 343 <PlatformToolset>Clang</PlatformToolset>
292 <ConfigurationType>DynamicLibrary</ConfigurationType> 344 <ConfigurationType>DynamicLibrary</ConfigurationType>
293 </PropertyGroup> 345 </PropertyGroup>
346 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Prospero'" Label="Configuration">
347 <PlatformToolset>Clang</PlatformToolset>
348 <ConfigurationType>DynamicLibrary</ConfigurationType>
349 </PropertyGroup>
294 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'"> 350 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'">
295 <PlatformToolset>Clang</PlatformToolset> 351 <PlatformToolset>Clang</PlatformToolset>
296 <ConfigurationType>DynamicLibrary</ConfigurationType> 352 <ConfigurationType>DynamicLibrary</ConfigurationType>
@@ -322,6 +378,9 @@
322 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'" Label="PropertySheets"> 378 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'" Label="PropertySheets">
323 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 379 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
324 </ImportGroup> 380 </ImportGroup>
381 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'" Label="PropertySheets">
382 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
383 </ImportGroup>
325 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'" Label="PropertySheets"> 384 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'" Label="PropertySheets">
326 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 385 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
327 </ImportGroup> 386 </ImportGroup>
@@ -331,6 +390,9 @@
331 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'" Label="PropertySheets"> 390 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'" Label="PropertySheets">
332 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 391 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
333 </ImportGroup> 392 </ImportGroup>
393 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'" Label="PropertySheets">
394 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
395 </ImportGroup>
334 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'" Label="PropertySheets"> 396 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'" Label="PropertySheets">
335 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 397 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
336 </ImportGroup> 398 </ImportGroup>
@@ -343,6 +405,9 @@
343 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'" Label="PropertySheets"> 405 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'" Label="PropertySheets">
344 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 406 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
345 </ImportGroup> 407 </ImportGroup>
408 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'" Label="PropertySheets">
409 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
410 </ImportGroup>
346 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'" Label="PropertySheets"> 411 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'" Label="PropertySheets">
347 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 412 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
348 </ImportGroup> 413 </ImportGroup>
@@ -352,6 +417,9 @@
352 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'" Label="PropertySheets"> 417 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'" Label="PropertySheets">
353 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 418 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
354 </ImportGroup> 419 </ImportGroup>
420 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'" Label="PropertySheets">
421 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
422 </ImportGroup>
355 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'" Label="PropertySheets"> 423 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'" Label="PropertySheets">
356 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 424 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
357 </ImportGroup> 425 </ImportGroup>
@@ -365,37 +433,46 @@
365 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 433 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
366 <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 434 <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
367 <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 435 <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
436 <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
368 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 437 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
369 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 438 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
370 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 439 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
440 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
371 <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 441 <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
372 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 442 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
373 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 443 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
374 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 444 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
375 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 445 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
446 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
376 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 447 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
377 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 448 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
378 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 449 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
450 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
379 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 451 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
380 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 452 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
381 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 453 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
382 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 454 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
455 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
383 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 456 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
384 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 457 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
385 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 458 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
459 <IntDir Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
386 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 460 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
387 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 461 <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
388 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">false</LinkIncremental> 462 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">false</LinkIncremental>
389 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">false</LinkIncremental> 463 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">false</LinkIncremental>
390 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">false</LinkIncremental> 464 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">false</LinkIncremental>
391 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">false</LinkIncremental> 465 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">false</LinkIncremental>
466 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">false</LinkIncremental>
392 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">false</LinkIncremental> 467 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">false</LinkIncremental>
393 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">false</LinkIncremental> 468 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">false</LinkIncremental>
394 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">false</LinkIncremental> 469 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">false</LinkIncremental>
395 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">false</LinkIncremental> 470 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">false</LinkIncremental>
471 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">false</LinkIncremental>
396 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">false</LinkIncremental> 472 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">false</LinkIncremental>
397 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">false</LinkIncremental> 473 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">false</LinkIncremental>
398 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">false</LinkIncremental> 474 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">false</LinkIncremental>
475 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">false</LinkIncremental>
399 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">false</LinkIncremental> 476 <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">false</LinkIncremental>
400 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 477 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
401 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 478 <OutDir Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Win32'">$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
@@ -410,16 +487,20 @@
410 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">lanes_core</TargetName> 487 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">lanes_core</TargetName>
411 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">lanes_core</TargetName> 488 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">lanes_core</TargetName>
412 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">lanes_core</TargetName> 489 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">lanes_core</TargetName>
490 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">lanes_core</TargetName>
413 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">lanes_core</TargetName> 491 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">lanes_core</TargetName>
414 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">lanes_core</TargetName> 492 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">lanes_core</TargetName>
415 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">lanes_core</TargetName> 493 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">lanes_core</TargetName>
494 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">lanes_core</TargetName>
416 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">lanes_core</TargetName> 495 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">lanes_core</TargetName>
417 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">lanes_core</TargetName> 496 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">lanes_core</TargetName>
418 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">lanes_core</TargetName> 497 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">lanes_core</TargetName>
419 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">lanes_core</TargetName> 498 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">lanes_core</TargetName>
499 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">lanes_core</TargetName>
420 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">lanes_core</TargetName> 500 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">lanes_core</TargetName>
421 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">lanes_core</TargetName> 501 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">lanes_core</TargetName>
422 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">lanes_core</TargetName> 502 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">lanes_core</TargetName>
503 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">lanes_core</TargetName>
423 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">lanes_core</TargetName> 504 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">lanes_core</TargetName>
424 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">lanes_core</TargetName> 505 <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">lanes_core</TargetName>
425 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'">lanes_core</TargetName> 506 <TargetName Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'">lanes_core</TargetName>
@@ -447,6 +528,10 @@
447 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 528 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
448 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis> 529 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
449 </PropertyGroup> 530 </PropertyGroup>
531 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">
532 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
533 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
534 </PropertyGroup>
450 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'"> 535 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">
451 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 536 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
452 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis> 537 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
@@ -459,6 +544,10 @@
459 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 544 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
460 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis> 545 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
461 </PropertyGroup> 546 </PropertyGroup>
547 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">
548 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
549 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
550 </PropertyGroup>
462 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'"> 551 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">
463 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 552 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
464 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis> 553 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
@@ -479,6 +568,10 @@
479 <LinkIncremental>false</LinkIncremental> 568 <LinkIncremental>false</LinkIncremental>
480 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis> 569 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
481 </PropertyGroup> 570 </PropertyGroup>
571 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">
572 <LinkIncremental>false</LinkIncremental>
573 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
574 </PropertyGroup>
482 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'"> 575 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">
483 <LinkIncremental>false</LinkIncremental> 576 <LinkIncremental>false</LinkIncremental>
484 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis> 577 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
@@ -502,6 +595,9 @@
502 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'"> 595 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">
503 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis> 596 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
504 </PropertyGroup> 597 </PropertyGroup>
598 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">
599 <EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
600 </PropertyGroup>
505 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Prospero'"> 601 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Prospero'">
506 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 602 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
507 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 603 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
@@ -522,6 +618,11 @@
522 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 618 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
523 <TargetName>lanes_core</TargetName> 619 <TargetName>lanes_core</TargetName>
524 </PropertyGroup> 620 </PropertyGroup>
621 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Prospero'">
622 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
623 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
624 <TargetName>lanes_core</TargetName>
625 </PropertyGroup>
525 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'"> 626 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'">
526 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 627 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
527 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 628 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
@@ -552,6 +653,11 @@
552 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 653 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
553 <TargetName>lanes_core</TargetName> 654 <TargetName>lanes_core</TargetName>
554 </PropertyGroup> 655 </PropertyGroup>
656 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Prospero'">
657 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
658 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
659 <TargetName>lanes_core</TargetName>
660 </PropertyGroup>
555 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'"> 661 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">
556 <PreBuildEvent> 662 <PreBuildEvent>
557 <Command> 663 <Command>
@@ -560,7 +666,7 @@
560 <ClCompile> 666 <ClCompile>
561 <Optimization>Disabled</Optimization> 667 <Optimization>Disabled</Optimization>
562 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 668 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
563 <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 669 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
564 <MinimalRebuild>false</MinimalRebuild> 670 <MinimalRebuild>false</MinimalRebuild>
565 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 671 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
566 <PrecompiledHeader>Use</PrecompiledHeader> 672 <PrecompiledHeader>Use</PrecompiledHeader>
@@ -598,7 +704,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
598 <ClCompile> 704 <ClCompile>
599 <Optimization>MaxSpeed</Optimization> 705 <Optimization>MaxSpeed</Optimization>
600 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 706 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
601 <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 707 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
602 <MinimalRebuild>false</MinimalRebuild> 708 <MinimalRebuild>false</MinimalRebuild>
603 <BasicRuntimeChecks> 709 <BasicRuntimeChecks>
604 </BasicRuntimeChecks> 710 </BasicRuntimeChecks>
@@ -639,7 +745,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
639 <ClCompile> 745 <ClCompile>
640 <Optimization>Disabled</Optimization> 746 <Optimization>Disabled</Optimization>
641 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 747 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
642 <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 748 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
643 <MinimalRebuild>false</MinimalRebuild> 749 <MinimalRebuild>false</MinimalRebuild>
644 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 750 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
645 <PrecompiledHeader>Use</PrecompiledHeader> 751 <PrecompiledHeader>Use</PrecompiledHeader>
@@ -677,7 +783,45 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
677 <ClCompile> 783 <ClCompile>
678 <Optimization>Disabled</Optimization> 784 <Optimization>Disabled</Optimization>
679 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 785 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
680 <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 786 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
787 <MinimalRebuild>false</MinimalRebuild>
788 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
789 <PrecompiledHeader>Use</PrecompiledHeader>
790 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
791 <WarningLevel>Level4</WarningLevel>
792 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
793 <LanguageStandard>stdcpp20</LanguageStandard>
794 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
795 </ClCompile>
796 <Link>
797 <AdditionalDependencies>lua54.lib;%(AdditionalDependencies)</AdditionalDependencies>
798 <OutputFile>$(OutDir)$(TargetName).dll</OutputFile>
799 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
800 <GenerateDebugInformation>true</GenerateDebugInformation>
801 <SubSystem>Windows</SubSystem>
802 <RandomizedBaseAddress>false</RandomizedBaseAddress>
803 <DataExecutionPrevention>
804 </DataExecutionPrevention>
805 <TargetMachine>MachineX86</TargetMachine>
806 <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
807 </Link>
808 <PostBuildEvent>
809 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"
810xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"
811</Command>
812 <Message>
813 </Message>
814 </PostBuildEvent>
815 </ItemDefinitionGroup>
816 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">
817 <PreBuildEvent>
818 <Command>
819 </Command>
820 </PreBuildEvent>
821 <ClCompile>
822 <Optimization>Disabled</Optimization>
823 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
824 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
681 <MinimalRebuild>false</MinimalRebuild> 825 <MinimalRebuild>false</MinimalRebuild>
682 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 826 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
683 <PrecompiledHeader>Use</PrecompiledHeader> 827 <PrecompiledHeader>Use</PrecompiledHeader>
@@ -715,7 +859,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
715 <ClCompile> 859 <ClCompile>
716 <Optimization>Disabled</Optimization> 860 <Optimization>Disabled</Optimization>
717 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 861 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
718 <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 862 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
719 <MinimalRebuild>false</MinimalRebuild> 863 <MinimalRebuild>false</MinimalRebuild>
720 <BasicRuntimeChecks> 864 <BasicRuntimeChecks>
721 </BasicRuntimeChecks> 865 </BasicRuntimeChecks>
@@ -754,7 +898,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
754 </PreBuildEvent> 898 </PreBuildEvent>
755 <ClCompile> 899 <ClCompile>
756 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 900 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
757 <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 901 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
758 <MinimalRebuild>false</MinimalRebuild> 902 <MinimalRebuild>false</MinimalRebuild>
759 <PrecompiledHeader>Use</PrecompiledHeader> 903 <PrecompiledHeader>Use</PrecompiledHeader>
760 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 904 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
@@ -797,7 +941,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
797 </PreBuildEvent> 941 </PreBuildEvent>
798 <ClCompile> 942 <ClCompile>
799 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 943 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
800 <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 944 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
801 <PrecompiledHeader>Use</PrecompiledHeader> 945 <PrecompiledHeader>Use</PrecompiledHeader>
802 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 946 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
803 <WarningLevel>Level4</WarningLevel> 947 <WarningLevel>Level4</WarningLevel>
@@ -832,6 +976,49 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
832 </Message> 976 </Message>
833 </PostBuildEvent> 977 </PostBuildEvent>
834 </ItemDefinitionGroup> 978 </ItemDefinitionGroup>
979 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">
980 <PreBuildEvent>
981 <Command>
982 </Command>
983 </PreBuildEvent>
984 <ClCompile>
985 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
986 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
987 <PrecompiledHeader>Use</PrecompiledHeader>
988 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
989 <WarningLevel>Level4</WarningLevel>
990 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
991 <LanguageStandard>stdcpp20</LanguageStandard>
992 <WholeProgramOptimization>true</WholeProgramOptimization>
993 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
994 <OmitFramePointers>true</OmitFramePointers>
995 <BasicRuntimeChecks>
996 </BasicRuntimeChecks>
997 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
998 </ClCompile>
999 <Link>
1000 <AdditionalDependencies>lua54.lib;%(AdditionalDependencies)</AdditionalDependencies>
1001 <OutputFile>$(OutDir)$(TargetName).dll</OutputFile>
1002 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
1003 <GenerateDebugInformation>true</GenerateDebugInformation>
1004 <SubSystem>Windows</SubSystem>
1005 <RandomizedBaseAddress>false</RandomizedBaseAddress>
1006 <DataExecutionPrevention>
1007 </DataExecutionPrevention>
1008 <TargetMachine>MachineX86</TargetMachine>
1009 <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
1010 <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
1011 <OptimizeReferences>true</OptimizeReferences>
1012 <EnableCOMDATFolding>true</EnableCOMDATFolding>
1013 </Link>
1014 <PostBuildEvent>
1015 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"
1016xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"
1017</Command>
1018 <Message>
1019 </Message>
1020 </PostBuildEvent>
1021 </ItemDefinitionGroup>
835 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'"> 1022 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">
836 <PreBuildEvent> 1023 <PreBuildEvent>
837 <Command> 1024 <Command>
@@ -840,7 +1027,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
840 <ClCompile> 1027 <ClCompile>
841 <Optimization>Disabled</Optimization> 1028 <Optimization>Disabled</Optimization>
842 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1029 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
843 <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1030 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
844 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 1031 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
845 <PrecompiledHeader>Use</PrecompiledHeader> 1032 <PrecompiledHeader>Use</PrecompiledHeader>
846 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1033 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
@@ -876,7 +1063,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
876 <ClCompile> 1063 <ClCompile>
877 <Optimization>MaxSpeed</Optimization> 1064 <Optimization>MaxSpeed</Optimization>
878 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1065 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
879 <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1066 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
880 <BasicRuntimeChecks> 1067 <BasicRuntimeChecks>
881 </BasicRuntimeChecks> 1068 </BasicRuntimeChecks>
882 <PrecompiledHeader>Use</PrecompiledHeader> 1069 <PrecompiledHeader>Use</PrecompiledHeader>
@@ -914,7 +1101,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
914 <ClCompile> 1101 <ClCompile>
915 <Optimization>Disabled</Optimization> 1102 <Optimization>Disabled</Optimization>
916 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1103 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
917 <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1104 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
918 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 1105 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
919 <PrecompiledHeader>Use</PrecompiledHeader> 1106 <PrecompiledHeader>Use</PrecompiledHeader>
920 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1107 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
@@ -950,7 +1137,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
950 <ClCompile> 1137 <ClCompile>
951 <Optimization>Disabled</Optimization> 1138 <Optimization>Disabled</Optimization>
952 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1139 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
953 <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1140 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
954 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 1141 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
955 <PrecompiledHeader>Use</PrecompiledHeader> 1142 <PrecompiledHeader>Use</PrecompiledHeader>
956 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1143 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
@@ -978,6 +1165,42 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
978 </Message> 1165 </Message>
979 </PostBuildEvent> 1166 </PostBuildEvent>
980 </ItemDefinitionGroup> 1167 </ItemDefinitionGroup>
1168 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">
1169 <PreBuildEvent>
1170 <Command>
1171 </Command>
1172 </PreBuildEvent>
1173 <ClCompile>
1174 <Optimization>Disabled</Optimization>
1175 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
1176 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1177 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
1178 <PrecompiledHeader>Use</PrecompiledHeader>
1179 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
1180 <WarningLevel>Level4</WarningLevel>
1181 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
1182 <LanguageStandard>stdcpp20</LanguageStandard>
1183 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
1184 <OmitFramePointers>false</OmitFramePointers>
1185 </ClCompile>
1186 <Link>
1187 <AdditionalDependencies>lua55.lib;%(AdditionalDependencies)</AdditionalDependencies>
1188 <OutputFile>$(OutDir)$(TargetName).dll</OutputFile>
1189 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
1190 <GenerateDebugInformation>true</GenerateDebugInformation>
1191 <SubSystem>Windows</SubSystem>
1192 <RandomizedBaseAddress>false</RandomizedBaseAddress>
1193 <DataExecutionPrevention>
1194 </DataExecutionPrevention>
1195 </Link>
1196 <PostBuildEvent>
1197 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"
1198xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"
1199</Command>
1200 <Message>
1201 </Message>
1202 </PostBuildEvent>
1203 </ItemDefinitionGroup>
981 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'"> 1204 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">
982 <PreBuildEvent> 1205 <PreBuildEvent>
983 <Command> 1206 <Command>
@@ -986,7 +1209,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
986 <ClCompile> 1209 <ClCompile>
987 <Optimization>Disabled</Optimization> 1210 <Optimization>Disabled</Optimization>
988 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1211 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
989 <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1212 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
990 <BasicRuntimeChecks> 1213 <BasicRuntimeChecks>
991 </BasicRuntimeChecks> 1214 </BasicRuntimeChecks>
992 <PrecompiledHeader>Use</PrecompiledHeader> 1215 <PrecompiledHeader>Use</PrecompiledHeader>
@@ -1024,7 +1247,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1024 <ClCompile> 1247 <ClCompile>
1025 <Optimization>MaxSpeed</Optimization> 1248 <Optimization>MaxSpeed</Optimization>
1026 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1249 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
1027 <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1250 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1028 <PrecompiledHeader>Use</PrecompiledHeader> 1251 <PrecompiledHeader>Use</PrecompiledHeader>
1029 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1252 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
1030 <WarningLevel>Level4</WarningLevel> 1253 <WarningLevel>Level4</WarningLevel>
@@ -1064,7 +1287,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1064 </PreBuildEvent> 1287 </PreBuildEvent>
1065 <ClCompile> 1288 <ClCompile>
1066 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1289 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
1067 <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1290 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1068 <PrecompiledHeader>Use</PrecompiledHeader> 1291 <PrecompiledHeader>Use</PrecompiledHeader>
1069 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1292 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
1070 <WarningLevel>Level4</WarningLevel> 1293 <WarningLevel>Level4</WarningLevel>
@@ -1097,6 +1320,47 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1097 </Message> 1320 </Message>
1098 </PostBuildEvent> 1321 </PostBuildEvent>
1099 </ItemDefinitionGroup> 1322 </ItemDefinitionGroup>
1323 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">
1324 <PreBuildEvent>
1325 <Command>
1326 </Command>
1327 </PreBuildEvent>
1328 <ClCompile>
1329 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
1330 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1331 <PrecompiledHeader>Use</PrecompiledHeader>
1332 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
1333 <WarningLevel>Level4</WarningLevel>
1334 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
1335 <LanguageStandard>stdcpp20</LanguageStandard>
1336 <WholeProgramOptimization>true</WholeProgramOptimization>
1337 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
1338 <OmitFramePointers>true</OmitFramePointers>
1339 <BasicRuntimeChecks>
1340 </BasicRuntimeChecks>
1341 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
1342 </ClCompile>
1343 <Link>
1344 <AdditionalDependencies>lua55.lib;%(AdditionalDependencies)</AdditionalDependencies>
1345 <OutputFile>$(OutDir)$(TargetName).dll</OutputFile>
1346 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
1347 <GenerateDebugInformation>true</GenerateDebugInformation>
1348 <SubSystem>Windows</SubSystem>
1349 <RandomizedBaseAddress>false</RandomizedBaseAddress>
1350 <DataExecutionPrevention>
1351 </DataExecutionPrevention>
1352 <LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
1353 <OptimizeReferences>true</OptimizeReferences>
1354 <EnableCOMDATFolding>true</EnableCOMDATFolding>
1355 </Link>
1356 <PostBuildEvent>
1357 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"
1358xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"
1359</Command>
1360 <Message>
1361 </Message>
1362 </PostBuildEvent>
1363 </ItemDefinitionGroup>
1100 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'"> 1364 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">
1101 <PreBuildEvent> 1365 <PreBuildEvent>
1102 <Command> 1366 <Command>
@@ -1105,7 +1369,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1105 <ClCompile> 1369 <ClCompile>
1106 <Optimization>Disabled</Optimization> 1370 <Optimization>Disabled</Optimization>
1107 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1371 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
1108 <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1372 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1109 <MinimalRebuild>false</MinimalRebuild> 1373 <MinimalRebuild>false</MinimalRebuild>
1110 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 1374 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
1111 <PrecompiledHeader>Use</PrecompiledHeader> 1375 <PrecompiledHeader>Use</PrecompiledHeader>
@@ -1143,7 +1407,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1143 <ClCompile> 1407 <ClCompile>
1144 <Optimization>Disabled</Optimization> 1408 <Optimization>Disabled</Optimization>
1145 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1409 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
1146 <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1410 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1147 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 1411 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
1148 <PrecompiledHeader>Use</PrecompiledHeader> 1412 <PrecompiledHeader>Use</PrecompiledHeader>
1149 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1413 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
@@ -1178,7 +1442,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1178 </PreBuildEvent> 1442 </PreBuildEvent>
1179 <ClCompile> 1443 <ClCompile>
1180 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1444 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
1181 <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1445 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1182 <PrecompiledHeader>Use</PrecompiledHeader> 1446 <PrecompiledHeader>Use</PrecompiledHeader>
1183 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1447 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
1184 <WarningLevel>Level4</WarningLevel> 1448 <WarningLevel>Level4</WarningLevel>
@@ -1220,7 +1484,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1220 </PreBuildEvent> 1484 </PreBuildEvent>
1221 <ClCompile> 1485 <ClCompile>
1222 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1486 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
1223 <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1487 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1224 <PrecompiledHeader>Use</PrecompiledHeader> 1488 <PrecompiledHeader>Use</PrecompiledHeader>
1225 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1489 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
1226 <WarningLevel>Level4</WarningLevel> 1490 <WarningLevel>Level4</WarningLevel>
@@ -1260,7 +1524,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1260 </PreBuildEvent> 1524 </PreBuildEvent>
1261 <ClCompile> 1525 <ClCompile>
1262 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1526 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
1263 <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1527 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1264 <PrecompiledHeader>Use</PrecompiledHeader> 1528 <PrecompiledHeader>Use</PrecompiledHeader>
1265 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1529 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
1266 <WarningLevel>Level4</WarningLevel> 1530 <WarningLevel>Level4</WarningLevel>
@@ -1302,7 +1566,7 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1302 </PreBuildEvent> 1566 </PreBuildEvent>
1303 <ClCompile> 1567 <ClCompile>
1304 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories> 1568 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include</AdditionalIncludeDirectories>
1305 <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1569 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1306 <PrecompiledHeader>Use</PrecompiledHeader> 1570 <PrecompiledHeader>Use</PrecompiledHeader>
1307 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1571 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
1308 <WarningLevel>Level4</WarningLevel> 1572 <WarningLevel>Level4</WarningLevel>
@@ -1367,6 +1631,14 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1367 <ExtraWarnings>true</ExtraWarnings> 1631 <ExtraWarnings>true</ExtraWarnings>
1368 </ClCompile> 1632 </ClCompile>
1369 </ItemDefinitionGroup> 1633 </ItemDefinitionGroup>
1634 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Prospero'">
1635 <ClCompile>
1636 <CppLanguageStd>Cpp20</CppLanguageStd>
1637 <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\Lua54\include</AdditionalIncludeDirectories>
1638 <PrecompiledHeader>Use</PrecompiledHeader>
1639 <ExtraWarnings>true</ExtraWarnings>
1640 </ClCompile>
1641 </ItemDefinitionGroup>
1370 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'"> 1642 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'">
1371 <ClCompile> 1643 <ClCompile>
1372 <CppLanguageStd>Cpp20</CppLanguageStd> 1644 <CppLanguageStd>Cpp20</CppLanguageStd>
@@ -1413,38 +1685,52 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1413 <ExtraWarnings>true</ExtraWarnings> 1685 <ExtraWarnings>true</ExtraWarnings>
1414 </ClCompile> 1686 </ClCompile>
1415 </ItemDefinitionGroup> 1687 </ItemDefinitionGroup>
1688 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Prospero'">
1689 <ClCompile>
1690 <CppLanguageStd>Cpp20</CppLanguageStd>
1691 <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\Lua54\include</AdditionalIncludeDirectories>
1692 <PrecompiledHeader>Use</PrecompiledHeader>
1693 <ExtraWarnings>true</ExtraWarnings>
1694 </ClCompile>
1695 </ItemDefinitionGroup>
1416 <ItemGroup> 1696 <ItemGroup>
1417 <ClCompile Include="src\allocator.cpp" /> 1697 <ClCompile Include="src\allocator.cpp" />
1418 <ClCompile Include="src\_pch.cpp"> 1698 <ClCompile Include="src\_pch.cpp">
1419 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">Create</PrecompiledHeader> 1699 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">Create</PrecompiledHeader>
1420 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">Create</PrecompiledHeader> 1700 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">Create</PrecompiledHeader>
1421 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">Create</PrecompiledHeader> 1701 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">Create</PrecompiledHeader>
1702 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">Create</PrecompiledHeader>
1422 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">Create</PrecompiledHeader> 1703 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">Create</PrecompiledHeader>
1423 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'">Create</PrecompiledHeader> 1704 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'">Create</PrecompiledHeader>
1424 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Win32'">Create</PrecompiledHeader> 1705 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Win32'">Create</PrecompiledHeader>
1425 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">Create</PrecompiledHeader> 1706 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">Create</PrecompiledHeader>
1426 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">Create</PrecompiledHeader> 1707 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">Create</PrecompiledHeader>
1427 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">Create</PrecompiledHeader> 1708 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">Create</PrecompiledHeader>
1709 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">Create</PrecompiledHeader>
1428 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">Create</PrecompiledHeader> 1710 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">Create</PrecompiledHeader>
1429 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">Create</PrecompiledHeader> 1711 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">Create</PrecompiledHeader>
1430 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">Create</PrecompiledHeader> 1712 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">Create</PrecompiledHeader>
1431 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">Create</PrecompiledHeader> 1713 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">Create</PrecompiledHeader>
1714 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">Create</PrecompiledHeader>
1432 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">Create</PrecompiledHeader> 1715 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">Create</PrecompiledHeader>
1433 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|x64'">Create</PrecompiledHeader> 1716 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|x64'">Create</PrecompiledHeader>
1434 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|x64'">Create</PrecompiledHeader> 1717 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|x64'">Create</PrecompiledHeader>
1435 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">Create</PrecompiledHeader> 1718 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">Create</PrecompiledHeader>
1436 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">Create</PrecompiledHeader> 1719 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">Create</PrecompiledHeader>
1437 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">Create</PrecompiledHeader> 1720 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">Create</PrecompiledHeader>
1721 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">Create</PrecompiledHeader>
1438 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">Create</PrecompiledHeader> 1722 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">Create</PrecompiledHeader>
1439 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'">Create</PrecompiledHeader> 1723 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'">Create</PrecompiledHeader>
1440 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Prospero'">Create</PrecompiledHeader> 1724 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Prospero'">Create</PrecompiledHeader>
1441 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'">Create</PrecompiledHeader> 1725 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'">Create</PrecompiledHeader>
1726 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Prospero'">Create</PrecompiledHeader>
1442 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'">Create</PrecompiledHeader> 1727 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'">Create</PrecompiledHeader>
1443 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Prospero'">Create</PrecompiledHeader> 1728 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Prospero'">Create</PrecompiledHeader>
1444 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Prospero'">Create</PrecompiledHeader> 1729 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Prospero'">Create</PrecompiledHeader>
1445 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Prospero'">Create</PrecompiledHeader> 1730 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Prospero'">Create</PrecompiledHeader>
1446 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Prospero'">Create</PrecompiledHeader> 1731 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Prospero'">Create</PrecompiledHeader>
1447 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'">Create</PrecompiledHeader> 1732 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'">Create</PrecompiledHeader>
1733 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Prospero'">Create</PrecompiledHeader>
1448 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Prospero'">Create</PrecompiledHeader> 1734 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Prospero'">Create</PrecompiledHeader>
1449 </ClCompile> 1735 </ClCompile>
1450 <ClCompile Include="src\cancel.cpp" /> 1736 <ClCompile Include="src\cancel.cpp" />
@@ -1504,12 +1790,16 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1504 </Message> 1790 </Message>
1505 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'"> 1791 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">
1506 </Message> 1792 </Message>
1793 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">
1794 </Message>
1507 <Message Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'"> 1795 <Message Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">
1508 </Message> 1796 </Message>
1509 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'"> 1797 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">
1510 </Message> 1798 </Message>
1511 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'"> 1799 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">
1512 </Message> 1800 </Message>
1801 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">
1802 </Message>
1513 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'"> 1803 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">
1514 </Message> 1804 </Message>
1515 <Message Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'"> 1805 <Message Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">
@@ -1518,12 +1808,16 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1518 </Message> 1808 </Message>
1519 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'"> 1809 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">
1520 </Message> 1810 </Message>
1811 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">
1812 </Message>
1521 <Message Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'"> 1813 <Message Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">
1522 </Message> 1814 </Message>
1523 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'"> 1815 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">
1524 </Message> 1816 </Message>
1525 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'"> 1817 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">
1526 </Message> 1818 </Message>
1819 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">
1820 </Message>
1527 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'"> 1821 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">
1528 </Message> 1822 </Message>
1529 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'"> 1823 <Message Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">
@@ -1532,32 +1826,40 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1532 <Command Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua"</Command> 1826 <Command Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua"</Command>
1533 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command> 1827 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1534 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command> 1828 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1829 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1535 <Command Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua"</Command> 1830 <Command Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua"</Command>
1536 <Command Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command> 1831 <Command Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1537 <Command Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command> 1832 <Command Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1833 <Command Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1538 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command> 1834 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1539 <Command Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua"</Command> 1835 <Command Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua"</Command>
1540 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command> 1836 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1541 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command> 1837 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1838 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1542 <Command Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua"</Command> 1839 <Command Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua"</Command>
1543 <Command Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command> 1840 <Command Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1544 <Command Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command> 1841 <Command Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1842 <Command Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1545 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command> 1843 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1546 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command> 1844 <Command Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">xcopy /F /I /R /Y %(FullPath) "$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)"</Command>
1547 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1845 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1548 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua/%(Filename)%(Extension)</Outputs> 1846 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua/%(Filename)%(Extension)</Outputs>
1549 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1847 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1550 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1848 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1849 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1551 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua/%(Filename)%(Extension)</Outputs> 1850 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua/%(Filename)%(Extension)</Outputs>
1552 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1851 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1553 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1852 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1853 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1554 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1854 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1555 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua/%(Filename)%(Extension)</Outputs> 1855 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua/%(Filename)%(Extension)</Outputs>
1556 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1856 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1557 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1857 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1858 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1558 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua/%(Filename)%(Extension)</Outputs> 1859 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/lua/%(Filename)%(Extension)</Outputs>
1559 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1860 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1560 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1861 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1862 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1561 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1863 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1562 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1864 <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1563 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'"> 1865 <Message Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'">
@@ -1578,14 +1880,20 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1578 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.2|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs> 1880 <Outputs Condition="'$(Configuration)|$(Platform)'=='Release 5.2|x64'">$(SolutionDir)_LuaVersions/$(PlatformName)/$(ConfigurationName)/%(Filename)%(Extension)</Outputs>
1579 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'"> 1881 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">
1580 </BuildInParallel> 1882 </BuildInParallel>
1883 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">
1884 </BuildInParallel>
1581 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'"> 1885 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">
1582 </BuildInParallel> 1886 </BuildInParallel>
1583 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'"> 1887 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">
1584 </MaxProcesses> 1888 </MaxProcesses>
1889 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">
1890 </MaxProcesses>
1585 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'"> 1891 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">
1586 </MaxProcesses> 1892 </MaxProcesses>
1587 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'"> 1893 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">
1588 </MaxItemsInBatch> 1894 </MaxItemsInBatch>
1895 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">
1896 </MaxItemsInBatch>
1589 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'"> 1897 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">
1590 </MaxItemsInBatch> 1898 </MaxItemsInBatch>
1591 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'"> 1899 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">
@@ -1620,14 +1928,20 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1620 </MaxItemsInBatch> 1928 </MaxItemsInBatch>
1621 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'"> 1929 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">
1622 </BuildInParallel> 1930 </BuildInParallel>
1931 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">
1932 </BuildInParallel>
1623 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'"> 1933 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">
1624 </BuildInParallel> 1934 </BuildInParallel>
1625 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'"> 1935 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">
1626 </MaxProcesses> 1936 </MaxProcesses>
1937 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">
1938 </MaxProcesses>
1627 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'"> 1939 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">
1628 </MaxProcesses> 1940 </MaxProcesses>
1629 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'"> 1941 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">
1630 </MaxItemsInBatch> 1942 </MaxItemsInBatch>
1943 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">
1944 </MaxItemsInBatch>
1631 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'"> 1945 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">
1632 </MaxItemsInBatch> 1946 </MaxItemsInBatch>
1633 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'"> 1947 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">
@@ -1674,10 +1988,16 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1674 </MaxItemsInBatch> 1988 </MaxItemsInBatch>
1675 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'"> 1989 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">
1676 </BuildInParallel> 1990 </BuildInParallel>
1991 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">
1992 </BuildInParallel>
1677 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'"> 1993 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">
1678 </MaxProcesses> 1994 </MaxProcesses>
1995 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">
1996 </MaxProcesses>
1679 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'"> 1997 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">
1680 </MaxItemsInBatch> 1998 </MaxItemsInBatch>
1999 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">
2000 </MaxItemsInBatch>
1681 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'"> 2001 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">
1682 </BuildInParallel> 2002 </BuildInParallel>
1683 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'"> 2003 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">
@@ -1692,10 +2012,16 @@ xcopy /F /I /R /Y "$(OutputPath)$(TargetName).pdb" "$(SolutionDir)_LuaVersions/$
1692 </MaxItemsInBatch> 2012 </MaxItemsInBatch>
1693 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'"> 2013 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">
1694 </BuildInParallel> 2014 </BuildInParallel>
2015 <BuildInParallel Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">
2016 </BuildInParallel>
1695 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'"> 2017 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">
1696 </MaxProcesses> 2018 </MaxProcesses>
2019 <MaxProcesses Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">
2020 </MaxProcesses>
1697 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'"> 2021 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">
1698 </MaxItemsInBatch> 2022 </MaxItemsInBatch>
2023 <MaxItemsInBatch Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">
2024 </MaxItemsInBatch>
1699 </CustomBuild> 2025 </CustomBuild>
1700 <None Include="CMakeLists.txt" /> 2026 <None Include="CMakeLists.txt" />
1701 <None Include="docs\comparison.html" /> 2027 <None Include="docs\comparison.html" />
diff --git a/Makefile b/Makefile
index 98fa1ac..ea4f1d3 100644
--- a/Makefile
+++ b/Makefile
@@ -80,7 +80,7 @@ build_DUE:
80run_unit_tests: build_lanes build_unit_tests build_DUE 80run_unit_tests: build_lanes build_unit_tests build_DUE
81 @echo ========================================================================================= 81 @echo =========================================================================================
82 $(_PREFIX) $(_UNITTEST_TARGET) --list-tests 82 $(_PREFIX) $(_UNITTEST_TARGET) --list-tests
83 $(_PREFIX) $(_UNITTEST_TARGET) --rng-seed 0 -s scripted_tests.lane.tasking_cancelling 83 $(_PREFIX) $(_UNITTEST_TARGET) --rng-seed 0
84 84
85debug_unit_tests: build_lanes build_unit_tests build_DUE 85debug_unit_tests: build_lanes build_unit_tests build_DUE
86 @echo ========================================================================================= 86 @echo =========================================================================================
diff --git a/Shared.makefile b/Shared.makefile
index d1a96fb..3809538 100644
--- a/Shared.makefile
+++ b/Shared.makefile
@@ -30,7 +30,7 @@ ifeq "$(LUAROCKS)" ""
30 $(warning LUA_DEV not defined - try i.e. 'make LUA_DEV=/c/Program\ Files/Lua/5.1') 30 $(warning LUA_DEV not defined - try i.e. 'make LUA_DEV=/c/Program\ Files/Lua/5.1')
31 # this assumes Lua was built and installed from source and everything is located in default folders (/usr/local/include and /usr/local/bin) 31 # this assumes Lua was built and installed from source and everything is located in default folders (/usr/local/include and /usr/local/bin)
32 LUA_FLAGS := -I "/usr/local/include" 32 LUA_FLAGS := -I "/usr/local/include"
33 LUA_LIBS := $(word 1,$(shell which lua54.$(_SO) 2>/dev/null) $(shell which lua53.$(_SO) 2>/dev/null) $(shell which lua52.$(_SO) 2>/dev/null) $(shell which lua51$(_SO) 2>/dev/null)) 33 LUA_LIBS := $(word 1,$(shell which lua55.$(_SO) 2>/dev/null) $(shell which lua54.$(_SO) 2>/dev/null) $(shell which lua53.$(_SO) 2>/dev/null) $(shell which lua52.$(_SO) 2>/dev/null) $(shell which lua51$(_SO) 2>/dev/null))
34 $(info detected LUA_LIBS as $(LUA_LIBS)) 34 $(info detected LUA_LIBS as $(LUA_LIBS))
35 else 35 else
36 LUA_FLAGS := -I "$(LUA_DEV)/include" 36 LUA_FLAGS := -I "$(LUA_DEV)/include"
diff --git a/deep_userdata_example/deep_userdata_example.cpp b/deep_userdata_example/deep_userdata_example.cpp
index 075cfbe..6845ff1 100644
--- a/deep_userdata_example/deep_userdata_example.cpp
+++ b/deep_userdata_example/deep_userdata_example.cpp
@@ -25,7 +25,7 @@ class MyDeepFactory final : public DeepFactory
25 25
26// ################################################################################################# 26// #################################################################################################
27 27
28// a lanes-deep userdata. needs DeepPrelude and luaG_newdeepuserdata from Lanes code. 28// a lanes-deep userdata. needs DeepPrelude and luaW_newdeepuserdata from Lanes code.
29struct MyDeepUserdata : public DeepPrelude // Deep userdata MUST start with a DeepPrelude 29struct MyDeepUserdata : public DeepPrelude // Deep userdata MUST start with a DeepPrelude
30{ 30{
31 std::atomic<int> inUse{}; 31 std::atomic<int> inUse{};
@@ -82,7 +82,7 @@ static int deep_tostring(lua_State* const L_)
82{ 82{
83 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, StackIndex{ 1 })) }; 83 MyDeepUserdata* const _self{ static_cast<MyDeepUserdata*>(MyDeepFactory::Instance.toDeep(L_, StackIndex{ 1 })) };
84 _self->inUse.fetch_add(1, std::memory_order_seq_cst); 84 _self->inUse.fetch_add(1, std::memory_order_seq_cst);
85 luaG_pushstring(L_, "%p:deep(%d)", _self, _self->val); 85 luaW_pushstring(L_, "%p:deep(%d)", _self, _self->val);
86 _self->inUse.fetch_sub(1, std::memory_order_seq_cst); 86 _self->inUse.fetch_sub(1, std::memory_order_seq_cst);
87 return 1; 87 return 1;
88} 88}
@@ -241,7 +241,7 @@ static int clonable_getuv(lua_State* const L_)
241static int clonable_tostring(lua_State* const L_) 241static int clonable_tostring(lua_State* const L_)
242{ 242{
243 MyClonableUserdata* _self = static_cast<MyClonableUserdata*>(lua_touserdata(L_, 1)); 243 MyClonableUserdata* _self = static_cast<MyClonableUserdata*>(lua_touserdata(L_, 1));
244 luaG_pushstring(L_, "%p:clonable(%d)", lua_topointer(L_, 1), _self->val); 244 luaW_pushstring(L_, "%p:clonable(%d)", lua_topointer(L_, 1), _self->val);
245 return 1; 245 return 1;
246} 246}
247 247
@@ -299,7 +299,7 @@ int luaD_new_clonable(lua_State* L)
299{ 299{
300 UserValueCount const _nuv{ static_cast<int>(luaL_optinteger(L, 1, 1)) }; 300 UserValueCount const _nuv{ static_cast<int>(luaL_optinteger(L, 1, 1)) };
301 lua_newuserdatauv(L, sizeof(MyClonableUserdata), _nuv); 301 lua_newuserdatauv(L, sizeof(MyClonableUserdata), _nuv);
302 luaG_setmetatable(L, "clonable"); 302 luaW_setmetatable(L, "clonable");
303 return 1; 303 return 1;
304} 304}
305 305
@@ -307,7 +307,7 @@ int luaD_new_clonable(lua_State* L)
307// ################################################################################################# 307// #################################################################################################
308 308
309static luaL_Reg const deep_module[] = { 309static luaL_Reg const deep_module[] = {
310 { "get_deep_count", luaD_get_deep_count }, 310 { "get_deep_count", luaD_get_deep_count },
311 { "new_deep", luaD_new_deep }, 311 { "new_deep", luaD_new_deep },
312 { "new_clonable", luaD_new_clonable }, 312 { "new_clonable", luaD_new_clonable },
313 { nullptr, nullptr } 313 { nullptr, nullptr }
@@ -317,12 +317,12 @@ static luaL_Reg const deep_module[] = {
317 317
318LANES_API int luaopen_deep_userdata_example(lua_State* L) 318LANES_API int luaopen_deep_userdata_example(lua_State* L)
319{ 319{
320 luaG_newlib<std::size(deep_module)>(L, deep_module); // M 320 luaW_newlib<std::size(deep_module)>(L, deep_module); // M
321 321
322 // preregister the metatables for the types we can instantiate so that Lanes can know about them 322 // preregister the metatables for the types we can instantiate so that Lanes can know about them
323 if (luaL_newmetatable(L, "clonable")) // M mt 323 if (luaL_newmetatable(L, "clonable")) // M mt
324 { 324 {
325 luaG_registerlibfuncs(L, clonable_mt); 325 luaW_registerlibfuncs(L, clonable_mt);
326 lua_pushvalue(L, -1); // M mt mt 326 lua_pushvalue(L, -1); // M mt mt
327 lua_setfield(L, -2, "__index"); // M mt 327 lua_setfield(L, -2, "__index"); // M mt
328 } 328 }
@@ -330,7 +330,7 @@ LANES_API int luaopen_deep_userdata_example(lua_State* L)
330 330
331 if (luaL_newmetatable(L, "deep")) // mt 331 if (luaL_newmetatable(L, "deep")) // mt
332 { 332 {
333 luaG_registerlibfuncs(L, deep_mt); 333 luaW_registerlibfuncs(L, deep_mt);
334 lua_pushvalue(L, -1); // mt mt 334 lua_pushvalue(L, -1); // mt mt
335 lua_setfield(L, -2, "__index"); // mt 335 lua_setfield(L, -2, "__index"); // mt
336 } 336 }
diff --git a/deep_userdata_example/deep_userdata_example.vcxproj b/deep_userdata_example/deep_userdata_example.vcxproj
index 54db35a..bea5edd 100644
--- a/deep_userdata_example/deep_userdata_example.vcxproj
+++ b/deep_userdata_example/deep_userdata_example.vcxproj
@@ -45,6 +45,30 @@
45 <Configuration>Debug 5.4</Configuration> 45 <Configuration>Debug 5.4</Configuration>
46 <Platform>x64</Platform> 46 <Platform>x64</Platform>
47 </ProjectConfiguration> 47 </ProjectConfiguration>
48 <ProjectConfiguration Include="Debug 5.5|Prospero">
49 <Configuration>Debug 5.5</Configuration>
50 <Platform>Prospero</Platform>
51 </ProjectConfiguration>
52 <ProjectConfiguration Include="Debug 5.5|Win32">
53 <Configuration>Debug 5.5</Configuration>
54 <Platform>Win32</Platform>
55 </ProjectConfiguration>
56 <ProjectConfiguration Include="Debug 5.5|x64">
57 <Configuration>Debug 5.5</Configuration>
58 <Platform>x64</Platform>
59 </ProjectConfiguration>
60 <ProjectConfiguration Include="Release 5.5|Prospero">
61 <Configuration>Release 5.5</Configuration>
62 <Platform>Prospero</Platform>
63 </ProjectConfiguration>
64 <ProjectConfiguration Include="Release 5.5|Win32">
65 <Configuration>Release 5.5</Configuration>
66 <Platform>Win32</Platform>
67 </ProjectConfiguration>
68 <ProjectConfiguration Include="Release 5.5|x64">
69 <Configuration>Release 5.5</Configuration>
70 <Platform>x64</Platform>
71 </ProjectConfiguration>
48 <ProjectConfiguration Include="Release LuaJIT|Prospero"> 72 <ProjectConfiguration Include="Release LuaJIT|Prospero">
49 <Configuration>Release LuaJIT</Configuration> 73 <Configuration>Release LuaJIT</Configuration>
50 <Platform>Prospero</Platform> 74 <Platform>Prospero</Platform>
@@ -173,6 +197,12 @@
173 <PlatformToolset>v143</PlatformToolset> 197 <PlatformToolset>v143</PlatformToolset>
174 <CharacterSet>MultiByte</CharacterSet> 198 <CharacterSet>MultiByte</CharacterSet>
175 </PropertyGroup> 199 </PropertyGroup>
200 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'" Label="Configuration">
201 <ConfigurationType>DynamicLibrary</ConfigurationType>
202 <UseDebugLibraries>true</UseDebugLibraries>
203 <PlatformToolset>v143</PlatformToolset>
204 <CharacterSet>MultiByte</CharacterSet>
205 </PropertyGroup>
176 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'" Label="Configuration"> 206 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'" Label="Configuration">
177 <ConfigurationType>DynamicLibrary</ConfigurationType> 207 <ConfigurationType>DynamicLibrary</ConfigurationType>
178 <UseDebugLibraries>true</UseDebugLibraries> 208 <UseDebugLibraries>true</UseDebugLibraries>
@@ -193,6 +223,13 @@
193 <WholeProgramOptimization>true</WholeProgramOptimization> 223 <WholeProgramOptimization>true</WholeProgramOptimization>
194 <CharacterSet>MultiByte</CharacterSet> 224 <CharacterSet>MultiByte</CharacterSet>
195 </PropertyGroup> 225 </PropertyGroup>
226 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'" Label="Configuration">
227 <ConfigurationType>DynamicLibrary</ConfigurationType>
228 <UseDebugLibraries>false</UseDebugLibraries>
229 <PlatformToolset>v143</PlatformToolset>
230 <WholeProgramOptimization>true</WholeProgramOptimization>
231 <CharacterSet>MultiByte</CharacterSet>
232 </PropertyGroup>
196 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'" Label="Configuration"> 233 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'" Label="Configuration">
197 <ConfigurationType>DynamicLibrary</ConfigurationType> 234 <ConfigurationType>DynamicLibrary</ConfigurationType>
198 <UseDebugLibraries>true</UseDebugLibraries> 235 <UseDebugLibraries>true</UseDebugLibraries>
@@ -237,6 +274,12 @@
237 <PlatformToolset>v143</PlatformToolset> 274 <PlatformToolset>v143</PlatformToolset>
238 <CharacterSet>MultiByte</CharacterSet> 275 <CharacterSet>MultiByte</CharacterSet>
239 </PropertyGroup> 276 </PropertyGroup>
277 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'" Label="Configuration">
278 <ConfigurationType>DynamicLibrary</ConfigurationType>
279 <UseDebugLibraries>true</UseDebugLibraries>
280 <PlatformToolset>v143</PlatformToolset>
281 <CharacterSet>MultiByte</CharacterSet>
282 </PropertyGroup>
240 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'" Label="Configuration"> 283 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'" Label="Configuration">
241 <ConfigurationType>DynamicLibrary</ConfigurationType> 284 <ConfigurationType>DynamicLibrary</ConfigurationType>
242 <UseDebugLibraries>true</UseDebugLibraries> 285 <UseDebugLibraries>true</UseDebugLibraries>
@@ -257,6 +300,13 @@
257 <WholeProgramOptimization>true</WholeProgramOptimization> 300 <WholeProgramOptimization>true</WholeProgramOptimization>
258 <CharacterSet>MultiByte</CharacterSet> 301 <CharacterSet>MultiByte</CharacterSet>
259 </PropertyGroup> 302 </PropertyGroup>
303 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'" Label="Configuration">
304 <ConfigurationType>DynamicLibrary</ConfigurationType>
305 <UseDebugLibraries>false</UseDebugLibraries>
306 <PlatformToolset>v143</PlatformToolset>
307 <WholeProgramOptimization>true</WholeProgramOptimization>
308 <CharacterSet>MultiByte</CharacterSet>
309 </PropertyGroup>
260 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Prospero'"> 310 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Prospero'">
261 <PlatformToolset>Clang</PlatformToolset> 311 <PlatformToolset>Clang</PlatformToolset>
262 </PropertyGroup> 312 </PropertyGroup>
@@ -266,6 +316,9 @@
266 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'"> 316 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'">
267 <PlatformToolset>Clang</PlatformToolset> 317 <PlatformToolset>Clang</PlatformToolset>
268 </PropertyGroup> 318 </PropertyGroup>
319 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Prospero'" Label="Configuration">
320 <PlatformToolset>Clang</PlatformToolset>
321 </PropertyGroup>
269 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'"> 322 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'">
270 <PlatformToolset>Clang</PlatformToolset> 323 <PlatformToolset>Clang</PlatformToolset>
271 </PropertyGroup> 324 </PropertyGroup>
@@ -284,6 +337,9 @@
284 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'"> 337 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'">
285 <PlatformToolset>Clang</PlatformToolset> 338 <PlatformToolset>Clang</PlatformToolset>
286 </PropertyGroup> 339 </PropertyGroup>
340 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Prospero'" Label="Configuration">
341 <PlatformToolset>Clang</PlatformToolset>
342 </PropertyGroup>
287 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'" Label="Configuration"> 343 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'" Label="Configuration">
288 <PlatformToolset>Clang</PlatformToolset> 344 <PlatformToolset>Clang</PlatformToolset>
289 </PropertyGroup> 345 </PropertyGroup>
@@ -313,6 +369,9 @@
313 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'" Label="PropertySheets"> 369 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'" Label="PropertySheets">
314 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 370 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
315 </ImportGroup> 371 </ImportGroup>
372 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'" Label="PropertySheets">
373 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
374 </ImportGroup>
316 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'" Label="PropertySheets"> 375 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'" Label="PropertySheets">
317 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 376 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
318 </ImportGroup> 377 </ImportGroup>
@@ -322,6 +381,9 @@
322 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'" Label="PropertySheets"> 381 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'" Label="PropertySheets">
323 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 382 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
324 </ImportGroup> 383 </ImportGroup>
384 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'" Label="PropertySheets">
385 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
386 </ImportGroup>
325 <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'"> 387 <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">
326 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 388 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
327 </ImportGroup> 389 </ImportGroup>
@@ -343,6 +405,9 @@
343 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'" Label="PropertySheets"> 405 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'" Label="PropertySheets">
344 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 406 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
345 </ImportGroup> 407 </ImportGroup>
408 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'" Label="PropertySheets">
409 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
410 </ImportGroup>
346 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'" Label="PropertySheets"> 411 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'" Label="PropertySheets">
347 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 412 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
348 </ImportGroup> 413 </ImportGroup>
@@ -352,6 +417,9 @@
352 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'" Label="PropertySheets"> 417 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'" Label="PropertySheets">
353 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 418 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
354 </ImportGroup> 419 </ImportGroup>
420 <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'" Label="PropertySheets">
421 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
422 </ImportGroup>
355 <PropertyGroup Label="UserMacros" /> 423 <PropertyGroup Label="UserMacros" />
356 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'"> 424 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">
357 <TargetExt>.dll</TargetExt> 425 <TargetExt>.dll</TargetExt>
@@ -395,6 +463,12 @@
395 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 463 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
396 <LinkIncremental>false</LinkIncremental> 464 <LinkIncremental>false</LinkIncremental>
397 </PropertyGroup> 465 </PropertyGroup>
466 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">
467 <TargetExt>.dll</TargetExt>
468 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
469 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
470 <LinkIncremental>false</LinkIncremental>
471 </PropertyGroup>
398 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'"> 472 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">
399 <TargetExt>.dll</TargetExt> 473 <TargetExt>.dll</TargetExt>
400 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 474 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
@@ -443,6 +517,12 @@
443 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 517 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
444 <LinkIncremental>false</LinkIncremental> 518 <LinkIncremental>false</LinkIncremental>
445 </PropertyGroup> 519 </PropertyGroup>
520 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">
521 <TargetExt>.dll</TargetExt>
522 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
523 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
524 <LinkIncremental>false</LinkIncremental>
525 </PropertyGroup>
446 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'"> 526 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">
447 <TargetExt>.dll</TargetExt> 527 <TargetExt>.dll</TargetExt>
448 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 528 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
@@ -459,6 +539,11 @@
459 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 539 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
460 <LinkIncremental>false</LinkIncremental> 540 <LinkIncremental>false</LinkIncremental>
461 </PropertyGroup> 541 </PropertyGroup>
542 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">
543 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
544 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
545 <LinkIncremental>false</LinkIncremental>
546 </PropertyGroup>
462 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'"> 547 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">
463 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 548 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
464 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 549 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
@@ -469,6 +554,11 @@
469 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> 554 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
470 <LinkIncremental>false</LinkIncremental> 555 <LinkIncremental>false</LinkIncremental>
471 </PropertyGroup> 556 </PropertyGroup>
557 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">
558 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
559 <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir>
560 <LinkIncremental>false</LinkIncremental>
561 </PropertyGroup>
472 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'"> 562 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">
473 <ClCompile> 563 <ClCompile>
474 <WarningLevel>Level3</WarningLevel> 564 <WarningLevel>Level3</WarningLevel>
@@ -476,7 +566,7 @@
476 <ConformanceMode>true</ConformanceMode> 566 <ConformanceMode>true</ConformanceMode>
477 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 567 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
478 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 568 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
479 <PreprocessorDefinitions>_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 569 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
480 <LanguageStandard>stdcpp20</LanguageStandard> 570 <LanguageStandard>stdcpp20</LanguageStandard>
481 <OmitFramePointers>true</OmitFramePointers> 571 <OmitFramePointers>true</OmitFramePointers>
482 <BasicRuntimeChecks /> 572 <BasicRuntimeChecks />
@@ -501,7 +591,7 @@
501 <ConformanceMode>true</ConformanceMode> 591 <ConformanceMode>true</ConformanceMode>
502 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 592 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
503 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 593 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
504 <PreprocessorDefinitions>_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 594 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
505 <LanguageStandard>stdcpp20</LanguageStandard> 595 <LanguageStandard>stdcpp20</LanguageStandard>
506 <BasicRuntimeChecks /> 596 <BasicRuntimeChecks />
507 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> 597 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -518,6 +608,31 @@
518 </Message> 608 </Message>
519 </PostBuildEvent> 609 </PostBuildEvent>
520 </ItemDefinitionGroup> 610 </ItemDefinitionGroup>
611 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">
612 <ClCompile>
613 <WarningLevel>Level3</WarningLevel>
614 <SDLCheck>true</SDLCheck>
615 <ConformanceMode>true</ConformanceMode>
616 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
617 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
618 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
619 <LanguageStandard>stdcpp20</LanguageStandard>
620 <BasicRuntimeChecks>
621 </BasicRuntimeChecks>
622 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
623 </ClCompile>
624 <Link>
625 <EnableCOMDATFolding>true</EnableCOMDATFolding>
626 <OptimizeReferences>true</OptimizeReferences>
627 <AdditionalDependencies>lua55.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
628 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
629 </Link>
630 <PostBuildEvent>
631 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command>
632 <Message>
633 </Message>
634 </PostBuildEvent>
635 </ItemDefinitionGroup>
521 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'"> 636 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">
522 <ClCompile> 637 <ClCompile>
523 <WarningLevel>Level3</WarningLevel> 638 <WarningLevel>Level3</WarningLevel>
@@ -528,6 +643,7 @@
528 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 643 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
529 <LanguageStandard>stdcpp20</LanguageStandard> 644 <LanguageStandard>stdcpp20</LanguageStandard>
530 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 645 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
646 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
531 </ClCompile> 647 </ClCompile>
532 <PostBuildEvent> 648 <PostBuildEvent>
533 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command> 649 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command>
@@ -550,6 +666,7 @@
550 <LanguageStandard>stdcpp20</LanguageStandard> 666 <LanguageStandard>stdcpp20</LanguageStandard>
551 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 667 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
552 <OmitFramePointers>false</OmitFramePointers> 668 <OmitFramePointers>false</OmitFramePointers>
669 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
553 </ClCompile> 670 </ClCompile>
554 <PostBuildEvent> 671 <PostBuildEvent>
555 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command> 672 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command>
@@ -574,6 +691,7 @@
574 <Optimization>MaxSpeed</Optimization> 691 <Optimization>MaxSpeed</Optimization>
575 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> 692 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
576 <BasicRuntimeChecks /> 693 <BasicRuntimeChecks />
694 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
577 </ClCompile> 695 </ClCompile>
578 <PostBuildEvent> 696 <PostBuildEvent>
579 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command> 697 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command>
@@ -597,6 +715,7 @@
597 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 715 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
598 <LanguageStandard>stdcpp20</LanguageStandard> 716 <LanguageStandard>stdcpp20</LanguageStandard>
599 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 717 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
718 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
600 </ClCompile> 719 </ClCompile>
601 <PostBuildEvent> 720 <PostBuildEvent>
602 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command> 721 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command>
@@ -621,6 +740,7 @@
621 <OmitFramePointers>true</OmitFramePointers> 740 <OmitFramePointers>true</OmitFramePointers>
622 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> 741 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
623 <BasicRuntimeChecks /> 742 <BasicRuntimeChecks />
743 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
624 </ClCompile> 744 </ClCompile>
625 <PostBuildEvent> 745 <PostBuildEvent>
626 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command> 746 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command>
@@ -642,7 +762,7 @@
642 <ConformanceMode>true</ConformanceMode> 762 <ConformanceMode>true</ConformanceMode>
643 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 763 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
644 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 764 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
645 <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 765 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
646 <LanguageStandard>stdcpp20</LanguageStandard> 766 <LanguageStandard>stdcpp20</LanguageStandard>
647 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 767 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
648 <BasicRuntimeChecks /> 768 <BasicRuntimeChecks />
@@ -670,6 +790,29 @@
670 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 790 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
671 <LanguageStandard>stdcpp20</LanguageStandard> 791 <LanguageStandard>stdcpp20</LanguageStandard>
672 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 792 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
793 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
794 </ClCompile>
795 <PostBuildEvent>
796 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command>
797 <Message>
798 </Message>
799 </PostBuildEvent>
800 <Link>
801 <AdditionalDependencies>lua54.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
802 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
803 </Link>
804 </ItemDefinitionGroup>
805 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">
806 <ClCompile>
807 <WarningLevel>Level3</WarningLevel>
808 <Optimization>Disabled</Optimization>
809 <SDLCheck>true</SDLCheck>
810 <ConformanceMode>true</ConformanceMode>
811 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
812 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
813 <LanguageStandard>stdcpp20</LanguageStandard>
814 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
815 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
673 </ClCompile> 816 </ClCompile>
674 <PostBuildEvent> 817 <PostBuildEvent>
675 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command> 818 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command>
@@ -693,7 +836,7 @@
693 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 836 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
694 <BasicRuntimeChecks /> 837 <BasicRuntimeChecks />
695 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> 838 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
696 <PreprocessorDefinitions>_WINDLL;NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 839 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
697 </ClCompile> 840 </ClCompile>
698 <PostBuildEvent> 841 <PostBuildEvent>
699 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command> 842 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command>
@@ -714,7 +857,7 @@
714 <ConformanceMode>true</ConformanceMode> 857 <ConformanceMode>true</ConformanceMode>
715 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 858 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
716 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 859 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
717 <PreprocessorDefinitions>_WINDLL;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 860 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
718 <LanguageStandard>stdcpp20</LanguageStandard> 861 <LanguageStandard>stdcpp20</LanguageStandard>
719 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 862 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
720 <OmitFramePointers>false</OmitFramePointers> 863 <OmitFramePointers>false</OmitFramePointers>
@@ -736,7 +879,7 @@
736 <ConformanceMode>true</ConformanceMode> 879 <ConformanceMode>true</ConformanceMode>
737 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 880 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
738 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 881 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
739 <PreprocessorDefinitions>_WINDLL;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 882 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
740 <LanguageStandard>stdcpp20</LanguageStandard> 883 <LanguageStandard>stdcpp20</LanguageStandard>
741 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 884 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
742 <OmitFramePointers>false</OmitFramePointers> 885 <OmitFramePointers>false</OmitFramePointers>
@@ -758,7 +901,7 @@
758 <ConformanceMode>true</ConformanceMode> 901 <ConformanceMode>true</ConformanceMode>
759 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 902 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
760 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 903 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
761 <PreprocessorDefinitions>_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 904 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
762 <LanguageStandard>stdcpp20</LanguageStandard> 905 <LanguageStandard>stdcpp20</LanguageStandard>
763 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 906 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
764 <OmitFramePointers>true</OmitFramePointers> 907 <OmitFramePointers>true</OmitFramePointers>
@@ -785,7 +928,7 @@
785 <ConformanceMode>true</ConformanceMode> 928 <ConformanceMode>true</ConformanceMode>
786 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 929 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
787 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 930 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
788 <PreprocessorDefinitions>_WINDLL;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 931 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
789 <LanguageStandard>stdcpp20</LanguageStandard> 932 <LanguageStandard>stdcpp20</LanguageStandard>
790 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 933 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
791 <OmitFramePointers>false</OmitFramePointers> 934 <OmitFramePointers>false</OmitFramePointers>
@@ -807,7 +950,7 @@
807 <ConformanceMode>true</ConformanceMode> 950 <ConformanceMode>true</ConformanceMode>
808 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 951 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
809 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 952 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
810 <PreprocessorDefinitions>_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 953 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
811 <LanguageStandard>stdcpp20</LanguageStandard> 954 <LanguageStandard>stdcpp20</LanguageStandard>
812 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 955 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
813 <OmitFramePointers>true</OmitFramePointers> 956 <OmitFramePointers>true</OmitFramePointers>
@@ -834,7 +977,7 @@
834 <ConformanceMode>true</ConformanceMode> 977 <ConformanceMode>true</ConformanceMode>
835 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 978 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
836 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 979 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
837 <PreprocessorDefinitions>_WINDLL;NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 980 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
838 <LanguageStandard>stdcpp20</LanguageStandard> 981 <LanguageStandard>stdcpp20</LanguageStandard>
839 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 982 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
840 <OmitFramePointers>false</OmitFramePointers> 983 <OmitFramePointers>false</OmitFramePointers>
@@ -860,7 +1003,7 @@
860 <ConformanceMode>true</ConformanceMode> 1003 <ConformanceMode>true</ConformanceMode>
861 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 1004 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
862 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1005 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
863 <PreprocessorDefinitions>_WINDLL;_DEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1006 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
864 <LanguageStandard>stdcpp20</LanguageStandard> 1007 <LanguageStandard>stdcpp20</LanguageStandard>
865 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 1008 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
866 <OmitFramePointers>false</OmitFramePointers> 1009 <OmitFramePointers>false</OmitFramePointers>
@@ -875,6 +1018,28 @@
875 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories> 1018 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
876 </Link> 1019 </Link>
877 </ItemDefinitionGroup> 1020 </ItemDefinitionGroup>
1021 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">
1022 <ClCompile>
1023 <WarningLevel>Level3</WarningLevel>
1024 <SDLCheck>true</SDLCheck>
1025 <ConformanceMode>true</ConformanceMode>
1026 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
1027 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
1028 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1029 <LanguageStandard>stdcpp20</LanguageStandard>
1030 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
1031 <OmitFramePointers>false</OmitFramePointers>
1032 </ClCompile>
1033 <PostBuildEvent>
1034 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command>
1035 <Message>
1036 </Message>
1037 </PostBuildEvent>
1038 <Link>
1039 <AdditionalDependencies>lua55.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
1040 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
1041 </Link>
1042 </ItemDefinitionGroup>
878 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'"> 1043 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'">
879 <ClCompile> 1044 <ClCompile>
880 <WarningLevel>Level3</WarningLevel> 1045 <WarningLevel>Level3</WarningLevel>
@@ -882,7 +1047,7 @@
882 <ConformanceMode>true</ConformanceMode> 1047 <ConformanceMode>true</ConformanceMode>
883 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 1048 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
884 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> 1049 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
885 <PreprocessorDefinitions>_WINDLL;NDEBUG;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> 1050 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
886 <LanguageStandard>stdcpp20</LanguageStandard> 1051 <LanguageStandard>stdcpp20</LanguageStandard>
887 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 1052 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
888 <OmitFramePointers>false</OmitFramePointers> 1053 <OmitFramePointers>false</OmitFramePointers>
@@ -912,6 +1077,7 @@
912 <OmitFramePointers>true</OmitFramePointers> 1077 <OmitFramePointers>true</OmitFramePointers>
913 <BasicRuntimeChecks /> 1078 <BasicRuntimeChecks />
914 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> 1079 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
1080 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
915 </ClCompile> 1081 </ClCompile>
916 <Link> 1082 <Link>
917 <EnableCOMDATFolding>true</EnableCOMDATFolding> 1083 <EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -938,6 +1104,7 @@
938 <LanguageStandard>stdcpp20</LanguageStandard> 1104 <LanguageStandard>stdcpp20</LanguageStandard>
939 <BasicRuntimeChecks /> 1105 <BasicRuntimeChecks />
940 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> 1106 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
1107 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
941 </ClCompile> 1108 </ClCompile>
942 <Link> 1109 <Link>
943 <EnableCOMDATFolding>true</EnableCOMDATFolding> 1110 <EnableCOMDATFolding>true</EnableCOMDATFolding>
@@ -954,6 +1121,36 @@
954 </Message> 1121 </Message>
955 </PostBuildEvent> 1122 </PostBuildEvent>
956 </ItemDefinitionGroup> 1123 </ItemDefinitionGroup>
1124 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">
1125 <ClCompile>
1126 <WarningLevel>Level3</WarningLevel>
1127 <Optimization>MaxSpeed</Optimization>
1128 <SDLCheck>true</SDLCheck>
1129 <ConformanceMode>true</ConformanceMode>
1130 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
1131 <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
1132 <LanguageStandard>stdcpp20</LanguageStandard>
1133 <BasicRuntimeChecks>
1134 </BasicRuntimeChecks>
1135 <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
1136 <PreprocessorDefinitions>LANES_DEBUG;_WINDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1137 </ClCompile>
1138 <Link>
1139 <EnableCOMDATFolding>true</EnableCOMDATFolding>
1140 <OptimizeReferences>true</OptimizeReferences>
1141 <AdditionalDependencies>lua54.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
1142 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
1143 <ImageHasSafeExceptionHandlers>
1144 </ImageHasSafeExceptionHandlers>
1145 </Link>
1146 <PostBuildEvent>
1147 <Command>xcopy /F /I /R /Y "$(TargetPath)" "$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)"</Command>
1148 </PostBuildEvent>
1149 <PostBuildEvent>
1150 <Message>
1151 </Message>
1152 </PostBuildEvent>
1153 </ItemDefinitionGroup>
957 <ItemGroup> 1154 <ItemGroup>
958 <ClCompile Include="..\src\compat.cpp" /> 1155 <ClCompile Include="..\src\compat.cpp" />
959 <ClCompile Include="..\src\deep.cpp" /> 1156 <ClCompile Include="..\src\deep.cpp" />
diff --git a/deep_userdata_example/deeptest.lua b/deep_userdata_example/deeptest.lua
index 37136cd..7e6ffd3 100644
--- a/deep_userdata_example/deeptest.lua
+++ b/deep_userdata_example/deeptest.lua
@@ -1,5 +1,5 @@
1local lanes = require("lanes").configure{ with_timers = false} 1local lanes = require("lanes").configure{ with_timers = false}
2local l = lanes.linda "my linda" 2local l = lanes.linda{name = "my linda"}
3 3
4local table_unpack = table.unpack or unpack -- Lua 5.1 support 4local table_unpack = table.unpack or unpack -- Lua 5.1 support
5 5
diff --git a/docs/index.html b/docs/index.html
index 116fc0a..2e74495 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -38,6 +38,7 @@
38 <a href="#description">Description</a> &middot; 38 <a href="#description">Description</a> &middot;
39 <a href="#systems">Supported systems</a> &middot; 39 <a href="#systems">Supported systems</a> &middot;
40 <a href="#installing">Building and Installing</a> &middot; 40 <a href="#installing">Building and Installing</a> &middot;
41 <a href="#apicheatsheet">API Cheat sheet</a>
41 <a href="#embedding">Embedding</a> 42 <a href="#embedding">Embedding</a>
42 </p> 43 </p>
43 44
@@ -66,11 +67,11 @@
66 <br /> 67 <br />
67 <i>Copyright &copy; 2007-25 Asko Kauppi, Benoit Germain. All rights reserved.</i> 68 <i>Copyright &copy; 2007-25 Asko Kauppi, Benoit Germain. All rights reserved.</i>
68 <br /> 69 <br />
69 Lua Lanes is published under the same <a href="http://en.wikipedia.org/wiki/MIT_License">MIT license</a> as Lua 5.1, 5.2, 5.3 and 5.4. 70 Lua Lanes is published under the same <a href="http://en.wikipedia.org/wiki/MIT_License">MIT license</a> as Lua 5.1, 5.2, 5.3, 5.4 and 5.5.
70 </p> 71 </p>
71 72
72 <p> 73 <p>
73 This document was revised on 18-Apr-25, and applies to version <tt>4.0.0</tt>. 74 This document was revised on 03-Jul-25, and applies to version <tt>4.0.0</tt>.
74 </p> 75 </p>
75 </font> 76 </font>
76 </center> 77 </center>
@@ -88,7 +89,7 @@
88 Lanes is included into your software by the regular <tt>require "lanes"</tt> method. No C side programming is needed; all APIs are Lua side, and most existing extension modules should work seamlessly together with the multiple lanes. 89 Lanes is included into your software by the regular <tt>require "lanes"</tt> method. No C side programming is needed; all APIs are Lua side, and most existing extension modules should work seamlessly together with the multiple lanes.
89</p> 90</p>
90<p> 91<p>
91 Lanes should build and run identically with either Lua 5.1 to Lua 5.4, as well as LuaJIT. 92 Lanes should build and run identically with either Lua 5.1 to Lua 5.5, as well as LuaJIT.
92</p> 93</p>
93<p> 94<p>
94 See <A HREF="comparison.html">comparison</A> of Lua Lanes with other Lua multithreading solutions. 95 See <A HREF="comparison.html">comparison</A> of Lua Lanes with other Lua multithreading solutions.
@@ -105,7 +106,7 @@
105 <li>Threads can be given priorities.</li> 106 <li>Threads can be given priorities.</li>
106 <li>Lanes are cancellable, with proper cleanup.</li> 107 <li>Lanes are cancellable, with proper cleanup.</li>
107 <li>No Lua-side application level locking - ever!</li> 108 <li>No Lua-side application level locking - ever!</li>
108 <li>Several totally independant Lanes universes may coexist in an application, one per "master" Lua state.</li> 109 <li>Several totally independent Lanes universes may coexist in an application, one per "master" Lua state.</li>
109 </ul> 110 </ul>
110 111
111 112
@@ -116,7 +117,7 @@
116 <li>Sharing full userdata between states needs special C side preparations (-&gt; <A HREF="#deep_userdata">deep userdata</A> and -&gt; <A HREF="#clonable_userdata">clonable userdata</A>).</li> 117 <li>Sharing full userdata between states needs special C side preparations (-&gt; <A HREF="#deep_userdata">deep userdata</A> and -&gt; <A HREF="#clonable_userdata">clonable userdata</A>).</li>
117 <li>Network level parallelism not included.</li> 118 <li>Network level parallelism not included.</li>
118 <li>Multi-CPU is done with OS threads, not processes. A lane is a Lua full userdata, therefore it will exist only as long as the Lua state that created it still exists. Therefore, a lane won't continue execution after the main program's termination.</li> 119 <li>Multi-CPU is done with OS threads, not processes. A lane is a Lua full userdata, therefore it will exist only as long as the Lua state that created it still exists. Therefore, a lane won't continue execution after the main program's termination.</li>
119 <li>Just like independant Lua states, Lanes universes cannot communicate together.</li> 120 <li>Just like independent Lua states, Lanes universes cannot communicate together.</li>
120 </ul> 121 </ul>
121</p> 122</p>
122 123
@@ -169,6 +170,84 @@
169</pre> 170</pre>
170 171
171 172
173<!-- API reference +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
174 <hr/>
175 <h2 id="apicheatsheet">API Cheat sheet</h2>
176 <ul>
177 <li>
178 <tt>require "lanes"</tt>: to require Lanes
179 </li>
180 <li>
181 The <tt>lanes</tt> module
182 <ul>
183 <li><tt>lanes.cancel_error</tt>: a special error value returned from cancelled lanes</li>
184 <li><tt>lanes.collectgarbage()</tt>: trigger a GC cycle in all Keeper states</li>
185 <li><tt>lanes.configure()</tt>: configure Lanes</li>
186 <li><tt>lanes.coro()</tt>: start a coroutine-like lane</li>
187 <li><tt>lanes.finally()</tt>: install a function called on Lanes shutdown</li>
188 <li><tt>lanes.gen()</tt>: start a lane as a regular function</li>
189 <li><tt>lanes.genactomic()</tt>: obtain an atomic counter</li>
190 <li><tt>lanes.genlock()</tt>: obtain an atomic-like data stack</li>
191 <li><tt>lanes.linda()</tt>: create a Linda</li>
192 <li><tt>lanes.nameof()</tt>: find where a value exists</li>
193 <li><tt>lanes.thread_priority_range()</tt>: obtain the valid range of thread priorities</li>
194 <li><tt>lanes.now_secs()</tt>: obtain the current clock value</li>
195 <li><tt>lanes.register()</tt>: scan modules so that functions using them can be transferred</li>
196 <li><tt>lanes.set_thread_priority()</tt>: change thread priority</li>
197 <li><tt>lanes.set_thread_affinity()</tt>: change thread affinity</li>
198 <li><tt>lanes.threads()</tt>: obtain a list of all lanes</li>
199 <li><tt>lanes.sleep()</tt>: sleep for a given duration</li>
200 <li><tt>lanes.timer()</tt>: start a timer</li>
201 <li><tt>lanes.timers()</tt>: list active timers</li>
202 </ul>
203 </li>
204 <li>
205 Given some lane handle <tt>lane_h</tt>
206 <ul>
207 <li><tt>lane_h[]</tt>: wait for, and read the values returned by the lane</li>
208 <li><tt>lane_h:cancel()</tt>: request the lane to stop running</li>
209 <li><tt>lane_h.error_trace_level</tt>: current setting of error logging level</li>
210 <li><tt>lane_h:get_threadname()</tt>: read the thread name</li>
211 <li><tt>lane_h:join()</tt>: wait for the lane to close, reading the returned values</li>
212 <li><tt>lane_h:resume()</tt>: resume a coroutine Lane</li>
213 <li><tt>lane_h.status</tt>: current status of the lane</li>
214 </ul>
215 </li>
216 <li>
217 Inside the lane
218 <ul>
219 <li><tt>cancel_test()</tt>: check for cancellation requests</li>
220 <li><tt>lane_threadname()</tt>: read or change the name of the thread</li>
221 <li><tt>set_finalizer()</tt>: install a function called when the lane exits</li>
222 </ul>
223 </li>
224 <li>
225 Given some Linda <tt>l</tt>
226 <ul>
227 <li><tt>l:cancel()</tt>: mark a Linda for cancellation</li>
228 <li><tt>l:collectgarbage()</tt>: trigger a GC cycle in the Linda's Keeper state</li>
229 <li><tt>l:deep()</tt>: obtain a light userdata uniquely representing the Linda</li>
230 <li><tt>l:dump()</tt>: have information about slot contents</li>
231 <li><tt>l:count()</tt>: obtain a count of data items in slots</li>
232 <li><tt>l:get()</tt>: read data without consuming it</li>
233 <li><tt>l:limit()</tt>: cap the amount of transiting data</li>
234 <li><tt>l:receive()</tt>: read one item of data from multiple slots</li>
235 <li><tt>l:receive_batched()</tt>: read several item of data from a single slot</li>
236 <li><tt>l:restrict()</tt>: place a restraint on the operations that can be done on a slot</li>
237 <li><tt>l:send()</tt>: append data</li>
238 <li><tt>l:set()</tt>: replace the data</li>
239 <li><tt>l:wake()</tt>: manually wake blocking calls</li>
240 </ul>
241 </li>
242 <li>
243 embedding
244 <ul>
245 <li><tt>luaopen_lanes_embedded</tt>: manually initialize Lanes</li>
246 </ul>
247 </li>
248 </ul>
249
250
172<!-- embedding +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> 251<!-- embedding +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -->
173<hr/> 252<hr/>
174<h2 id="embedding">Embedding</h2> 253<h2 id="embedding">Embedding</h2>
@@ -785,12 +864,13 @@
785 </tr> 864 </tr>
786 <tr valign=top> 865 <tr valign=top>
787 <td> 866 <td>
788 <code>.priority</code> 867 <code>.priority</code><br />
868 <code>.native_priority</code>
789 </td> 869 </td>
790 <td>integer</td> 870 <td>integer</td>
791 <td> 871 <td>
792 The priority of lanes generated in the range -3..+3 (default is 0). 872 <tt>priority</tt>: The priority of lanes in the range <tt>[-3,+3]</tt> (default is 0). These values are a mapping over the actual priority range of the underlying implementation.<br />
793 These values are a mapping over the actual priority range of the underlying implementation.<br /> 873 <tt>native_priority</tt>: The priority of lanes in a platform-dependent range. Use <a href="#priority"><tt>lanes.thread_priority_range()</tt></a> to query said range.
794 Implementation and dependability of priorities varies by platform. Especially Linux kernel 2.6 is not supporting priorities in user mode.<br /> 874 Implementation and dependability of priorities varies by platform. Especially Linux kernel 2.6 is not supporting priorities in user mode.<br />
795 A lane can also change its own thread priority dynamically with <a href="#priority"><tt>lanes.set_thread_priority()</tt></a>. 875 A lane can also change its own thread priority dynamically with <a href="#priority"><tt>lanes.set_thread_priority()</tt></a>.
796 </td> 876 </td>
@@ -813,7 +893,7 @@
813 The name is stored inside the Lua state registry so that it is available for error reporting. Changing <tt>decoda_name</tt> doesn't affect this hidden name or the OS thread name reported by MSVC.<br /> 893 The name is stored inside the Lua state registry so that it is available for error reporting. Changing <tt>decoda_name</tt> doesn't affect this hidden name or the OS thread name reported by MSVC.<br />
814 When Lanes is initialized by the first <a href="#initialization"><tt>lanes.configure()</tt></a> call, <tt>"main"</tt> is stored in the registry in the same fashion (but <tt>decoda_name</tt> and the OS thread name are left unchanged).<br /> 894 When Lanes is initialized by the first <a href="#initialization"><tt>lanes.configure()</tt></a> call, <tt>"main"</tt> is stored in the registry in the same fashion (but <tt>decoda_name</tt> and the OS thread name are left unchanged).<br />
815 The lane also has a method <tt>lane:get_threadname()</tt> that gives access to that name from the caller side (returns <tt>"&lt;unnamed&gt;"</tt> if unset).<br /> 895 The lane also has a method <tt>lane:get_threadname()</tt> that gives access to that name from the caller side (returns <tt>"&lt;unnamed&gt;"</tt> if unset).<br />
816 With Lua 5.4, Lanes have a <tt>__close</tt> metamethod, meaning they can be declared to-be-closed. <tt>__close</tt> calls <tt>lane:join(nil)</tt>. 896 With Lua 5.4+, Lanes have a <tt>__close</tt> metamethod, meaning they can be declared to-be-closed. <tt>__close</tt> calls <tt>lane:join(nil)</tt>.
817</p> 897</p>
818 898
819<p> 899<p>
@@ -842,8 +922,9 @@
842 </tr> 922 </tr>
843 </table> 923 </table>
844 924
845 Coroutine lanes function mostly like regular coroutines. They can use <tt>coroutine.yield()</tt> normally, in which case the yielded values can be obtained with regular lane indexing (see <a href="#results">Results and errors</a>).<br /> 925 Coroutine lanes function mostly like regular coroutines. They can use <tt>coroutine.yield()</tt> normally.<br />
846 A yielded coroutine lane has a <tt>"suspended"</tt> status. It can be resumed with <tt>lane_h:resume(values...)</tt>. 926 A yielded coroutine lane has a <tt>"suspended"</tt> status. It can be resumed with <tt>lane_h:resume(values...), which returns the yielded values</tt>.
927 The latter can also be the returned values of <tt>lane_h:join()</tt> or accessed by regular lane indexing (see <a href="#results">Results and errors</a>).<br />
847 <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"> 928 <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%">
848 <tr> 929 <tr>
849 <td> 930 <td>
@@ -852,8 +933,8 @@
852 </tr> 933 </tr>
853 </table> 934 </table>
854 935
855 The reply values are returned to the lane body at the <tt>coroutine.yield()</tt> point.<br /> 936 Just like regulare coroutines, the reply values passed to <tt>h:resume()</tt> are returned to the lane body at the <tt>coroutine.yield()</tt> point.<br />
856 If the yielded values were previously obtained by lane indexing, <tt>resume()</tt> returns <tt>nil</tt>. 937 If a coroutine lane is suspended when it is joined either by indexing or <tt>lane_h:join()</tt>, active to-be-closed variables are closed at that point, and the Lane can no longer be resumed.
857</p> 938</p>
858<h3>Free running lanes</h3> 939<h3>Free running lanes</h3>
859 940
@@ -879,14 +960,17 @@
879 <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> 960 <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%">
880 <tr> 961 <tr>
881 <td> 962 <td>
882 <pre> lanes.set_thread_priority(prio)</pre> 963 <pre> prio_min, prio_max = lanes.thread_priority_range(prio [,"native"])</pre>
964 <pre> lanes.set_thread_priority(prio [,"native"])</pre>
883 </td> 965 </td>
884 </tr> 966 </tr>
885 </table> 967 </table>
886<p> 968<p>
887 Besides setting a default priority in the generator <a href="#generator_settings">settings</a>, each thread can change its own priority at will. This is also true for the main Lua state. 969 Besides setting a default priority in the generator <a href="#generator_settings">settings</a>, each thread can change its own priority at will. This is also true for the main Lua state.
888 <br /> 970 <br />
889 The priority must be in the range <tt>[-3,+3]</tt>. 971 <tt>lanes.thread_priority_range()</tt> returns the range of acceptable mapped values. If nothing is specified, should be <tt>[-3,3]</tt> or <tt>[0,3]</tt>, depending on the threading implementation.
972 <br />
973 <tt>lanes.thread_priority_range('native')</tt> returns the range of acceptable native values. The actual values are threading implementation dependent. And some implementations can only accept some values inside that range. YMMV.
890</p> 974</p>
891 975
892 976
@@ -1073,7 +1157,7 @@
1073</p> 1157</p>
1074 1158
1075<table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> 1159<table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre>
1076 [...]|[nil,err,stack_tbl]= lane_h:join([timeout]) 1160 [true, ...]|[nil,err,stack_tbl]= lane_h:join([timeout])
1077</pre></td></tr></table> 1161</pre></td></tr></table>
1078 1162
1079<p> 1163<p>
@@ -1091,9 +1175,9 @@
1091 </ul> 1175 </ul>
1092 </li> 1176 </li>
1093 <li><tt>nil, "killed"</tt> if forcefully killed.</li> 1177 <li><tt>nil, "killed"</tt> if forcefully killed.</li>
1094 <li>The return values of the lane function. If the first return value is <tt>nil</tt> (or there is no return value), an error is raised, to make sure you can tell timeout and error cases apart from successful return.</li> 1178 <li><tt>true [, returned-values]</tt>: The return values of the lane function.</li>
1095 </ul> 1179 </ul>
1096 If the lane handle obtained from <tt>lanes.gen()</tt> is to-be-closed, closing the value will cause a call to <tt>join()</tt>. Since it is implicit, the lane body isn't forced to return non-<tt>nil</tt> in that case. 1180 If the lane handle obtained from <tt>lanes.gen()</tt> is to-be-closed, closing the value will cause a call to <tt>join()</tt>.
1097</p> 1181</p>
1098 1182
1099<table border=1 bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> 1183<table border=1 bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre>
@@ -1137,38 +1221,49 @@
1137</pre></td></tr></table> 1221</pre></td></tr></table>
1138 1222
1139<p> 1223<p>
1140 <tt>timeout</tt> is an optional number &gt= 0. Defaults to infinite if left unspecified or <tt>nil</tt>.
1141 <br />
1142 <tt>cancel()</tt> sends a cancellation request to the lane. 1224 <tt>cancel()</tt> sends a cancellation request to the lane.
1143 <br /> 1225 <p>
1144 First argument is a <tt>mode</tt> can be one of: 1226 Returns <tt>true, lane_h.status</tt> if lane was already done (in <tt>"done"</tt>, <tt>"error"</tt> or <tt>"cancelled"</tt> status), or the cancellation was fruitful within <tt>timeout_secs</tt> timeout period.<br />
1227 Returns <tt>false, "timeout"</tt> otherwise.
1228 </p>
1229 First argument is a <tt>mode</tt>. It can be one of:
1145 <ul> 1230 <ul>
1146 <li> 1231 <li>
1147 <tt>"soft"</tt>: Cancellation will only cause <tt>cancel_test()</tt> to return <tt>true</tt>, so that the lane can cleanup manually. 1232 <tt>"soft"</tt>: Cancellation will only cause <tt>cancel_test()</tt> to return <tt>"soft"</tt>, so that the lane can cleanup manually.
1233 <br />
1234 Lindas will also check for cancellation inside blocking calls to early out based on their <tt>wake_period</tt>.
1148 </li> 1235 </li>
1149 <li> 1236 <li>
1150 <tt>"hard"</tt>: waits for the request to be processed, or a timeout to occur. <a href="#lindas">linda</a> operations detecting the cancellation request will raise a special cancellation error (meaning they won't return in that case).<br /> 1237 <tt>"hard"</tt>: waits for the request to be processed, or a timeout to occur. <a href="#lindas">linda</a> operations detecting the cancellation request will raise a special cancellation error (meaning they won't return in that case).
1238 <br />
1239 If the lane isn't actually waiting on a Linda when the request is issued, a lane calling <tt>cancel_test()</tt> will see it return <tt>"hard"</tt>.
1240 <br />
1151 <tt>wake_lane</tt> defaults to <tt>true</tt>, and <tt>timeout</tt> defaults to 0 if not specified. 1241 <tt>wake_lane</tt> defaults to <tt>true</tt>, and <tt>timeout</tt> defaults to 0 if not specified.
1152 </li> 1242 </li>
1153 <li> 1243 <li>
1154 <tt>"call"</tt>, <tt>"ret"</tt>, <tt>"line"</tt>, <tt>"count"</tt>: Asynchronously install the corresponding hook, then behave as <tt>"hard"</tt>. 1244 <tt>"call"</tt>, <tt>"ret"</tt>, <tt>"line"</tt>, <tt>"count"</tt>: Asynchronously install the corresponding hook, then behave as <tt>"hard"</tt>.
1245 <br />
1246 If the lane has the opportunity to call <tt>cancel_test()</tt> before the hook is invoked, calling <tt>cancel_test()</tt> will see it return <tt>"hard"</tt>.
1155 </li> 1247 </li>
1156 <li> 1248 <li>
1157 <tt>"all"</tt>: Installs all hooks in one shot, just to be sure. 1249 <tt>"all"</tt>: Installs all hooks in one shot, just to be sure.
1158 </li> 1250 </li>
1159 </ul> 1251 </ul>
1160 If <tt>mode</tt> is not specified, it defaults to <tt>"hard"</tt>. 1252 <p>
1253 If <tt>mode</tt> is not specified, it defaults to <tt>"hard"</tt>.
1254 </p>
1255</p>
1256<p>
1161 If <tt>wake_lane</tt> is <tt>true</tt>, the lane is also signalled so that execution returns from any pending <a href="#lindas">linda</a> operation. <a href="#lindas">linda</a> operations detecting the cancellation request return <tt>lanes.cancel_error</tt>. 1257 If <tt>wake_lane</tt> is <tt>true</tt>, the lane is also signalled so that execution returns from any pending <a href="#lindas">linda</a> operation. <a href="#lindas">linda</a> operations detecting the cancellation request return <tt>lanes.cancel_error</tt>.
1162</p> 1258</p>
1163<p> 1259<p>
1164 Returns <tt>true, lane_h.status</tt> if lane was already done (in <tt>"done"</tt>, <tt>"error"</tt> or <tt>"cancelled"</tt> status), or the cancellation was fruitful within <tt>timeout_secs</tt> timeout period.<br /> 1260 <tt>timeout</tt> is an optional number &gt= 0. Defaults to infinite if left unspecified or <tt>nil</tt>.
1165 Returns <tt>false, "timeout"</tt> otherwise.
1166</p> 1261</p>
1167<p> 1262<p>
1168 If the lane is still running after the timeout expired, there is a chance lanes will freeze forever at shutdown when failing to terminate all free-running lanes within the specified timeout. 1263 If the lane is still running after the timeout expired, there is a chance lanes will freeze forever at shutdown when failing to terminate all free-running lanes within the specified timeout.
1169</p> 1264</p>
1170<p> 1265<p>
1171 Cancellation is tested <u>before</u> going to sleep in <tt>receive()</tt> or <tt>send()</tt> calls and after executing <tt>cancelstep</tt> Lua statements. A pending <tt>receive()</tt>or <tt>send()</tt> call is awakened. 1266 Cancellation is tested <u>before</u> going to sleep in <tt>receive()</tt>, <tt>receive_batched()</tt> or <tt>send()</tt> calls and after executing <tt>cancelstep</tt> Lua statements. A pending <tt>receive()</tt>or <tt>send()</tt> call is awakened.
1172 <br /> 1267 <br />
1173 This means the execution of the lane will resume although the operation has not completed, to give the lane a chance to detect cancellation (even in the case the code waits on a <a href="#lindas">linda</a> with infinite timeout). 1268 This means the execution of the lane will resume although the operation has not completed, to give the lane a chance to detect cancellation (even in the case the code waits on a <a href="#lindas">linda</a> with infinite timeout).
1174 <br /> 1269 <br />
diff --git a/lanes-4.0.0-0.rockspec b/lanes-4.0.0-0.rockspec
index 77e0f6a..f4de050 100644
--- a/lanes-4.0.0-0.rockspec
+++ b/lanes-4.0.0-0.rockspec
@@ -36,7 +36,7 @@ supported_platforms= { "win32",
36} 36}
37 37
38dependencies= { 38dependencies= {
39 "lua >= 5.1", -- builds with either 5.1/LuaJIT, 5.2, 5.3 and 5.4 39 "lua >= 5.1", -- builds with either 5.1/LuaJIT, 5.2, 5.3, 5.4 and 5.5
40} 40}
41 41
42build = { 42build = {
@@ -56,7 +56,7 @@ build = {
56 }, 56 },
57 modules = 57 modules =
58 { 58 {
59 ["lanes.core"] = 59 ["lanes_core"] =
60 { 60 {
61 sources = 61 sources =
62 { 62 {
diff --git a/src/allocator.cpp b/src/allocator.cpp
index 84acde5..243583b 100644
--- a/src/allocator.cpp
+++ b/src/allocator.cpp
@@ -35,7 +35,7 @@ namespace lanes
35{ 35{
36 AllocatorDefinition& AllocatorDefinition::Validated(lua_State* const L_, StackIndex const idx_) 36 AllocatorDefinition& AllocatorDefinition::Validated(lua_State* const L_, StackIndex const idx_)
37 { 37 {
38 lanes::AllocatorDefinition* const _def{ luaG_tofulluserdata<lanes::AllocatorDefinition>(L_, idx_) }; 38 lanes::AllocatorDefinition* const _def{ luaW_tofulluserdata<lanes::AllocatorDefinition>(L_, idx_) };
39 // raise an error and don't return if the full userdata at the specified index is not a valid AllocatorDefinition 39 // raise an error and don't return if the full userdata at the specified index is not a valid AllocatorDefinition
40 if (!_def) { 40 if (!_def) {
41 raise_luaL_error(L_, "Bad config.allocator function, provided value is not a userdata"); 41 raise_luaL_error(L_, "Bad config.allocator function, provided value is not a userdata");
diff --git a/src/allocator.hpp b/src/allocator.hpp
index c073391..b578f12 100644
--- a/src/allocator.hpp
+++ b/src/allocator.hpp
@@ -33,6 +33,8 @@ namespace lanes {
33 // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception 33 // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception
34 static void operator delete([[maybe_unused]] void* const p_, [[maybe_unused]] lua_State* const L_) {} 34 static void operator delete([[maybe_unused]] void* const p_, [[maybe_unused]] lua_State* const L_) {}
35 35
36 ~AllocatorDefinition() = default;
37
36 AllocatorDefinition(lua_Alloc const allocF_, void* const allocUD_) noexcept 38 AllocatorDefinition(lua_Alloc const allocF_, void* const allocUD_) noexcept
37 : allocF{ allocF_ } 39 : allocF{ allocF_ }
38 , allocUD{ allocUD_ } 40 , allocUD{ allocUD_ }
@@ -64,7 +66,7 @@ namespace lanes {
64 [[nodiscard]] 66 [[nodiscard]]
65 lua_State* newState() const 67 lua_State* newState() const
66 { 68 {
67 return lua_newstate(allocF, allocUD); 69 return luaW_newstate(allocF, allocUD, luaL_makeseed(nullptr));
68 } 70 }
69 71
70 [[nodiscard]] 72 [[nodiscard]]
diff --git a/src/cancel.cpp b/src/cancel.cpp
index 5bba9fc..6812b0d 100644
--- a/src/cancel.cpp
+++ b/src/cancel.cpp
@@ -38,6 +38,53 @@ THE SOFTWARE.
38#include "debugspew.hpp" 38#include "debugspew.hpp"
39#include "lane.hpp" 39#include "lane.hpp"
40 40
41namespace {
42 namespace local {
43
44 // #########################################################################################
45 // #########################################################################################
46
47 [[nodiscard]]
48 static std::optional<CancelOp> WhichCancelOp(std::string_view const& opString_)
49 {
50 if (opString_ == "soft") {
51 return std::make_optional<CancelOp>(CancelRequest::Soft, LuaHookMask::None);
52 } else if (opString_ == "hard") {
53 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::None);
54 } else if (opString_ == "call") {
55 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Call);
56 } else if (opString_ == "ret") {
57 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Ret);
58 } else if (opString_ == "line") {
59 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Line);
60 } else if (opString_ == "count") {
61 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Count);
62 } else if (opString_ == "all") {
63 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::All);
64 }
65 return std::nullopt;
66 }
67
68 // #########################################################################################
69
70 [[nodiscard]]
71 static CancelOp WhichCancelOp(lua_State* const L_, StackIndex const idx_)
72 {
73 if (luaW_type(L_, idx_) == LuaType::STRING) {
74 std::string_view const _str{ luaW_tostring(L_, idx_) };
75 auto const _op{ WhichCancelOp(_str) };
76 lua_remove(L_, idx_); // argument is processed, remove it
77 if (!_op.has_value()) {
78 raise_luaL_error(L_, "Invalid cancel operation '%s'", _str.data());
79 }
80 return _op.value();
81 }
82 return CancelOp{ CancelRequest::Hard, LuaHookMask::None };
83 }
84
85 } // namespace local
86} // namespace
87
41// ################################################################################################# 88// #################################################################################################
42// ################################################################################################# 89// #################################################################################################
43 90
@@ -60,66 +107,6 @@ CancelRequest CheckCancelRequest(lua_State* const L_)
60 107
61// ################################################################################################# 108// #################################################################################################
62// ################################################################################################# 109// #################################################################################################
63
64//---
65// = lane_cancel( lane_ud [,timeout_secs=0.0] [,wake_lindas_bool=false] )
66//
67// The originator thread asking us specifically to cancel the other thread.
68//
69// 'timeout': <0: wait forever, until the lane is finished
70// 0.0: just signal it to cancel, no time waited
71// >0: time to wait for the lane to detect cancellation
72//
73// 'wake_lindas_bool': if true, signal any linda the thread is waiting on
74// instead of waiting for its timeout (if any)
75//
76// Returns: true if the lane was already finished (Done/Error/Cancelled) or if we
77// managed to cancel it.
78// false if the cancellation timed out, or a kill was needed.
79//
80
81// #################################################################################################
82// #################################################################################################
83
84static std::optional<CancelOp> WhichCancelOp(std::string_view const& opString_)
85{
86 if (opString_ == "soft") {
87 return std::make_optional<CancelOp>(CancelRequest::Soft, LuaHookMask::None);
88 } else if (opString_ == "hard") {
89 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::None);
90 } else if (opString_== "call") {
91 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Call);
92 } else if (opString_ == "ret") {
93 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Ret);
94 } else if (opString_ == "line") {
95 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Line);
96 } else if (opString_ == "count") {
97 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::Count);
98 } else if (opString_ == "all") {
99 return std::make_optional<CancelOp>(CancelRequest::Hard, LuaHookMask::All);
100 }
101 return std::nullopt;
102}
103
104// #################################################################################################
105
106[[nodiscard]]
107static CancelOp WhichCancelOp(lua_State* const L_, StackIndex const idx_)
108{
109 if (luaG_type(L_, idx_) == LuaType::STRING) {
110 std::string_view const _str{ luaG_tostring(L_, idx_) };
111 auto const _op{ WhichCancelOp(_str) };
112 lua_remove(L_, idx_); // argument is processed, remove it
113 if (!_op.has_value()) {
114 raise_luaL_error(L_, "Invalid cancel operation '%s'", _str.data());
115 }
116 return _op.value();
117 }
118 return CancelOp{ CancelRequest::Hard, LuaHookMask::None };
119}
120
121// #################################################################################################
122// #################################################################################################
123// ######################################### Lua API ############################################### 110// ######################################### Lua API ###############################################
124// ################################################################################################# 111// #################################################################################################
125// ################################################################################################# 112// #################################################################################################
@@ -133,24 +120,45 @@ static CancelOp WhichCancelOp(lua_State* const L_, StackIndex const idx_)
133LUAG_FUNC(cancel_test) 120LUAG_FUNC(cancel_test)
134{ 121{
135 CancelRequest const _test{ CheckCancelRequest(L_) }; 122 CancelRequest const _test{ CheckCancelRequest(L_) };
136 lua_pushboolean(L_, _test != CancelRequest::None); 123 if (_test == CancelRequest::None) {
124 lua_pushboolean(L_, 0);
125 } else {
126 luaW_pushstring(L_, (_test == CancelRequest::Soft) ? "soft" : "hard");
127 }
137 return 1; 128 return 1;
138} 129}
139 130
140// ################################################################################################# 131// #################################################################################################
141 132
133//---
134// = lane_cancel( lane_ud [,timeout_secs=0.0] [,wake_lindas_bool=false] )
135//
136// The originator thread asking us specifically to cancel the other thread.
137//
138// 'timeout': <0: wait forever, until the lane is finished
139// 0.0: just signal it to cancel, no time waited
140// >0: time to wait for the lane to detect cancellation
141//
142// 'wake_lindas_bool': if true, signal any linda the thread is waiting on
143// instead of waiting for its timeout (if any)
144//
145// Returns: true if the lane was already finished (Done/Error/Cancelled) or if we
146// managed to cancel it.
147// false if the cancellation timed out, or a kill was needed.
148//
149
142// bool[,reason] = lane_h:cancel( [cancel_op, hookcount] [, timeout] [, wake_lane]) 150// bool[,reason] = lane_h:cancel( [cancel_op, hookcount] [, timeout] [, wake_lane])
143LUAG_FUNC(lane_cancel) 151LUAG_FUNC(lane_cancel)
144{ 152{
145 Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: lane [cancel_op, hookcount] [, timeout] [, wake_lane] 153 Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: lane [cancel_op, hookcount] [, timeout] [, wake_lane]
146 CancelOp const _op{ WhichCancelOp(L_, StackIndex{ 2 }) }; // L_: lane [hookcount] [, timeout] [, wake_lane] 154 CancelOp const _op{ local::WhichCancelOp(L_, StackIndex{ 2 }) }; // L_: lane [hookcount] [, timeout] [, wake_lane]
147 155
148 int const _hook_count{ std::invoke([_op, L_]() { 156 int const _hook_count{ std::invoke([_op, L_]() {
149 if (_op.hookMask == LuaHookMask::None) { 157 if (_op.hookMask == LuaHookMask::None) {
150 // the caller shouldn't have provided a hook count in that case 158 // the caller shouldn't have provided a hook count in that case
151 return 0; 159 return 0;
152 } 160 }
153 if (luaG_type(L_, StackIndex{ 2 }) != LuaType::NUMBER) { 161 if (luaW_type(L_, StackIndex{ 2 }) != LuaType::NUMBER) {
154 raise_luaL_error(L_, "Hook count expected"); 162 raise_luaL_error(L_, "Hook count expected");
155 } 163 }
156 auto const _hook_count{ static_cast<int>(lua_tointeger(L_, 2)) }; 164 auto const _hook_count{ static_cast<int>(lua_tointeger(L_, 2)) };
@@ -162,7 +170,7 @@ LUAG_FUNC(lane_cancel)
162 }) }; 170 }) };
163 171
164 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; 172 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() };
165 if (luaG_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion 173 if (luaW_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion
166 lua_Duration const duration{ lua_tonumber(L_, 2) }; 174 lua_Duration const duration{ lua_tonumber(L_, 2) };
167 if (duration.count() >= 0.0) { 175 if (duration.count() >= 0.0) {
168 _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); 176 _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration);
@@ -178,7 +186,7 @@ LUAG_FUNC(lane_cancel)
178 WakeLane _wake_lane{ (_op.mode == CancelRequest::Hard) ? WakeLane::Yes : WakeLane::No }; 186 WakeLane _wake_lane{ (_op.mode == CancelRequest::Hard) ? WakeLane::Yes : WakeLane::No };
179 if (lua_gettop(L_) >= 2) { 187 if (lua_gettop(L_) >= 2) {
180 if (!lua_isboolean(L_, 2)) { 188 if (!lua_isboolean(L_, 2)) {
181 raise_luaL_error(L_, "Boolean expected for wake_lane argument, got %s", luaG_typename(L_, StackIndex{ 2 }).data()); 189 raise_luaL_error(L_, "Boolean expected for wake_lane argument, got %s", luaW_typename(L_, StackIndex{ 2 }).data());
182 } 190 }
183 _wake_lane = lua_toboolean(L_, 2) ? WakeLane::Yes : WakeLane::No; 191 _wake_lane = lua_toboolean(L_, 2) ? WakeLane::Yes : WakeLane::No;
184 lua_remove(L_, 2); // argument is processed, remove it // L_: lane 192 lua_remove(L_, 2); // argument is processed, remove it // L_: lane
@@ -198,7 +206,7 @@ LUAG_FUNC(lane_cancel)
198 206
199 case CancelResult::Timeout: 207 case CancelResult::Timeout:
200 lua_pushboolean(L_, 0); // L_: false 208 lua_pushboolean(L_, 0); // L_: false
201 luaG_pushstring(L_, "timeout"); // L_: false "timeout" 209 luaW_pushstring(L_, "timeout"); // L_: false "timeout"
202 break; 210 break;
203 211
204 case CancelResult::Cancelled: 212 case CancelResult::Cancelled:
diff --git a/src/compat.cpp b/src/compat.cpp
index 7e90142..c833480 100644
--- a/src/compat.cpp
+++ b/src/compat.cpp
@@ -5,10 +5,10 @@
5 5
6// ################################################################################################# 6// #################################################################################################
7 7
8UserValueCount luaG_getalluservalues(lua_State* const L_, StackIndex const idx_) 8UserValueCount luaW_getalluservalues(lua_State* const L_, StackIndex const idx_)
9{ 9{
10 STACK_CHECK_START_REL(L_, 0); 10 STACK_CHECK_START_REL(L_, 0);
11 StackIndex const _idx{ luaG_absindex(L_, idx_) }; 11 StackIndex const _idx{ luaW_absindex(L_, idx_) };
12 UserValueIndex _nuv{ 0 }; 12 UserValueIndex _nuv{ 0 };
13 do { 13 do {
14 // we don't know how many uservalues we are going to extract, there might be a lot... 14 // we don't know how many uservalues we are going to extract, there might be a lot...
@@ -24,15 +24,15 @@ UserValueCount luaG_getalluservalues(lua_State* const L_, StackIndex const idx_)
24// ################################################################################################# 24// #################################################################################################
25 25
26// a small helper to obtain a module's table from the registry instead of relying on the presence of _G["<name>"] 26// a small helper to obtain a module's table from the registry instead of relying on the presence of _G["<name>"]
27LuaType luaG_getmodule(lua_State* const L_, std::string_view const& name_) 27LuaType luaW_getmodule(lua_State* const L_, std::string_view const& name_)
28{ 28{
29 STACK_CHECK_START_REL(L_, 0); 29 STACK_CHECK_START_REL(L_, 0);
30 LuaType _type{ luaG_getfield(L_, kIdxRegistry, LUA_LOADED_TABLE) }; // L_: _R._LOADED|nil 30 LuaType _type{ luaW_getfield(L_, kIdxRegistry, LUA_LOADED_TABLE) }; // L_: _R._LOADED|nil
31 if (_type != LuaType::TABLE) { // L_: _R._LOADED|nil 31 if (_type != LuaType::TABLE) { // L_: _R._LOADED|nil
32 STACK_CHECK(L_, 1); 32 STACK_CHECK(L_, 1);
33 return _type; 33 return _type;
34 } 34 }
35 _type = luaG_getfield(L_, kIdxTop, name_); // L_: _R._LOADED {module}|nil 35 _type = luaW_getfield(L_, kIdxTop, name_); // L_: _R._LOADED {module}|nil
36 lua_remove(L_, -2); // L_: {module}|nil 36 lua_remove(L_, -2); // L_: {module}|nil
37 STACK_CHECK(L_, 1); 37 STACK_CHECK(L_, 1);
38 return _type; 38 return _type;
@@ -52,7 +52,7 @@ int luaL_getsubtable(lua_State* const L_, StackIndex const idx_, char const* fna
52 return 1; /* table already there */ 52 return 1; /* table already there */
53 } else { 53 } else {
54 lua_pop(L_, 1); /* remove previous result */ 54 lua_pop(L_, 1); /* remove previous result */
55 StackIndex const _absidx{ luaG_absindex(L_, idx_) }; 55 StackIndex const _absidx{ luaW_absindex(L_, idx_) };
56 lua_newtable(L_); 56 lua_newtable(L_);
57 lua_pushvalue(L_, -1); /* copy to be left at top */ 57 lua_pushvalue(L_, -1); /* copy to be left at top */
58 lua_setfield(L_, _absidx, fname_); /* assign new table to field */ 58 lua_setfield(L_, _absidx, fname_); /* assign new table to field */
@@ -149,3 +149,41 @@ int lua_setiuservalue(lua_State* const L_, StackIndex const idx_, UserValueIndex
149} 149}
150 150
151#endif // LUA_VERSION_NUM 151#endif // LUA_VERSION_NUM
152
153// #################################################################################################
154
155#if LUA_VERSION_NUM < 505
156
157#include <time.h>
158
159/* Size for the buffer, in bytes */
160#define BUFSEEDB (sizeof(void*) + sizeof(time_t))
161
162/* Size for the buffer in int's, rounded up */
163#define BUFSEED ((BUFSEEDB + sizeof(int) - 1) / sizeof(int))
164
165/*
166** Copy the contents of variable 'v' into the buffer pointed by 'b'.
167** (The '&b[0]' disguises 'b' to fix an absurd warning from clang.)
168*/
169#define addbuff(b, v) (memcpy(&b[0], &(v), sizeof(v)), b += sizeof(v))
170
171// Copied from Lua 5.5 lauxlib.c
172unsigned int luaL_makeseed(lua_State*)
173{
174 unsigned int buff[BUFSEED];
175 unsigned int res;
176 unsigned int i;
177 time_t t = time(nullptr);
178 char* b = (char*) buff;
179 addbuff(b, b); /* local variable's address */
180 addbuff(b, t); /* time */
181 /* fill (rare but possible) remain of the buffer with zeros */
182 memset(b, 0, sizeof(buff) - BUFSEEDB);
183 res = buff[0];
184 for (i = 1; i < BUFSEED; i++)
185 res ^= (res >> 3) + (res << 7) + buff[i];
186 return res;
187}
188
189#endif // LUA_VERSION_NUM < 505
diff --git a/src/compat.hpp b/src/compat.hpp
index 9a8dedf..4dc7433 100644
--- a/src/compat.hpp
+++ b/src/compat.hpp
@@ -5,7 +5,6 @@
5 5
6// try to detect if we are building against LuaJIT or MoonJIT 6// try to detect if we are building against LuaJIT or MoonJIT
7#if defined(LUA_JITLIBNAME) 7#if defined(LUA_JITLIBNAME)
8#include "luajit.h"
9#if (defined(__x86_64__) || defined(_M_X64) || defined(__LP64__)) 8#if (defined(__x86_64__) || defined(_M_X64) || defined(__LP64__))
10#define LUAJIT_FLAVOR() 64 9#define LUAJIT_FLAVOR() 64
11#else // 64 bits 10#else // 64 bits
@@ -21,7 +20,7 @@
21#endif // LUA_OK 20#endif // LUA_OK
22 21
23#ifndef LUA_ERRGCMM 22#ifndef LUA_ERRGCMM
24#define LUA_ERRGCMM 666 // doesn't exist in Lua 5.1 and Lua 5.4, we don't care about the actual value 23#define LUA_ERRGCMM 666 // doesn't exist in Lua 5.1 and Lua 5.4/5.5, we don't care about the actual value
25#endif // LUA_ERRGCMM 24#endif // LUA_ERRGCMM
26 25
27 26
@@ -29,7 +28,7 @@
29#define LUA_LOADED_TABLE "_LOADED" // doesn't exist before Lua 5.3 28#define LUA_LOADED_TABLE "_LOADED" // doesn't exist before Lua 5.3
30#endif // LUA_LOADED_TABLE 29#endif // LUA_LOADED_TABLE
31 30
32// code is now preferring Lua 5.4 API 31// code is now preferring Lua 5.5 API
33 32
34// ################################################################################################# 33// #################################################################################################
35 34
@@ -76,18 +75,6 @@ int luaL_getsubtable(lua_State* L_, StackIndex idx_, char const* fname_);
76 75
77// ################################################################################################# 76// #################################################################################################
78 77
79// wrap Lua 5.3 calls under Lua 5.1 API when it is simpler that way
80#if LUA_VERSION_NUM == 503
81
82inline int luaL_optint(lua_State* L_, int n_, lua_Integer d_)
83{
84 return static_cast<int>(luaL_optinteger(L_, n_, d_));
85}
86
87#endif // LUA_VERSION_NUM == 503
88
89// #################################################################################################
90
91#if LUA_VERSION_NUM < 504 78#if LUA_VERSION_NUM < 504
92 79
93void* lua_newuserdatauv(lua_State* L_, size_t sz_, UserValueCount nuvalue_); 80void* lua_newuserdatauv(lua_State* L_, size_t sz_, UserValueCount nuvalue_);
@@ -100,15 +87,11 @@ int lua_setiuservalue(lua_State* L_, StackIndex idx_, UserValueIndex n_);
100 87
101// ################################################################################################# 88// #################################################################################################
102 89
103// wrap Lua 5.4 calls under Lua 5.1 API when it is simpler that way 90#if LUA_VERSION_NUM < 505
104#if LUA_VERSION_NUM == 504
105 91
106inline int luaL_optint(lua_State* L_, StackIndex n_, lua_Integer d_) 92unsigned int luaL_makeseed(lua_State*);
107{
108 return static_cast<int>(luaL_optinteger(L_, n_, d_));
109}
110 93
111#endif // LUA_VERSION_NUM == 504 94#endif // LUA_VERSION_NUM < 505
112 95
113// ################################################################################################# 96// #################################################################################################
114 97
@@ -136,14 +119,14 @@ inline constexpr LuaError ToLuaError(int const rc_)
136 119
137// break lexical order for that one because it's needed below 120// break lexical order for that one because it's needed below
138[[nodiscard]] 121[[nodiscard]]
139inline LuaType luaG_type(lua_State* const L_, StackIndex const idx_) 122inline LuaType luaW_type(lua_State* const L_, StackIndex const idx_)
140{ 123{
141 return static_cast<LuaType>(lua_type(L_, idx_)); 124 return static_cast<LuaType>(lua_type(L_, idx_));
142} 125}
143 126
144// ################################################################################################# 127// #################################################################################################
145// ################################################################################################# 128// #################################################################################################
146// All the compatibility wrappers we expose start with luaG_ 129// All the compatibility wrappers we expose start with luaW_
147// ################################################################################################# 130// #################################################################################################
148// ################################################################################################# 131// #################################################################################################
149 132
@@ -152,7 +135,7 @@ inline LuaType luaG_type(lua_State* const L_, StackIndex const idx_)
152 135
153// a replacement of lua_tolstring 136// a replacement of lua_tolstring
154[[nodiscard]] 137[[nodiscard]]
155inline std::string_view luaG_tostring(lua_State* const L_, StackIndex const idx_) 138inline std::string_view luaW_tostring(lua_State* const L_, StackIndex const idx_)
156{ 139{
157 size_t _len{ 0 }; 140 size_t _len{ 0 };
158 char const* _str{ lua_tolstring(L_, idx_, &_len) }; 141 char const* _str{ lua_tolstring(L_, idx_, &_len) };
@@ -160,7 +143,7 @@ inline std::string_view luaG_tostring(lua_State* const L_, StackIndex const idx_
160} 143}
161 144
162[[nodiscard]] 145[[nodiscard]]
163inline std::string_view luaG_checkstring(lua_State* const L_, StackIndex const idx_) 146inline std::string_view luaW_checkstring(lua_State* const L_, StackIndex const idx_)
164{ 147{
165 size_t _len{ 0 }; 148 size_t _len{ 0 };
166 char const* _str{ luaL_checklstring(L_, idx_, &_len) }; 149 char const* _str{ luaL_checklstring(L_, idx_, &_len) };
@@ -168,7 +151,7 @@ inline std::string_view luaG_checkstring(lua_State* const L_, StackIndex const i
168} 151}
169 152
170[[nodiscard]] 153[[nodiscard]]
171inline std::string_view luaG_optstring(lua_State* const L_, StackIndex const idx_, std::string_view const& default_) 154inline std::string_view luaW_optstring(lua_State* const L_, StackIndex const idx_, std::string_view const& default_)
172{ 155{
173 if (lua_isnoneornil(L_, idx_)) { 156 if (lua_isnoneornil(L_, idx_)) {
174 return default_; 157 return default_;
@@ -179,13 +162,13 @@ inline std::string_view luaG_optstring(lua_State* const L_, StackIndex const idx
179} 162}
180 163
181template <typename... EXTRA> 164template <typename... EXTRA>
182inline std::string_view luaG_pushstring(lua_State* const L_, std::string_view const& str_, EXTRA&&... extra_) 165inline std::string_view luaW_pushstring(lua_State* const L_, std::string_view const& str_, EXTRA&&... extra_)
183{ 166{
184 if constexpr (sizeof...(EXTRA) == 0) { 167 if constexpr (sizeof...(EXTRA) == 0) {
185 if constexpr (LUA_VERSION_NUM == 501) { 168 if constexpr (LUA_VERSION_NUM == 501) {
186 // lua_pushlstring doesn't return a value in Lua 5.1 169 // lua_pushlstring doesn't return a value in Lua 5.1
187 lua_pushlstring(L_, str_.data(), str_.size()); 170 lua_pushlstring(L_, str_.data(), str_.size());
188 return luaG_tostring(L_, kIdxTop); 171 return luaW_tostring(L_, kIdxTop);
189 } else { 172 } else {
190 return std::string_view{ lua_pushlstring(L_, str_.data(), str_.size()), str_.size() }; 173 return std::string_view{ lua_pushlstring(L_, str_.data(), str_.size()), str_.size() };
191 } 174 }
@@ -198,7 +181,7 @@ inline std::string_view luaG_pushstring(lua_State* const L_, std::string_view co
198// ################################################################################################# 181// #################################################################################################
199 182
200// use this in place of lua_absindex to save a function call 183// use this in place of lua_absindex to save a function call
201inline StackIndex luaG_absindex(lua_State* const L_, StackIndex const idx_) 184inline StackIndex luaW_absindex(lua_State* const L_, StackIndex const idx_)
202{ 185{
203 return StackIndex{ (idx_ >= 0 || idx_ <= kIdxRegistry) ? idx_ : StackIndex{ lua_gettop(L_) + idx_ + 1 } }; 186 return StackIndex{ (idx_ >= 0 || idx_ <= kIdxRegistry) ? idx_ : StackIndex{ lua_gettop(L_) + idx_ + 1 } };
204} 187}
@@ -227,14 +210,14 @@ static inline int WrapLuaDump(LUA_DUMP f_, lua_State* const L_, lua_Writer const
227 210
228// ------------------------------------------------------------------------------------------------- 211// -------------------------------------------------------------------------------------------------
229 212
230static inline int luaG_dump(lua_State* const L_, lua_Writer const writer_, void* const data_, int const strip_) 213static inline int luaW_dump(lua_State* const L_, lua_Writer const writer_, void* const data_, int const strip_)
231{ 214{
232 return WrapLuaDump(lua_dump, L_, writer_, data_, strip_); 215 return WrapLuaDump(lua_dump, L_, writer_, data_, strip_);
233} 216}
234 217
235// ################################################################################################# 218// #################################################################################################
236 219
237UserValueCount luaG_getalluservalues(lua_State* L_, StackIndex idx_); 220UserValueCount luaW_getalluservalues(lua_State* L_, StackIndex idx_);
238 221
239// ################################################################################################# 222// #################################################################################################
240 223
@@ -272,7 +255,7 @@ static inline int WrapLuaGetField(LUA_GETFIELD f_, lua_State* const L_, StackInd
272// ------------------------------------------------------------------------------------------------- 255// -------------------------------------------------------------------------------------------------
273 256
274[[nodiscard]] 257[[nodiscard]]
275static inline LuaType luaG_getfield(lua_State* const L_, StackIndex const idx_, std::string_view const& name_) 258static inline LuaType luaW_getfield(lua_State* const L_, StackIndex const idx_, std::string_view const& name_)
276{ 259{
277 return static_cast<LuaType>(WrapLuaGetField(lua_getfield, L_, idx_, name_)); 260 return static_cast<LuaType>(WrapLuaGetField(lua_getfield, L_, idx_, name_));
278} 261}
@@ -280,21 +263,62 @@ static inline LuaType luaG_getfield(lua_State* const L_, StackIndex const idx_,
280// ################################################################################################# 263// #################################################################################################
281 264
282[[nodiscard]] 265[[nodiscard]]
283LuaType luaG_getmodule(lua_State* L_, std::string_view const& name_); 266LuaType luaW_getmodule(lua_State* L_, std::string_view const& name_);
267
268// #################################################################################################
269
270template <typename LUA_NEWSTATE>
271concept RequiresOldLuaNewState = requires(LUA_NEWSTATE f_)
272{
273 {
274 f_(nullptr, 0)
275 } -> std::same_as<lua_State*>;
276};
277
278template <RequiresOldLuaNewState LUA_NEWSTATE>
279static inline lua_State* WrapLuaNewState(LUA_NEWSTATE const lua_newstate_, lua_Alloc const allocf_, void* const ud_, [[maybe_unused]] unsigned int const seed_)
280{
281 // until Lua 5.5, lua_newstate has only 2 parameters
282 return lua_newstate_(allocf_, ud_);
283}
284
285// -------------------------------------------------------------------------------------------------
286
287template <typename LUA_NEWSTATE>
288concept RequiresNewLuaNewState = requires(LUA_NEWSTATE f_)
289{
290 {
291 f_(nullptr, nullptr, 0)
292 } -> std::same_as<lua_State*>;
293};
294
295template <RequiresNewLuaNewState LUA_NEWSTATE>
296static inline lua_State* WrapLuaNewState(LUA_NEWSTATE const lua_newstate_, lua_Alloc const allocf_, void* const ud_, unsigned int const seed_)
297{
298 // starting with Lua 5.5, lua_newstate has 3 parameters
299 return lua_newstate_(allocf_, ud_, seed_);
300}
301
302// -------------------------------------------------------------------------------------------------
303
304static inline lua_State* luaW_newstate(lua_Alloc const allocf_, void* const ud_, unsigned int const seed_)
305{
306 return WrapLuaNewState(lua_newstate, allocf_, ud_, seed_);
307}
284 308
285// ################################################################################################# 309// #################################################################################################
286 310
287template<typename ENUM> 311template<typename ENUM>
288requires std::is_enum_v<ENUM> 312requires std::is_enum_v<ENUM>
289[[nodiscard]] 313[[nodiscard]]
290ENUM luaG_optenum(lua_State* const L_, StackIndex const idx_, ENUM const def_) 314ENUM luaW_optenum(lua_State* const L_, StackIndex const idx_, ENUM const def_)
291{ 315{
292 return static_cast<ENUM>(luaL_optinteger(L_, idx_, static_cast<std::underlying_type_t<ENUM>>(def_))); 316 return static_cast<ENUM>(luaL_optinteger(L_, idx_, static_cast<std::underlying_type_t<ENUM>>(def_)));
293} 317}
294 318
295// ################################################################################################# 319// #################################################################################################
296 320
297inline void luaG_registerlibfuncs(lua_State* const L_, luaL_Reg const* funcs_) 321inline void luaW_registerlibfuncs(lua_State* const L_, luaL_Reg const* funcs_)
298{ 322{
299 // fake externs to make clang happy... 323 // fake externs to make clang happy...
300 extern void luaL_register(lua_State*, char const*, luaL_Reg const*); // Lua 5.1 324 extern void luaL_register(lua_State*, char const*, luaL_Reg const*); // Lua 5.1
@@ -353,7 +377,7 @@ static inline int WrapLuaResume(LUA_RESUME const lua_resume_, lua_State* const L
353// ------------------------------------------------------------------------------------------------- 377// -------------------------------------------------------------------------------------------------
354 378
355[[nodiscard]] 379[[nodiscard]]
356static inline LuaError luaG_resume(lua_State* const L_, lua_State* const from_, int const nargs_, int* const nresults_) 380static inline LuaError luaW_resume(lua_State* const L_, lua_State* const from_, int const nargs_, int* const nresults_)
357{ 381{
358 return ToLuaError(WrapLuaResume(lua_resume, L_, from_, nargs_, nresults_)); 382 return ToLuaError(WrapLuaResume(lua_resume, L_, from_, nargs_, nresults_));
359} 383}
@@ -364,11 +388,11 @@ template <typename LUA_RAWGET>
364concept RequiresOldLuaRawget = requires(LUA_RAWGET f_) { { f_(nullptr, 0) } -> std::same_as<void>; }; 388concept RequiresOldLuaRawget = requires(LUA_RAWGET f_) { { f_(nullptr, 0) } -> std::same_as<void>; };
365 389
366template <RequiresOldLuaRawget LUA_RAWGET> 390template <RequiresOldLuaRawget LUA_RAWGET>
367static inline LuaType WrapLuaRawget(LUA_RAWGET lua_rawget_, lua_State* const L_, StackIndex const idx_) 391static inline LuaType WrapLuaRawget(LUA_RAWGET const lua_rawget_, lua_State* const L_, StackIndex const idx_)
368{ 392{
369 // until Lua 5.3, lua_rawget -> void 393 // until Lua 5.3, lua_rawget -> void
370 lua_rawget_(L_, idx_); 394 lua_rawget_(L_, idx_);
371 return luaG_type(L_, kIdxTop); 395 return luaW_type(L_, kIdxTop);
372} 396}
373 397
374// ------------------------------------------------------------------------------------------------- 398// -------------------------------------------------------------------------------------------------
@@ -377,7 +401,7 @@ template <typename LUA_RAWGET>
377concept RequiresNewLuaRawget = requires(LUA_RAWGET f_) { { f_(nullptr, 0) } -> std::same_as<int>; }; 401concept RequiresNewLuaRawget = requires(LUA_RAWGET f_) { { f_(nullptr, 0) } -> std::same_as<int>; };
378 402
379template <RequiresNewLuaRawget LUA_RAWGET> 403template <RequiresNewLuaRawget LUA_RAWGET>
380static inline LuaType WrapLuaRawget(LUA_RAWGET lua_rawget_, lua_State* const L_, StackIndex const idx_) 404static inline LuaType WrapLuaRawget(LUA_RAWGET const lua_rawget_, lua_State* const L_, StackIndex const idx_)
381{ 405{
382 // starting with Lua 5.3, lua_rawget -> int (the type of the extracted value) 406 // starting with Lua 5.3, lua_rawget -> int (the type of the extracted value)
383 return static_cast<LuaType>(lua_rawget_(L_, idx_)); 407 return static_cast<LuaType>(lua_rawget_(L_, idx_));
@@ -385,42 +409,42 @@ static inline LuaType WrapLuaRawget(LUA_RAWGET lua_rawget_, lua_State* const L_,
385 409
386// ------------------------------------------------------------------------------------------------- 410// -------------------------------------------------------------------------------------------------
387 411
388static inline LuaType luaG_rawget(lua_State* const L_, StackIndex const idx_) 412static inline LuaType luaW_rawget(lua_State* const L_, StackIndex const idx_)
389{ 413{
390 return WrapLuaRawget(lua_rawget, L_, idx_); 414 return WrapLuaRawget(lua_rawget, L_, idx_);
391} 415}
392 416
393// ################################################################################################# 417// #################################################################################################
394 418
395static inline LuaType luaG_rawgetfield(lua_State* const L_, StackIndex const idx_, std::string_view const& name_) 419static inline LuaType luaW_rawgetfield(lua_State* const L_, StackIndex const idx_, std::string_view const& name_)
396{ 420{
397 auto const _absIdx{ luaG_absindex(L_, idx_) }; 421 auto const _absIdx{ luaW_absindex(L_, idx_) };
398 luaG_pushstring(L_, name_); // L_: ... t ... name_ 422 luaW_pushstring(L_, name_); // L_: ... t ... name_
399 lua_rawget(L_, _absIdx); // L_: ... t ... <field> 423 lua_rawget(L_, _absIdx); // L_: ... t ... <field>
400 return luaG_type(L_, kIdxTop); 424 return luaW_type(L_, kIdxTop);
401} 425}
402 426
403// ################################################################################################# 427// #################################################################################################
404 428
405template <size_t N> 429template <size_t N>
406static inline void luaG_newlib(lua_State* const L_, luaL_Reg const (&funcs_)[N]) 430static inline void luaW_newlib(lua_State* const L_, luaL_Reg const (&funcs_)[N])
407{ 431{
408 lua_createtable(L_, 0, N - 1); 432 lua_createtable(L_, 0, N - 1);
409 luaG_registerlibfuncs(L_, funcs_); 433 luaW_registerlibfuncs(L_, funcs_);
410} 434}
411 435
412// ################################################################################################# 436// #################################################################################################
413 437
414template <typename T> 438template <typename T>
415[[nodiscard]] 439[[nodiscard]]
416T* luaG_newuserdatauv(lua_State* const L_, UserValueCount const nuvalue_) 440T* luaW_newuserdatauv(lua_State* const L_, UserValueCount const nuvalue_)
417{ 441{
418 return static_cast<T*>(lua_newuserdatauv(L_, sizeof(T), nuvalue_)); 442 return static_cast<T*>(lua_newuserdatauv(L_, sizeof(T), nuvalue_));
419} 443}
420 444
421// ################################################################################################# 445// #################################################################################################
422 446
423inline void luaG_pushglobaltable(lua_State* const L_) 447inline void luaW_pushglobaltable(lua_State* const L_)
424{ 448{
425#ifdef LUA_GLOBALSINDEX // All flavors of Lua 5.1 449#ifdef LUA_GLOBALSINDEX // All flavors of Lua 5.1
426 ::lua_pushvalue(L_, LUA_GLOBALSINDEX); 450 ::lua_pushvalue(L_, LUA_GLOBALSINDEX);
@@ -431,15 +455,15 @@ inline void luaG_pushglobaltable(lua_State* const L_)
431 455
432// ################################################################################################# 456// #################################################################################################
433 457
434inline void luaG_setfield(lua_State* const L_, StackIndex const idx_, char const* const k_) = delete; 458inline void luaW_setfield(lua_State* const L_, StackIndex const idx_, char const* const k_) = delete;
435inline void luaG_setfield(lua_State* const L_, StackIndex const idx_, std::string_view const& k_) 459inline void luaW_setfield(lua_State* const L_, StackIndex const idx_, std::string_view const& k_)
436{ 460{
437 lua_setfield(L_, idx_, k_.data()); 461 lua_setfield(L_, idx_, k_.data());
438} 462}
439 463
440// ################################################################################################# 464// #################################################################################################
441 465
442inline void luaG_setmetatable(lua_State* const L_, std::string_view const& tname_) 466inline void luaW_setmetatable(lua_State* const L_, std::string_view const& tname_)
443{ 467{
444 // fake externs to make clang happy... 468 // fake externs to make clang happy...
445 if constexpr (LUA_VERSION_NUM > 501) { 469 if constexpr (LUA_VERSION_NUM > 501) {
@@ -456,7 +480,7 @@ inline void luaG_setmetatable(lua_State* const L_, std::string_view const& tname
456// a small helper to extract a full userdata pointer from the stack in a safe way 480// a small helper to extract a full userdata pointer from the stack in a safe way
457template <typename T> 481template <typename T>
458[[nodiscard]] 482[[nodiscard]]
459T* luaG_tofulluserdata(lua_State* const L_, StackIndex const index_) 483T* luaW_tofulluserdata(lua_State* const L_, StackIndex const index_)
460{ 484{
461 LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_type(L_, index_) == LUA_TUSERDATA); 485 LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_type(L_, index_) == LUA_TUSERDATA);
462 return static_cast<T*>(lua_touserdata(L_, index_)); 486 return static_cast<T*>(lua_touserdata(L_, index_));
@@ -466,7 +490,7 @@ T* luaG_tofulluserdata(lua_State* const L_, StackIndex const index_)
466 490
467template <typename T> 491template <typename T>
468[[nodiscard]] 492[[nodiscard]]
469auto luaG_tolightuserdata(lua_State* const L_, StackIndex const index_) 493auto luaW_tolightuserdata(lua_State* const L_, StackIndex const index_)
470{ 494{
471 LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_islightuserdata(L_, index_)); 495 LUA_ASSERT(L_, lua_isnil(L_, index_) || lua_islightuserdata(L_, index_));
472 if constexpr (std::is_pointer_v<T>) { 496 if constexpr (std::is_pointer_v<T>) {
@@ -479,7 +503,7 @@ auto luaG_tolightuserdata(lua_State* const L_, StackIndex const index_)
479// ------------------------------------------------------------------------------------------------- 503// -------------------------------------------------------------------------------------------------
480 504
481[[nodiscard]] 505[[nodiscard]]
482inline std::string_view luaG_typename(lua_State* const L_, LuaType const t_) 506inline std::string_view luaW_typename(lua_State* const L_, LuaType const t_)
483{ 507{
484 return lua_typename(L_, static_cast<int>(t_)); 508 return lua_typename(L_, static_cast<int>(t_));
485} 509}
@@ -487,7 +511,7 @@ inline std::string_view luaG_typename(lua_State* const L_, LuaType const t_)
487// ------------------------------------------------------------------------------------------------- 511// -------------------------------------------------------------------------------------------------
488 512
489[[nodiscard]] 513[[nodiscard]]
490inline std::string_view luaG_typename(lua_State* const L_, StackIndex const idx_) 514inline std::string_view luaW_typename(lua_State* const L_, StackIndex const idx_)
491{ 515{
492 return luaG_typename(L_, luaG_type(L_, idx_)); 516 return luaW_typename(L_, luaW_type(L_, idx_));
493} 517}
diff --git a/src/deep.cpp b/src/deep.cpp
index 82f1214..acd93a6 100644
--- a/src/deep.cpp
+++ b/src/deep.cpp
@@ -75,7 +75,7 @@ namespace {
75 lua_rawget(L_, -2); // L_: {} b 75 lua_rawget(L_, -2); // L_: {} b
76 } 76 }
77 lua_remove(L_, -2); // L_: a|b 77 lua_remove(L_, -2); // L_: a|b
78 LuaType const _type{ luaG_type(L_, kIdxTop) }; 78 LuaType const _type{ luaW_type(L_, kIdxTop) };
79 if (_type != LuaType::NIL && _type != expectedType_) { 79 if (_type != LuaType::NIL && _type != expectedType_) {
80 raise_luaL_error(L_, "INTERNAL ERROR: Unexpected value."); 80 raise_luaL_error(L_, "INTERNAL ERROR: Unexpected value.");
81 } 81 }
@@ -103,7 +103,7 @@ namespace {
103[[nodiscard]] 103[[nodiscard]]
104int DeepFactory::DeepGC(lua_State* const L_) 104int DeepFactory::DeepGC(lua_State* const L_)
105{ 105{
106 DeepPrelude* const* const _proxy{ luaG_tofulluserdata<DeepPrelude*>(L_, StackIndex{ 1 }) }; 106 DeepPrelude* const* const _proxy{ luaW_tofulluserdata<DeepPrelude*>(L_, StackIndex{ 1 }) };
107 DeepPrelude* const _p{ *_proxy }; 107 DeepPrelude* const _p{ *_proxy };
108 108
109 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded 109 // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded
@@ -150,7 +150,7 @@ DeepFactory* DeepFactory::LookupFactory(lua_State* const L_, StackIndex const in
150{ 150{
151 // when looking inside a keeper, we are 100% sure the object is a deep userdata 151 // when looking inside a keeper, we are 100% sure the object is a deep userdata
152 if (mode_ == LookupMode::FromKeeper) { 152 if (mode_ == LookupMode::FromKeeper) {
153 DeepPrelude* const _proxy{ *luaG_tofulluserdata<DeepPrelude*>(L_, index_) }; 153 DeepPrelude* const _proxy{ *luaW_tofulluserdata<DeepPrelude*>(L_, index_) };
154 // we can (and must) cast and fetch the internally stored factory 154 // we can (and must) cast and fetch the internally stored factory
155 return &_proxy->factory; 155 return &_proxy->factory;
156 } else { 156 } else {
@@ -167,7 +167,7 @@ DeepFactory* DeepFactory::LookupFactory(lua_State* const L_, StackIndex const in
167 // replace metatable with the factory pointer, if it is actually a deep userdata 167 // replace metatable with the factory pointer, if it is actually a deep userdata
168 LookupDeep(L_, LuaType::LIGHTUSERDATA); // L_: deep ... factory|nil 168 LookupDeep(L_, LuaType::LIGHTUSERDATA); // L_: deep ... factory|nil
169 169
170 DeepFactory* const _ret{ luaG_tolightuserdata<DeepFactory>(L_, kIdxTop) }; // nullptr if not a userdata 170 DeepFactory* const _ret{ luaW_tolightuserdata<DeepFactory>(L_, kIdxTop) }; // nullptr if not a userdata
171 lua_pop(L_, 1); 171 lua_pop(L_, 1);
172 STACK_CHECK(L_, 0); 172 STACK_CHECK(L_, 0);
173 return _ret; 173 return _ret;
@@ -190,7 +190,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_,
190 190
191 // Check if a proxy already exists 191 // Check if a proxy already exists
192 lua_pushlightuserdata(L_, prelude_); // L_: DPC deep 192 lua_pushlightuserdata(L_, prelude_); // L_: DPC deep
193 if (luaG_rawget(L_, StackIndex{ -2 }) != LuaType::NIL) { // L_: DPC proxy 193 if (luaW_rawget(L_, StackIndex{ -2 }) != LuaType::NIL) { // L_: DPC proxy
194 lua_remove(L_, -2); // L_: proxy 194 lua_remove(L_, -2); // L_: proxy
195 STACK_CHECK(L_, 1); 195 STACK_CHECK(L_, 1);
196 return; 196 return;
@@ -202,7 +202,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_,
202 STACK_GROW(L_, 7); 202 STACK_GROW(L_, 7);
203 203
204 // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) 204 // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4)
205 DeepPrelude** const _proxy{ luaG_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy 205 DeepPrelude** const _proxy{ luaW_newuserdatauv<DeepPrelude*>(L_, nuv_) }; // L_: DPC proxy
206 LUA_ASSERT(L_, _proxy); 206 LUA_ASSERT(L_, _proxy);
207 *_proxy = prelude_; 207 *_proxy = prelude_;
208 prelude_->refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data 208 prelude_->refcount.fetch_add(1, std::memory_order_relaxed); // one more proxy pointing to this deep data
@@ -223,7 +223,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_,
223 raise_luaL_error(errL_, "Bad DeepFactory::createMetatable overload: unexpected pushed value"); 223 raise_luaL_error(errL_, "Bad DeepFactory::createMetatable overload: unexpected pushed value");
224 } 224 }
225 // if the metatable contains a __gc, we will call it from our own 225 // if the metatable contains a __gc, we will call it from our own
226 std::ignore = luaG_rawgetfield(L_, kIdxTop, "__gc"); // L_: DPC proxy metatable __gc 226 std::ignore = luaW_rawgetfield(L_, kIdxTop, "__gc"); // L_: DPC proxy metatable __gc
227 } else { 227 } else {
228 // keepers need a minimal metatable that only contains our own __gc 228 // keepers need a minimal metatable that only contains our own __gc
229 lua_createtable(L_, 0, 1); // L_: DPC proxy metatable 229 lua_createtable(L_, 0, 1); // L_: DPC proxy metatable
@@ -251,8 +251,8 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_,
251 raise_luaL_error(errL_, "lanes receiving deep userdata should register the 'package' library"); 251 raise_luaL_error(errL_, "lanes receiving deep userdata should register the 'package' library");
252 } 252 }
253 253
254 luaG_pushstring(L_, _modname); // L_: DPC proxy metatable require() "module" 254 luaW_pushstring(L_, _modname); // L_: DPC proxy metatable require() "module"
255 if (luaG_getfield(L_, kIdxRegistry, LUA_LOADED_TABLE) != LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED 255 if (luaW_getfield(L_, kIdxRegistry, LUA_LOADED_TABLE) != LuaType::TABLE) { // L_: DPC proxy metatable require() "module" _R._LOADED
256 // no L.registry._LOADED; can this ever happen? 256 // no L.registry._LOADED; can this ever happen?
257 lua_pop(L_, 6); // L_: 257 lua_pop(L_, 6); // L_:
258 raise_luaL_error(errL_, "unexpected error while requiring a module identified by DeepFactory::moduleName"); 258 raise_luaL_error(errL_, "unexpected error while requiring a module identified by DeepFactory::moduleName");
@@ -270,7 +270,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_,
270 LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error? 270 LuaError const _require_result{ lua_pcall(L_, 1, 0, 0) }; // L_: DPC proxy metatable error?
271 if (_require_result != LuaError::OK) { 271 if (_require_result != LuaError::OK) {
272 // failed, raise the error in the proper state 272 // failed, raise the error in the proper state
273 raise_luaL_error(errL_, luaG_tostring(L_, kIdxTop)); 273 raise_luaL_error(errL_, luaW_tostring(L_, kIdxTop));
274 } 274 }
275 } 275 }
276 } else { // already loaded, we are happy 276 } else { // already loaded, we are happy
@@ -279,7 +279,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_,
279 } 279 }
280 } 280 }
281 STACK_CHECK(L_, 3); // L_: DPC proxy metatable 281 STACK_CHECK(L_, 3); // L_: DPC proxy metatable
282 LUA_ASSERT(L_, luaG_type(L_, StackIndex{ -2 }) == LuaType::USERDATA); 282 LUA_ASSERT(L_, luaW_type(L_, StackIndex{ -2 }) == LuaType::USERDATA);
283 LUA_ASSERT(L_, lua_istable(L_, -1)); 283 LUA_ASSERT(L_, lua_istable(L_, -1));
284 lua_setmetatable(L_, -2); // L_: DPC proxy 284 lua_setmetatable(L_, -2); // L_: DPC proxy
285 285
@@ -288,7 +288,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_,
288 lua_pushvalue(L_, -2); // L_: DPC proxy deep proxy 288 lua_pushvalue(L_, -2); // L_: DPC proxy deep proxy
289 lua_rawset(L_, -4); // L_: DPC proxy 289 lua_rawset(L_, -4); // L_: DPC proxy
290 lua_remove(L_, -2); // L_: proxy 290 lua_remove(L_, -2); // L_: proxy
291 LUA_ASSERT(L_, luaG_type(L_, kIdxTop) == LuaType::USERDATA); 291 LUA_ASSERT(L_, luaW_type(L_, kIdxTop) == LuaType::USERDATA);
292 STACK_CHECK(L_, 1); 292 STACK_CHECK(L_, 1);
293} 293}
294 294
@@ -305,7 +305,7 @@ void DeepFactory::PushDeepProxy(DestState const L_, DeepPrelude* const prelude_,
305 * Reference counting and true userdata proxying are taken care of for the actual data type. 305 * Reference counting and true userdata proxying are taken care of for the actual data type.
306 * 306 *
307 * Types using the deep userdata system (and only those!) can be passed between 307 * Types using the deep userdata system (and only those!) can be passed between
308 * separate Lua states via 'luaG_inter_move()'. 308 * separate Lua states via 'luaW_inter_move()'.
309 * 309 *
310 * Returns: 'proxy' userdata for accessing the deep data via 'DeepFactory::toDeep()' 310 * Returns: 'proxy' userdata for accessing the deep data via 'DeepFactory::toDeep()'
311 */ 311 */
@@ -382,7 +382,7 @@ DeepPrelude* DeepFactory::toDeep(lua_State* const L_, StackIndex const index_) c
382 } 382 }
383 STACK_CHECK(L_, 0); 383 STACK_CHECK(L_, 0);
384 384
385 DeepPrelude** const _proxy{ luaG_tofulluserdata<DeepPrelude*>(L_, index_) }; 385 DeepPrelude** const _proxy{ luaW_tofulluserdata<DeepPrelude*>(L_, index_) };
386 return *_proxy; 386 return *_proxy;
387} 387}
388 388
diff --git a/src/intercopycontext.cpp b/src/intercopycontext.cpp
index a93615b..6e9b66c 100644
--- a/src/intercopycontext.cpp
+++ b/src/intercopycontext.cpp
@@ -36,23 +36,6 @@ THE SOFTWARE.
36 36
37// ################################################################################################# 37// #################################################################################################
38 38
39// Lua 5.4.3 style of dumping (see lstrlib.c)
40// we have to do it that way because we can't unbalance the stack between buffer operations
41// namely, this means we can't push a function on top of the stack *after* we initialize the buffer!
42// luckily, this also works with earlier Lua versions
43[[nodiscard]]
44static int buf_writer(lua_State* L_, void const* b_, size_t size_, void* ud_)
45{
46 luaL_Buffer* const _B{ static_cast<luaL_Buffer*>(ud_) };
47 if (!_B->L) {
48 luaL_buffinit(L_, _B);
49 }
50 luaL_addlstring(_B, static_cast<char const*>(b_), size_);
51 return 0;
52}
53
54// #################################################################################################
55
56// function sentinel used to transfer native functions from/to keeper states 39// function sentinel used to transfer native functions from/to keeper states
57[[nodiscard]] 40[[nodiscard]]
58static int func_lookup_sentinel(lua_State* const L_) 41static int func_lookup_sentinel(lua_State* const L_)
@@ -93,7 +76,7 @@ static int userdata_lookup_sentinel(lua_State* const L_)
93[[nodiscard]] 76[[nodiscard]]
94std::string_view InterCopyContext::findLookupName() const 77std::string_view InterCopyContext::findLookupName() const
95{ 78{
96 LUA_ASSERT(L1, lua_isfunction(L1, L1_i) || lua_istable(L1, L1_i) || luaG_type(L1, L1_i) == LuaType::USERDATA); 79 LUA_ASSERT(L1, lua_isfunction(L1, L1_i) || lua_istable(L1, L1_i) || luaW_type(L1, L1_i) == LuaType::USERDATA);
97 STACK_CHECK_START_REL(L1, 0); // L1: ... v ... 80 STACK_CHECK_START_REL(L1, 0); // L1: ... v ...
98 STACK_GROW(L1, 3); // up to 3 slots are necessary on error 81 STACK_GROW(L1, 3); // up to 3 slots are necessary on error
99 if (mode == LookupMode::FromKeeper) { 82 if (mode == LookupMode::FromKeeper) {
@@ -114,7 +97,7 @@ std::string_view InterCopyContext::findLookupName() const
114 lua_pushvalue(L1, L1_i); // L1: ... v ... {} v 97 lua_pushvalue(L1, L1_i); // L1: ... v ... {} v
115 lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n" 98 lua_rawget(L1, -2); // L1: ... v ... {} "f.q.n"
116 } 99 }
117 std::string_view _fqn{ luaG_tostring(L1, kIdxTop) }; 100 std::string_view _fqn{ luaW_tostring(L1, kIdxTop) };
118 DEBUGSPEW_CODE(DebugSpew(U) << "function [C] " << _fqn << std::endl); 101 DEBUGSPEW_CODE(DebugSpew(U) << "function [C] " << _fqn << std::endl);
119 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database 102 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database
120 lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ... 103 lua_pop(L1, (mode == LookupMode::FromKeeper) ? 1 : 2); // L1: ... v ...
@@ -122,12 +105,12 @@ std::string_view InterCopyContext::findLookupName() const
122 if (_fqn.empty() && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function/userdata (but not for tables) 105 if (_fqn.empty() && !lua_istable(L1, L1_i)) { // raise an error if we try to send an unknown function/userdata (but not for tables)
123 // try to discover the name of the function/userdata we want to send 106 // try to discover the name of the function/userdata we want to send
124 kLaneNameRegKey.pushValue(L1); // L1: ... v ... lane_name 107 kLaneNameRegKey.pushValue(L1); // L1: ... v ... lane_name
125 std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; 108 std::string_view const _from{ luaW_tostring(L1, kIdxTop) };
126 lua_pushcfunction(L1, LG_nameof); // L1: ... v ... lane_name LG_nameof 109 lua_pushcfunction(L1, LG_nameof); // L1: ... v ... lane_name LG_nameof
127 lua_pushvalue(L1, L1_i); // L1: ... v ... lane_name LG_nameof t 110 lua_pushvalue(L1, L1_i); // L1: ... v ... lane_name LG_nameof t
128 lua_call(L1, 1, 2); // L1: ... v ... lane_name "type" "name"|nil 111 lua_call(L1, 1, 2); // L1: ... v ... lane_name "type" "name"|nil
129 StackIndex const _indexTypeWhat{ -2 }; 112 StackIndex const _indexTypeWhat{ -2 };
130 std::string_view const _typewhat{ (luaG_type(L1, _indexTypeWhat) == LuaType::STRING) ? luaG_tostring(L1, _indexTypeWhat) : luaG_typename(L1, _indexTypeWhat) }; 113 std::string_view const _typewhat{ (luaW_type(L1, _indexTypeWhat) == LuaType::STRING) ? luaW_tostring(L1, _indexTypeWhat) : luaW_typename(L1, _indexTypeWhat) };
131 // second return value can be nil if the table was not found 114 // second return value can be nil if the table was not found
132 // probable reason: the function was removed from the source Lua state before Lanes was required. 115 // probable reason: the function was removed from the source Lua state before Lanes was required.
133 std::string_view _what, _gotchaA, _gotchaB; 116 std::string_view _what, _gotchaA, _gotchaB;
@@ -139,7 +122,7 @@ std::string_view InterCopyContext::findLookupName() const
139 _gotchaA = ""; 122 _gotchaA = "";
140 _gotchaB = ""; 123 _gotchaB = "";
141 StackIndex const _indexWhat{ kIdxTop }; 124 StackIndex const _indexWhat{ kIdxTop };
142 _what = (luaG_type(L1, _indexWhat) == LuaType::STRING) ? luaG_tostring(L1, _indexWhat) : luaG_typename(L1, _indexWhat); 125 _what = (luaW_type(L1, _indexWhat) == LuaType::STRING) ? luaW_tostring(L1, _indexWhat) : luaW_typename(L1, _indexWhat);
143 } 126 }
144 raise_luaL_error(L1, "%s%s '%s' not found in %s origin transfer database.%s", _typewhat.data(), _gotchaA.data(), _what.data(), _from.empty() ? "main" : _from.data(), _gotchaB.data()); 127 raise_luaL_error(L1, "%s%s '%s' not found in %s origin transfer database.%s", _typewhat.data(), _gotchaA.data(), _what.data(), _from.empty() ? "main" : _from.data(), _gotchaB.data());
145 } 128 }
@@ -158,7 +141,7 @@ static constexpr RegistryUniqueKey kMtIdRegKey{ 0xA8895DCF4EC3FE3Cull };
158[[nodiscard]] 141[[nodiscard]]
159static lua_Integer get_mt_id(Universe* const U_, lua_State* const L_, StackIndex const idx_) 142static lua_Integer get_mt_id(Universe* const U_, lua_State* const L_, StackIndex const idx_)
160{ 143{
161 StackIndex const _absidx{ luaG_absindex(L_, idx_) }; 144 StackIndex const _absidx{ luaW_absindex(L_, idx_) };
162 145
163 STACK_GROW(L_, 3); 146 STACK_GROW(L_, 3);
164 147
@@ -195,11 +178,12 @@ static lua_Integer get_mt_id(Universe* const U_, lua_State* const L_, StackIndex
195// L2 has the cache key for this function at the top of the stack 178// L2 has the cache key for this function at the top of the stack
196void InterCopyContext::copyFunction() const 179void InterCopyContext::copyFunction() const
197{ 180{
198 LUA_ASSERT(L1, L2_cache_i != 0); // L2: ... {cache} ... p 181 LUA_ASSERT(L1, L2_cache_i != 0); // L1: ... f L2: ... {cache} ... p
199 STACK_GROW(L1, 2); 182 STACK_GROW(L1, 2);
200 STACK_CHECK_START_REL(L1, 0); 183 STACK_CHECK_START_REL(L1, 0);
184 STACK_CHECK_START_REL(L2, 0);
201 185
202 // 'luaG_dump()' needs the function at top of stack 186 // 'luaW_dump()' needs the function at top of stack
203 // if already on top of the stack, no need to push again 187 // if already on top of the stack, no need to push again
204 bool const _needToPush{ L1_i != lua_gettop(L1) }; 188 bool const _needToPush{ L1_i != lua_gettop(L1) };
205 if (_needToPush) { 189 if (_needToPush) {
@@ -211,19 +195,17 @@ void InterCopyContext::copyFunction() const
211 // to the writer" (and we only return 0) 195 // to the writer" (and we only return 0)
212 // not sure this could ever fail but for memory shortage reasons 196 // not sure this could ever fail but for memory shortage reasons
213 // last argument is Lua 5.4-specific (no stripping) 197 // last argument is Lua 5.4-specific (no stripping)
214 luaL_Buffer B{}; 198 tools::PushFunctionBytecode(L1, L2, U->stripFunctions); // L1: ... f L2: ... {cache} ... p "<bytecode>"
215 if (luaG_dump(L1, buf_writer, &B, U->stripFunctions) != 0) {
216 raise_luaL_error(getErrL(), "internal error: function dump failed.");
217 }
218 199
219 // pushes dumped string on 'L1' 200 // if pushed, we need to pop
220 luaL_pushresult(&B); // L1: ... f b
221
222 // if not pushed, no need to pop
223 if (_needToPush) { 201 if (_needToPush) {
224 lua_remove(L1, -2); // L1: ... b 202 lua_pop(L1, 1); // L1: ...
225 } 203 }
226 204
205 // When we are done, the stack of L1 should be the original one, with the bytecode string added on top of L2
206 STACK_CHECK(L1, 0);
207 STACK_CHECK(L2, 1);
208
227 // transfer the bytecode, then the upvalues, to create a similar closure 209 // transfer the bytecode, then the upvalues, to create a similar closure
228 { 210 {
229 char const* _fname{}; 211 char const* _fname{};
@@ -231,16 +213,16 @@ void InterCopyContext::copyFunction() const
231 if constexpr (LOG_FUNC_INFO) 213 if constexpr (LOG_FUNC_INFO)
232 { 214 {
233 lua_Debug _ar; 215 lua_Debug _ar;
234 lua_pushvalue(L1, L1_i); // L1: ... b f 216 lua_pushvalue(L1, L1_i); // L1: ... f
235 // "To get information about a function you push it onto the stack and start the what string with the character '>'." 217 // "To get information about a function you push it onto the stack and start the what string with the character '>'."
236 // fills 'fname' 'namewhat' and 'linedefined', pops function 218 // fills 'fname' 'namewhat' and 'linedefined', pops function
237 lua_getinfo(L1, ">nS", &_ar); // L1: ... b 219 lua_getinfo(L1, ">nS", &_ar); // L1: ...
238 _fname = _ar.namewhat; 220 _fname = _ar.namewhat;
239 DEBUGSPEW_CODE(DebugSpew(U) << "FNAME: " << _ar.short_src << " @ " << _ar.linedefined << std::endl); 221 DEBUGSPEW_CODE(DebugSpew(U) << "FNAME: " << _ar.short_src << " @ " << _ar.linedefined << std::endl);
240 } 222 }
241 223
242 { 224 {
243 std::string_view const _bytecode{ luaG_tostring(L1, kIdxTop) }; // L1: ... b 225 std::string_view const _bytecode{ luaW_tostring(L2, kIdxTop) }; // L2: ... {cache} ... p "<bytecode>"
244 LUA_ASSERT(L1, !_bytecode.empty()); 226 LUA_ASSERT(L1, !_bytecode.empty());
245 STACK_GROW(L2, 2); 227 STACK_GROW(L2, 2);
246 // Note: Line numbers seem to be taken precisely from the 228 // Note: Line numbers seem to be taken precisely from the
@@ -249,15 +231,15 @@ void InterCopyContext::copyFunction() const
249 // 231 //
250 // TBD: Can we get the function's original name through, as well? 232 // TBD: Can we get the function's original name through, as well?
251 // 233 //
252 if (luaL_loadbuffer(L2, _bytecode.data(), _bytecode.size(), _fname) != 0) { // L2: ... {cache} ... p function 234 if (luaL_loadbuffer(L2, _bytecode.data(), _bytecode.size(), _fname) != 0) { // L2: ... {cache} ... p "<bytecode>" function
253 // chunk is precompiled so only LUA_ERRMEM can happen 235 // chunk is precompiled so only LUA_ERRMEM can happen
254 // "Otherwise, it pushes an error message" 236 // "Otherwise, it pushes an error message"
255 // 237 //
256 STACK_GROW(L1, 1); 238 STACK_GROW(L1, 1);
257 raise_luaL_error(getErrL(), "%s: %s", _fname, lua_tostring(L2, -1)); 239 raise_luaL_error(getErrL(), "%s: %s", _fname, lua_tostring(L2, kIdxTop));
258 } 240 }
259 // remove the dumped string 241 // remove the dumped string
260 lua_pop(L1, 1); // ... 242 lua_replace(L2, -2); // L2: ... {cache} ... p function
261 // now set the cache as soon as we can. 243 // now set the cache as soon as we can.
262 // this is necessary if one of the function's upvalues references it indirectly 244 // this is necessary if one of the function's upvalues references it indirectly
263 // we need to find it in the cache even if it isn't fully transfered yet 245 // we need to find it in the cache even if it isn't fully transfered yet
@@ -267,6 +249,7 @@ void InterCopyContext::copyFunction() const
267 lua_rawset(L2, L2_cache_i); // L2: ... {cache} ... function 249 lua_rawset(L2, L2_cache_i); // L2: ... {cache} ... function
268 } 250 }
269 STACK_CHECK(L1, 0); 251 STACK_CHECK(L1, 0);
252 STACK_CHECK(L2, 0); // cache key is replaced by the function, so no stack level change
270 253
271 /* push over any upvalues; references to this function will come from 254 /* push over any upvalues; references to this function will come from
272 * cache so we don't end up in eternal loop. 255 * cache so we don't end up in eternal loop.
@@ -278,12 +261,12 @@ void InterCopyContext::copyFunction() const
278 { 261 {
279 InterCopyContext _c{ U, L2, L1, L2_cache_i, {}, VT::NORMAL, mode, {} }; 262 InterCopyContext _c{ U, L2, L1, L2_cache_i, {}, VT::NORMAL, mode, {} };
280 // if we encounter an upvalue equal to the global table in the source, bind it to the destination's global table 263 // if we encounter an upvalue equal to the global table in the source, bind it to the destination's global table
281 luaG_pushglobaltable(L1); // L1: ... _G 264 luaW_pushglobaltable(L1); // L1: ... _G
282 for (char const* _upname{}; (_upname = lua_getupvalue(L1, L1_i, 1 + _n)); ++_n) { // L1: ... _G up[n] 265 for (char const* _upname{}; (_upname = lua_getupvalue(L1, L1_i, 1 + _n)); ++_n) { // L1: ... _G up[n]
283 DEBUGSPEW_CODE(DebugSpew(U) << "UPNAME[" << _n << "]: " << _c.name << " -> "); 266 DEBUGSPEW_CODE(DebugSpew(U) << "UPNAME[" << _n << "]: " << _c.name << " -> ");
284 if (lua_rawequal(L1, -1, -2)) { // is the upvalue equal to the global table? 267 if (lua_rawequal(L1, -1, -2)) { // is the upvalue equal to the global table?
285 DEBUGSPEW_CODE(DebugSpew(nullptr) << "pushing destination global scope" << std::endl); 268 DEBUGSPEW_CODE(DebugSpew(nullptr) << "pushing destination global scope" << std::endl);
286 luaG_pushglobaltable(L2); // L2: ... {cache} ... function <upvalues> 269 luaW_pushglobaltable(L2); // L2: ... {cache} ... function <upvalues>
287 } else { 270 } else {
288 DEBUGSPEW_CODE(DebugSpew(nullptr) << "copying value" << std::endl); 271 DEBUGSPEW_CODE(DebugSpew(nullptr) << "copying value" << std::endl);
289 _c.name = _upname; 272 _c.name = _upname;
@@ -297,6 +280,7 @@ void InterCopyContext::copyFunction() const
297 lua_pop(L1, 1); // L1: ... 280 lua_pop(L1, 1); // L1: ...
298 } // L2: ... {cache} ... function + 'n' upvalues (>=0) 281 } // L2: ... {cache} ... function + 'n' upvalues (>=0)
299 STACK_CHECK(L1, 0); 282 STACK_CHECK(L1, 0);
283 STACK_CHECK(L2, _n);
300 284
301 // Set upvalues (originally set to 'nil' by 'lua_load') 285 // Set upvalues (originally set to 'nil' by 'lua_load')
302 for (StackIndex const _func_index{ lua_gettop(L2) - _n }; _n > 0; --_n) { 286 for (StackIndex const _func_index{ lua_gettop(L2) - _n }; _n > 0; --_n) {
@@ -307,6 +291,7 @@ void InterCopyContext::copyFunction() const
307 // once all upvalues have been set we are left 291 // once all upvalues have been set we are left
308 // with the function at the top of the stack // L2: ... {cache} ... function 292 // with the function at the top of the stack // L2: ... {cache} ... function
309 } 293 }
294 STACK_CHECK(L2, 0);
310 STACK_CHECK(L1, 0); 295 STACK_CHECK(L1, 0);
311} 296}
312 297
@@ -327,7 +312,7 @@ void InterCopyContext::lookupNativeFunction() const
327 312
328 case LookupMode::ToKeeper: 313 case LookupMode::ToKeeper:
329 // push a sentinel closure that holds the lookup name as upvalue 314 // push a sentinel closure that holds the lookup name as upvalue
330 luaG_pushstring(L2, _fqn); // L1: ... f ... L2: "f.q.n" 315 luaW_pushstring(L2, _fqn); // L1: ... f ... L2: "f.q.n"
331 lua_pushcclosure(L2, func_lookup_sentinel, 1); // L1: ... f ... L2: f 316 lua_pushcclosure(L2, func_lookup_sentinel, 1); // L1: ... f ... L2: f
332 break; 317 break;
333 318
@@ -336,16 +321,16 @@ void InterCopyContext::lookupNativeFunction() const
336 kLookupRegKey.pushValue(L2); // L1: ... f ... L2: {} 321 kLookupRegKey.pushValue(L2); // L1: ... f ... L2: {}
337 STACK_CHECK(L2, 1); 322 STACK_CHECK(L2, 1);
338 LUA_ASSERT(L1, lua_istable(L2, -1)); 323 LUA_ASSERT(L1, lua_istable(L2, -1));
339 luaG_pushstring(L2, _fqn); // L1: ... f ... L2: {} "f.q.n" 324 luaW_pushstring(L2, _fqn); // L1: ... f ... L2: {} "f.q.n"
340 LuaType const _objType{ luaG_rawget(L2, StackIndex{ -2 }) }; // L1: ... f ... L2: {} f 325 LuaType const _objType{ luaW_rawget(L2, StackIndex{ -2 }) }; // L1: ... f ... L2: {} f
341 // nil means we don't know how to transfer stuff: user should do something 326 // nil means we don't know how to transfer stuff: user should do something
342 // anything other than function or table should not happen! 327 // anything other than function or table should not happen!
343 if (_objType != LuaType::FUNCTION && _objType != LuaType::TABLE && _objType != LuaType::USERDATA) { 328 if (_objType != LuaType::FUNCTION && _objType != LuaType::TABLE && _objType != LuaType::USERDATA) {
344 kLaneNameRegKey.pushValue(L1); // L1: ... f ... lane_name 329 kLaneNameRegKey.pushValue(L1); // L1: ... f ... lane_name
345 std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; 330 std::string_view const _from{ luaW_tostring(L1, kIdxTop) };
346 lua_pop(L1, 1); // L1: ... f ... 331 lua_pop(L1, 1); // L1: ... f ...
347 kLaneNameRegKey.pushValue(L2); // L1: ... f ... L2: {} f lane_name 332 kLaneNameRegKey.pushValue(L2); // L1: ... f ... L2: {} f lane_name
348 std::string_view const _to{ luaG_tostring(L2, kIdxTop) }; 333 std::string_view const _to{ luaW_tostring(L2, kIdxTop) };
349 lua_pop(L2, 1); // L2: {} f 334 lua_pop(L2, 1); // L2: {} f
350 raise_luaL_error( 335 raise_luaL_error(
351 getErrL(), 336 getErrL(),
@@ -368,7 +353,7 @@ void InterCopyContext::lookupNativeFunction() const
368// Always pushes a function to 'L2'. 353// Always pushes a function to 'L2'.
369void InterCopyContext::copyCachedFunction() const 354void InterCopyContext::copyCachedFunction() const
370{ 355{
371 FuncSubType const _funcSubType{ luaG_getfuncsubtype(L1, L1_i) }; 356 FuncSubType const _funcSubType{ luaW_getfuncsubtype(L1, L1_i) };
372 if (_funcSubType == FuncSubType::Bytecode) { 357 if (_funcSubType == FuncSubType::Bytecode) {
373 void* const _aspointer{ const_cast<void*>(lua_topointer(L1, L1_i)) }; 358 void* const _aspointer{ const_cast<void*>(lua_topointer(L1, L1_i)) };
374 // TODO: Merge this and same code for tables 359 // TODO: Merge this and same code for tables
@@ -386,10 +371,10 @@ void InterCopyContext::copyCachedFunction() const
386 // push a light userdata uniquely representing the function 371 // push a light userdata uniquely representing the function
387 lua_pushlightuserdata(L2, _aspointer); // L2: ... {cache} ... p 372 lua_pushlightuserdata(L2, _aspointer); // L2: ... {cache} ... p
388 373
389 //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << luaG_tostring(L2, -1) << " >>" << std::endl); 374 //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << luaW_tostring(L2, -1) << " >>" << std::endl);
390 375
391 lua_pushvalue(L2, -1); // L2: ... {cache} ... p p 376 lua_pushvalue(L2, -1); // L2: ... {cache} ... p p
392 if (luaG_rawget(L2, L2_cache_i) == LuaType::NIL) { // function is unknown // L2: ... {cache} ... p function|nil|true 377 if (luaW_rawget(L2, L2_cache_i) == LuaType::NIL) { // function is unknown // L2: ... {cache} ... p function|nil|true
393 lua_pop(L2, 1); // L2: ... {cache} ... p 378 lua_pop(L2, 1); // L2: ... {cache} ... p
394 379
395 // Set to 'true' for the duration of creation; need to find self-references 380 // Set to 'true' for the duration of creation; need to find self-references
@@ -405,7 +390,7 @@ void InterCopyContext::copyCachedFunction() const
405 } else { // function is native/LuaJIT: no need to cache 390 } else { // function is native/LuaJIT: no need to cache
406 lookupNativeFunction(); // L2: ... {cache} ... function 391 lookupNativeFunction(); // L2: ... {cache} ... function
407 // if the function was in fact a lookup sentinel, we can either get a function, table or full userdata here 392 // if the function was in fact a lookup sentinel, we can either get a function, table or full userdata here
408 LUA_ASSERT(L1, lua_isfunction(L2, kIdxTop) || lua_istable(L2, kIdxTop) || luaG_type(L2, kIdxTop) == LuaType::USERDATA); 393 LUA_ASSERT(L1, lua_isfunction(L2, kIdxTop) || lua_istable(L2, kIdxTop) || luaW_type(L2, kIdxTop) == LuaType::USERDATA);
409 } 394 }
410} 395}
411 396
@@ -430,7 +415,7 @@ bool InterCopyContext::lookupTable() const
430 415
431 case LookupMode::ToKeeper: 416 case LookupMode::ToKeeper:
432 // push a sentinel closure that holds the lookup name as upvalue 417 // push a sentinel closure that holds the lookup name as upvalue
433 luaG_pushstring(L2, _fqn); // L1: ... t ... L2: "f.q.n" 418 luaW_pushstring(L2, _fqn); // L1: ... t ... L2: "f.q.n"
434 lua_pushcclosure(L2, table_lookup_sentinel, 1); // L1: ... t ... L2: f 419 lua_pushcclosure(L2, table_lookup_sentinel, 1); // L1: ... t ... L2: f
435 break; 420 break;
436 421
@@ -439,26 +424,26 @@ bool InterCopyContext::lookupTable() const
439 kLookupRegKey.pushValue(L2); // L1: ... t ... L2: {} 424 kLookupRegKey.pushValue(L2); // L1: ... t ... L2: {}
440 STACK_CHECK(L2, 1); 425 STACK_CHECK(L2, 1);
441 LUA_ASSERT(L1, lua_istable(L2, -1)); 426 LUA_ASSERT(L1, lua_istable(L2, -1));
442 luaG_pushstring(L2, _fqn); // L2: {} "f.q.n" 427 luaW_pushstring(L2, _fqn); // L2: {} "f.q.n"
443 // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead) 428 // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead)
444 // but not when we extract something out of a keeper, as there is nothing to clone! 429 // but not when we extract something out of a keeper, as there is nothing to clone!
445 if (luaG_rawget(L2, StackIndex{ -2 }) == LuaType::NIL && mode == LookupMode::LaneBody) { // L2: {} t 430 if (luaW_rawget(L2, StackIndex{ -2 }) == LuaType::NIL && mode == LookupMode::LaneBody) { // L2: {} t
446 lua_pop(L2, 2); // L1: ... t ... L2: 431 lua_pop(L2, 2); // L1: ... t ... L2:
447 STACK_CHECK(L2, 0); 432 STACK_CHECK(L2, 0);
448 return false; 433 return false;
449 } else if (!lua_istable(L2, -1)) { // this can happen if someone decides to replace same already registered item (for a example a standard lib function) with a table 434 } else if (!lua_istable(L2, -1)) { // this can happen if someone decides to replace same already registered item (for a example a standard lib function) with a table
450 kLaneNameRegKey.pushValue(L1); // L1: ... t ... lane_name 435 kLaneNameRegKey.pushValue(L1); // L1: ... t ... lane_name
451 std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; 436 std::string_view const _from{ luaW_tostring(L1, kIdxTop) };
452 lua_pop(L1, 1); // L1: ... t ... 437 lua_pop(L1, 1); // L1: ... t ...
453 kLaneNameRegKey.pushValue(L2); // L1: ... t ... L2: {} t lane_name 438 kLaneNameRegKey.pushValue(L2); // L1: ... t ... L2: {} t lane_name
454 std::string_view const _to{ luaG_tostring(L2, kIdxTop) }; 439 std::string_view const _to{ luaW_tostring(L2, kIdxTop) };
455 lua_pop(L2, 1); // L1: ... t ... L2: {} t 440 lua_pop(L2, 1); // L1: ... t ... L2: {} t
456 raise_luaL_error( 441 raise_luaL_error(
457 getErrL(), 442 getErrL(),
458 "%s: source table '%s' found as %s in %s destination transfer database.", 443 "%s: source table '%s' found as %s in %s destination transfer database.",
459 _from.empty() ? "main" : _from.data(), 444 _from.empty() ? "main" : _from.data(),
460 _fqn.data(), 445 _fqn.data(),
461 luaG_typename(L2, kIdxTop).data(), 446 luaW_typename(L2, kIdxTop).data(),
462 _to.empty() ? "main" : _to.data()); 447 _to.empty() ? "main" : _to.data());
463 } 448 }
464 lua_remove(L2, -2); // L1: ... t ... L2: t 449 lua_remove(L2, -2); // L1: ... t ... L2: t
@@ -487,8 +472,8 @@ void InterCopyContext::interCopyKeyValuePair() const
487 char* _valPath{ nullptr }; 472 char* _valPath{ nullptr };
488 if (U->verboseErrors) { 473 if (U->verboseErrors) {
489 // for debug purposes, let's try to build a useful name 474 // for debug purposes, let's try to build a useful name
490 if (luaG_type(L1, _key_i) == LuaType::STRING) { 475 if (luaW_type(L1, _key_i) == LuaType::STRING) {
491 std::string_view const _key{ luaG_tostring(L1, _key_i) }; 476 std::string_view const _key{ luaW_tostring(L1, _key_i) };
492 size_t const _bufLen{ name.size() + _key.size() + 2 }; // +2 for separator dot and terminating 0 477 size_t const _bufLen{ name.size() + _key.size() + 2 }; // +2 for separator dot and terminating 0
493 _valPath = static_cast<char*>(alloca(_bufLen)); 478 _valPath = static_cast<char*>(alloca(_bufLen));
494 sprintf(_valPath, "%s." STRINGVIEW_FMT, name.data(), (int) _key.size(), _key.data()); 479 sprintf(_valPath, "%s." STRINGVIEW_FMT, name.data(), (int) _key.size(), _key.data());
@@ -500,15 +485,15 @@ void InterCopyContext::interCopyKeyValuePair() const
500 sprintf(_valPath, "%s[" LUA_INTEGER_FMT "]", name.data(), key); 485 sprintf(_valPath, "%s[" LUA_INTEGER_FMT "]", name.data(), key);
501 } 486 }
502#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503 487#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503
503 else if (luaG_type(L1, _key_i) == LuaType::NUMBER) { 488 else if (luaW_type(L1, _key_i) == LuaType::NUMBER) {
504 lua_Number const key{ lua_tonumber(L1, _key_i) }; 489 lua_Number const key{ lua_tonumber(L1, _key_i) };
505 _valPath = (char*) alloca(name.size() + 32 + 3); // +3 for [] and terminating 0 490 _valPath = (char*) alloca(name.size() + 32 + 3); // +3 for [] and terminating 0
506 sprintf(_valPath, "%s[" LUA_NUMBER_FMT "]", name.data(), key); 491 sprintf(_valPath, "%s[" LUA_NUMBER_FMT "]", name.data(), key);
507 } else if (luaG_type(L1, _key_i) == LuaType::LIGHTUSERDATA) { 492 } else if (luaW_type(L1, _key_i) == LuaType::LIGHTUSERDATA) {
508 void* const _key{ lua_touserdata(L1, _key_i) }; 493 void* const _key{ lua_touserdata(L1, _key_i) };
509 _valPath = (char*) alloca(name.size() + 16 + 5); // +5 for [U:] and terminating 0 494 _valPath = (char*) alloca(name.size() + 16 + 5); // +5 for [U:] and terminating 0
510 sprintf(_valPath, "%s[U:%p]", name.data(), _key); 495 sprintf(_valPath, "%s[U:%p]", name.data(), _key);
511 } else if (luaG_type(L1, _key_i) == LuaType::BOOLEAN) { 496 } else if (luaW_type(L1, _key_i) == LuaType::BOOLEAN) {
512 int const _key{ lua_toboolean(L1, _key_i) }; 497 int const _key{ lua_toboolean(L1, _key_i) };
513 _valPath = (char*) alloca(name.size() + 8); // +8 for [], 'false' and terminating 0 498 _valPath = (char*) alloca(name.size() + 8); // +8 for [], 'false' and terminating 0
514 sprintf(_valPath, "%s[%s]", name.data(), _key ? "true" : "false"); 499 sprintf(_valPath, "%s[%s]", name.data(), _key ? "true" : "false");
@@ -532,7 +517,7 @@ LuaType InterCopyContext::processConversion() const
532{ 517{
533 static constexpr int kPODmask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING); 518 static constexpr int kPODmask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING);
534 519
535 LuaType _val_type{ luaG_type(L1, L1_i) }; 520 LuaType _val_type{ luaW_type(L1, L1_i) };
536 521
537 STACK_CHECK_START_REL(L1, 0); 522 STACK_CHECK_START_REL(L1, 0);
538 523
@@ -548,7 +533,7 @@ LuaType InterCopyContext::processConversion() const
548 } 533 }
549 // we have a metatable // L1: ... mt 534 // we have a metatable // L1: ... mt
550 static constexpr std::string_view kConvertField{ "__lanesconvert" }; 535 static constexpr std::string_view kConvertField{ "__lanesconvert" };
551 LuaType const _converterType{ luaG_getfield(L1, kIdxTop, kConvertField) }; // L1: ... mt kConvertField 536 LuaType const _converterType{ luaW_getfield(L1, kIdxTop, kConvertField) }; // L1: ... mt kConvertField
552 switch (_converterType) { 537 switch (_converterType) {
553 case LuaType::NIL: 538 case LuaType::NIL:
554 // no __lanesconvert, nothing to do 539 // no __lanesconvert, nothing to do
@@ -557,18 +542,18 @@ LuaType InterCopyContext::processConversion() const
557 542
558 case LuaType::LIGHTUSERDATA: 543 case LuaType::LIGHTUSERDATA:
559 if (kNilSentinel.equals(L1, kIdxTop)) { 544 if (kNilSentinel.equals(L1, kIdxTop)) {
560 DEBUGSPEW_CODE(DebugSpew(U) << "converted " << luaG_typename(L1, _val_type) << " to nil" << std::endl); 545 DEBUGSPEW_CODE(DebugSpew(U) << "converted " << luaW_typename(L1, _val_type) << " to nil" << std::endl);
561 lua_replace(L1, L1_i); // L1: ... mt 546 lua_replace(L1, L1_i); // L1: ... mt
562 lua_pop(L1, 1); // L1: ... 547 lua_pop(L1, 1); // L1: ...
563 _val_type = _converterType; 548 _val_type = _converterType;
564 } else { 549 } else {
565 raise_luaL_error(getErrL(), "Invalid %s type %s", kConvertField.data(), luaG_typename(L1, _converterType).data()); 550 raise_luaL_error(getErrL(), "Invalid %s type %s", kConvertField.data(), luaW_typename(L1, _converterType).data());
566 } 551 }
567 break; 552 break;
568 553
569 case LuaType::STRING: 554 case LuaType::STRING:
570 // kConvertField == "decay" -> replace source value with it's pointer 555 // kConvertField == "decay" -> replace source value with it's pointer
571 if (std::string_view const _mode{ luaG_tostring(L1, kIdxTop) }; _mode == "decay") { 556 if (std::string_view const _mode{ luaW_tostring(L1, kIdxTop) }; _mode == "decay") {
572 lua_pop(L1, 1); // L1: ... mt 557 lua_pop(L1, 1); // L1: ... mt
573 lua_pushlightuserdata(L1, const_cast<void*>(lua_topointer(L1, L1_i))); // L1: ... mt decayed 558 lua_pushlightuserdata(L1, const_cast<void*>(lua_topointer(L1, L1_i))); // L1: ... mt decayed
574 lua_replace(L1, L1_i); // L1: ... mt 559 lua_replace(L1, L1_i); // L1: ... mt
@@ -581,18 +566,18 @@ LuaType InterCopyContext::processConversion() const
581 566
582 case LuaType::FUNCTION: 567 case LuaType::FUNCTION:
583 lua_pushvalue(L1, L1_i); // L1: ... mt kConvertField val 568 lua_pushvalue(L1, L1_i); // L1: ... mt kConvertField val
584 luaG_pushstring(L1, mode == LookupMode::ToKeeper ? "keeper" : "regular"); // L1: ... mt kConvertField val string 569 luaW_pushstring(L1, mode == LookupMode::ToKeeper ? "keeper" : "regular"); // L1: ... mt kConvertField val string
585 lua_call(L1, 2, 1); // val:kConvertField(str) -> result // L1: ... mt kConvertField converted 570 lua_call(L1, 2, 1); // val:kConvertField(str) -> result // L1: ... mt kConvertField converted
586 lua_replace(L1, L1_i); // L1: ... mt 571 lua_replace(L1, L1_i); // L1: ... mt
587 lua_pop(L1, 1); // L1: ... mt 572 lua_pop(L1, 1); // L1: ... mt
588 _val_type = luaG_type(L1, L1_i); 573 _val_type = luaW_type(L1, L1_i);
589 break; 574 break;
590 575
591 default: 576 default:
592 raise_luaL_error(getErrL(), "Invalid %s type %s", kConvertField.data(), luaG_typename(L1, _converterType).data()); 577 raise_luaL_error(getErrL(), "Invalid %s type %s", kConvertField.data(), luaW_typename(L1, _converterType).data());
593 } 578 }
594 STACK_CHECK(L1, 0); 579 STACK_CHECK(L1, 0);
595 LUA_ASSERT(getErrL(), luaG_type(L1, L1_i) == _val_type); 580 LUA_ASSERT(getErrL(), luaW_type(L1, L1_i) == _val_type);
596 return _val_type; 581 return _val_type;
597} 582}
598 583
@@ -615,7 +600,7 @@ bool InterCopyContext::pushCachedMetatable() const
615 // do we already know this metatable? 600 // do we already know this metatable?
616 std::ignore = kMtIdRegKey.getSubTable(L2, NArr{ 0 }, NRec{ 0 }); // L2: _R[kMtIdRegKey] 601 std::ignore = kMtIdRegKey.getSubTable(L2, NArr{ 0 }, NRec{ 0 }); // L2: _R[kMtIdRegKey]
617 lua_pushinteger(L2, _mt_id); // L2: _R[kMtIdRegKey] id 602 lua_pushinteger(L2, _mt_id); // L2: _R[kMtIdRegKey] id
618 if (luaG_rawget(L2, StackIndex{ -2 }) == LuaType::NIL) { // L2 did not know the metatable // L2: _R[kMtIdRegKey] mt|nil 603 if (luaW_rawget(L2, StackIndex{ -2 }) == LuaType::NIL) { // L2 did not know the metatable // L2: _R[kMtIdRegKey] mt|nil
619 lua_pop(L2, 1); // L2: _R[kMtIdRegKey] 604 lua_pop(L2, 1); // L2: _R[kMtIdRegKey]
620 InterCopyContext const _c{ U, L2, L1, L2_cache_i, SourceIndex{ lua_gettop(L1) }, VT::METATABLE, mode, name }; 605 InterCopyContext const _c{ U, L2, L1, L2_cache_i, SourceIndex{ lua_gettop(L1) }, VT::METATABLE, mode, name };
621 if (_c.interCopyOne() != InterCopyResult::Success) { // L2: _R[kMtIdRegKey] mt? 606 if (_c.interCopyOne() != InterCopyResult::Success) { // L2: _R[kMtIdRegKey] mt?
@@ -662,9 +647,9 @@ bool InterCopyContext::pushCachedTable() const
662 // push a light userdata uniquely representing the table 647 // push a light userdata uniquely representing the table
663 lua_pushlightuserdata(L2, const_cast<void*>(_p)); // L1: ... t ... L2: ... p 648 lua_pushlightuserdata(L2, const_cast<void*>(_p)); // L1: ... t ... L2: ... p
664 649
665 //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << luaG_tostring(L2, -1) << " >>" << std::endl); 650 //DEBUGSPEW_CODE(DebugSpew(U) << "<< ID: " << luaW_tostring(L2, -1) << " >>" << std::endl);
666 651
667 bool const _not_found_in_cache{ luaG_rawget(L2, L2_cache_i) == LuaType::NIL }; // L1: ... t ... L2: ... {cached|nil} 652 bool const _not_found_in_cache{ luaW_rawget(L2, L2_cache_i) == LuaType::NIL }; // L1: ... t ... L2: ... {cached|nil}
668 if (_not_found_in_cache) { 653 if (_not_found_in_cache) {
669 // create a new entry in the cache 654 // create a new entry in the cache
670 lua_pop(L2, 1); // L1: ... t ... L2: ... 655 lua_pop(L2, 1); // L1: ... t ... L2: ...
@@ -696,7 +681,7 @@ bool InterCopyContext::lookupUserdata() const
696 681
697 case LookupMode::ToKeeper: 682 case LookupMode::ToKeeper:
698 // push a sentinel closure that holds the lookup name as upvalue 683 // push a sentinel closure that holds the lookup name as upvalue
699 luaG_pushstring(L2, _fqn); // L1: ... f ... L2: "f.q.n" 684 luaW_pushstring(L2, _fqn); // L1: ... f ... L2: "f.q.n"
700 lua_pushcclosure(L2, userdata_lookup_sentinel, 1); // L1: ... f ... L2: f 685 lua_pushcclosure(L2, userdata_lookup_sentinel, 1); // L1: ... f ... L2: f
701 break; 686 break;
702 687
@@ -705,16 +690,16 @@ bool InterCopyContext::lookupUserdata() const
705 kLookupRegKey.pushValue(L2); // L1: ... f ... L2: {} 690 kLookupRegKey.pushValue(L2); // L1: ... f ... L2: {}
706 STACK_CHECK(L2, 1); 691 STACK_CHECK(L2, 1);
707 LUA_ASSERT(L1, lua_istable(L2, -1)); 692 LUA_ASSERT(L1, lua_istable(L2, -1));
708 luaG_pushstring(L2, _fqn); // L1: ... f ... L2: {} "f.q.n" 693 luaW_pushstring(L2, _fqn); // L1: ... f ... L2: {} "f.q.n"
709 LuaType const _type{ luaG_rawget(L2, StackIndex{ -2 }) }; // L1: ... f ... L2: {} f 694 LuaType const _type{ luaW_rawget(L2, StackIndex{ -2 }) }; // L1: ... f ... L2: {} f
710 // nil means we don't know how to transfer stuff: user should do something 695 // nil means we don't know how to transfer stuff: user should do something
711 // anything other than function or table should not happen! 696 // anything other than function or table should not happen!
712 if (_type != LuaType::FUNCTION && _type != LuaType::TABLE) { 697 if (_type != LuaType::FUNCTION && _type != LuaType::TABLE) {
713 kLaneNameRegKey.pushValue(L1); // L1: ... f ... lane_name 698 kLaneNameRegKey.pushValue(L1); // L1: ... f ... lane_name
714 std::string_view const _from{ luaG_tostring(L1, kIdxTop) }; 699 std::string_view const _from{ luaW_tostring(L1, kIdxTop) };
715 lua_pop(L1, 1); // L1: ... f ... 700 lua_pop(L1, 1); // L1: ... f ...
716 kLaneNameRegKey.pushValue(L2); // L1: ... f ... L2: {} f lane_name 701 kLaneNameRegKey.pushValue(L2); // L1: ... f ... L2: {} f lane_name
717 std::string_view const _to{ luaG_tostring(L2, kIdxTop) }; 702 std::string_view const _to{ luaW_tostring(L2, kIdxTop) };
718 lua_pop(L2, 1); // L2: {} f 703 lua_pop(L2, 1); // L2: {} f
719 raise_luaL_error( 704 raise_luaL_error(
720 getErrL(), 705 getErrL(),
@@ -736,7 +721,7 @@ bool InterCopyContext::lookupUserdata() const
736[[nodiscard]] 721[[nodiscard]]
737bool InterCopyContext::tryCopyClonable() const 722bool InterCopyContext::tryCopyClonable() const
738{ 723{
739 SourceIndex const _L1_i{ luaG_absindex(L1, L1_i).value() }; 724 SourceIndex const _L1_i{ luaW_absindex(L1, L1_i).value() };
740 void* const _source{ lua_touserdata(L1, _L1_i) }; 725 void* const _source{ lua_touserdata(L1, _L1_i) };
741 726
742 STACK_CHECK_START_REL(L1, 0); 727 STACK_CHECK_START_REL(L1, 0);
@@ -744,7 +729,7 @@ bool InterCopyContext::tryCopyClonable() const
744 729
745 // Check if the source was already cloned during this copy 730 // Check if the source was already cloned during this copy
746 lua_pushlightuserdata(L2, _source); // L2: ... source 731 lua_pushlightuserdata(L2, _source); // L2: ... source
747 if (luaG_rawget(L2, L2_cache_i) != LuaType::NIL) { // L2: ... clone? 732 if (luaW_rawget(L2, L2_cache_i) != LuaType::NIL) { // L2: ... clone?
748 STACK_CHECK(L2, 1); 733 STACK_CHECK(L2, 1);
749 return true; 734 return true;
750 } else { 735 } else {
@@ -759,7 +744,7 @@ bool InterCopyContext::tryCopyClonable() const
759 } 744 }
760 745
761 // no __lanesclone? -> not clonable 746 // no __lanesclone? -> not clonable
762 if (luaG_getfield(L1, kIdxTop, "__lanesclone") == LuaType::NIL) { // L1: ... mt nil 747 if (luaW_getfield(L1, kIdxTop, "__lanesclone") == LuaType::NIL) { // L1: ... mt nil
763 lua_pop(L1, 2); // L1: ... 748 lua_pop(L1, 2); // L1: ...
764 STACK_CHECK(L1, 0); 749 STACK_CHECK(L1, 0);
765 return false; 750 return false;
@@ -769,10 +754,10 @@ bool InterCopyContext::tryCopyClonable() const
769 754
770 // we need to copy over the uservalues of the userdata as well 755 // we need to copy over the uservalues of the userdata as well
771 { 756 {
772 StackIndex const _mt{ luaG_absindex(L1, StackIndex{ -2 }) }; // L1: ... mt __lanesclone 757 StackIndex const _mt{ luaW_absindex(L1, StackIndex{ -2 }) }; // L1: ... mt __lanesclone
773 auto const userdata_size{ static_cast<size_t>(lua_rawlen(L1, _L1_i)) }; // make 32-bits builds happy 758 auto const userdata_size{ static_cast<size_t>(lua_rawlen(L1, _L1_i)) }; // make 32-bits builds happy
774 // extract all the uservalues, but don't transfer them yet 759 // extract all the uservalues, but don't transfer them yet
775 UserValueCount const _nuv{ luaG_getalluservalues(L1, _L1_i) }; // L1: ... mt __lanesclone [uv]* 760 UserValueCount const _nuv{ luaW_getalluservalues(L1, _L1_i) }; // L1: ... mt __lanesclone [uv]*
776 // create the clone userdata with the required number of uservalue slots 761 // create the clone userdata with the required number of uservalue slots
777 void* const _clone{ lua_newuserdatauv(L2, userdata_size, _nuv) }; // L2: ... u 762 void* const _clone{ lua_newuserdatauv(L2, userdata_size, _nuv) }; // L2: ... u
778 // copy the metatable in the target state, and give it to the clone we put there 763 // copy the metatable in the target state, and give it to the clone we put there
@@ -804,7 +789,7 @@ bool InterCopyContext::tryCopyClonable() const
804 // assign uservalues 789 // assign uservalues
805 UserValueIndex _uvi{ _nuv.value() }; 790 UserValueIndex _uvi{ _nuv.value() };
806 while (_uvi > 0) { 791 while (_uvi > 0) {
807 _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop).value() }; 792 _c.L1_i = SourceIndex{ luaW_absindex(L1, kIdxTop).value() };
808 if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... u uv 793 if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... u uv
809 raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); 794 raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1));
810 } 795 }
@@ -850,10 +835,10 @@ bool InterCopyContext::tryCopyDeep() const
850 STACK_CHECK_START_REL(L2, 0); 835 STACK_CHECK_START_REL(L2, 0);
851 836
852 // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail 837 // extract all uservalues of the source. unfortunately, the only way to know their count is to iterate until we fail
853 UserValueCount const _nuv{ luaG_getalluservalues(L1, L1_i) }; // L1: ... deep ... [uv]* 838 UserValueCount const _nuv{ luaW_getalluservalues(L1, L1_i) }; // L1: ... deep ... [uv]*
854 STACK_CHECK(L1, _nuv); 839 STACK_CHECK(L1, _nuv);
855 840
856 DeepPrelude* const _deep{ *luaG_tofulluserdata<DeepPrelude*>(L1, L1_i) }; 841 DeepPrelude* const _deep{ *luaW_tofulluserdata<DeepPrelude*>(L1, L1_i) };
857 DeepFactory::PushDeepProxy(L2, _deep, _nuv, mode, getErrL()); // L1: ... deep ... [uv]* L2: deep 842 DeepFactory::PushDeepProxy(L2, _deep, _nuv, mode, getErrL()); // L1: ... deep ... [uv]* L2: deep
858 843
859 // transfer all uservalues of the source in the destination 844 // transfer all uservalues of the source in the destination
@@ -863,7 +848,7 @@ bool InterCopyContext::tryCopyDeep() const
863 STACK_GROW(L2, _nuv); 848 STACK_GROW(L2, _nuv);
864 UserValueIndex _uvi{ _nuv.value() }; 849 UserValueIndex _uvi{ _nuv.value() };
865 while (_uvi) { 850 while (_uvi) {
866 _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop).value() }; 851 _c.L1_i = SourceIndex{ luaW_absindex(L1, kIdxTop).value() };
867 if (_c.interCopyOne() != InterCopyResult::Success) { // L1: ... deep ... [uv]* L2: deep uv 852 if (_c.interCopyOne() != InterCopyResult::Success) { // L1: ... deep ... [uv]* L2: deep uv
868 raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); 853 raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1));
869 } 854 }
@@ -911,7 +896,7 @@ bool InterCopyContext::interCopyFunction() const
911 lua_getupvalue(L1, L1_i, 2); // L1: ... u 896 lua_getupvalue(L1, L1_i, 2); // L1: ... u
912 void* _source{ lua_touserdata(L1, -1) }; 897 void* _source{ lua_touserdata(L1, -1) };
913 lua_pushlightuserdata(L2, _source); // L2: ... source 898 lua_pushlightuserdata(L2, _source); // L2: ... source
914 if (luaG_rawget(L2, L2_cache_i) != LuaType::NIL) { // L2: ... u? 899 if (luaW_rawget(L2, L2_cache_i) != LuaType::NIL) { // L2: ... u?
915 lua_pop(L1, 1); // L1: ... 900 lua_pop(L1, 1); // L1: ...
916 STACK_CHECK(L1, 0); 901 STACK_CHECK(L1, 0);
917 STACK_CHECK(L2, 1); 902 STACK_CHECK(L2, 1);
@@ -933,7 +918,7 @@ bool InterCopyContext::interCopyFunction() const
933 auto const _userdata_size{ static_cast<size_t>(lua_rawlen(L1, kIdxTop)) }; // make 32-bits builds happy 918 auto const _userdata_size{ static_cast<size_t>(lua_rawlen(L1, kIdxTop)) }; // make 32-bits builds happy
934 { 919 {
935 // extract uservalues (don't transfer them yet) 920 // extract uservalues (don't transfer them yet)
936 UserValueCount const _nuv{ luaG_getalluservalues(L1, source_i) }; // L1: ... u [uv]* 921 UserValueCount const _nuv{ luaW_getalluservalues(L1, source_i) }; // L1: ... u [uv]*
937 STACK_CHECK(L1, _nuv + 1); 922 STACK_CHECK(L1, _nuv + 1);
938 // create the clone userdata with the required number of uservalue slots 923 // create the clone userdata with the required number of uservalue slots
939 _clone = lua_newuserdatauv(L2, _userdata_size, _nuv); // L2: ... mt u 924 _clone = lua_newuserdatauv(L2, _userdata_size, _nuv); // L2: ... mt u
@@ -948,7 +933,7 @@ bool InterCopyContext::interCopyFunction() const
948 InterCopyContext _c{ *this }; 933 InterCopyContext _c{ *this };
949 UserValueIndex _uvi{ _nuv.value() }; 934 UserValueIndex _uvi{ _nuv.value() };
950 while (_uvi > 0) { 935 while (_uvi > 0) {
951 _c.L1_i = SourceIndex{ luaG_absindex(L1, kIdxTop).value() }; 936 _c.L1_i = SourceIndex{ luaW_absindex(L1, kIdxTop).value() };
952 if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... mt u uv 937 if (_c.interCopyOne() != InterCopyResult::Success) { // L2: ... mt u uv
953 raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1)); 938 raise_luaL_error(getErrL(), "Cannot copy upvalue type '%s'", luaL_typename(L1, -1));
954 } 939 }
@@ -965,9 +950,9 @@ bool InterCopyContext::interCopyFunction() const
965 // perform the custom cloning part 950 // perform the custom cloning part
966 lua_insert(L2, -2); // L2: ... u mt 951 lua_insert(L2, -2); // L2: ... u mt
967 // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with 952 // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with
968 LuaType const _funcType{ luaG_getfield(L2, kIdxTop, "__lanesclone") }; // L2: ... u mt __lanesclone 953 LuaType const _funcType{ luaW_getfield(L2, kIdxTop, "__lanesclone") }; // L2: ... u mt __lanesclone
969 if (_funcType != LuaType::FUNCTION) { 954 if (_funcType != LuaType::FUNCTION) {
970 raise_luaL_error(getErrL(), "INTERNAL ERROR: __lanesclone is a %s, not a function", luaG_typename(L2, _funcType).data()); 955 raise_luaL_error(getErrL(), "INTERNAL ERROR: __lanesclone is a %s, not a function", luaW_typename(L2, _funcType).data());
971 } 956 }
972 lua_remove(L2, -2); // L2: ... u __lanesclone 957 lua_remove(L2, -2); // L2: ... u __lanesclone
973 lua_pushlightuserdata(L2, _clone); // L2: ... u __lanesclone clone 958 lua_pushlightuserdata(L2, _clone); // L2: ... u __lanesclone clone
@@ -1060,9 +1045,9 @@ bool InterCopyContext::interCopyNumber() const
1060[[nodiscard]] 1045[[nodiscard]]
1061bool InterCopyContext::interCopyString() const 1046bool InterCopyContext::interCopyString() const
1062{ 1047{
1063 std::string_view const _s{ luaG_tostring(L1, L1_i) }; 1048 std::string_view const _s{ luaW_tostring(L1, L1_i) };
1064 DEBUGSPEW_CODE(DebugSpew(nullptr) << "'" << _s << "'" << std::endl); 1049 DEBUGSPEW_CODE(DebugSpew(nullptr) << "'" << _s << "'" << std::endl);
1065 luaG_pushstring(L2, _s); 1050 luaW_pushstring(L2, _s);
1066 return true; 1051 return true;
1067} 1052}
1068 1053
@@ -1154,7 +1139,7 @@ bool InterCopyContext::interCopyUserdata() const
1154 1139
1155 // Last, let's try to see if this userdata is special (aka is it some userdata that we registered in our lookup databases during module registration?) 1140 // Last, let's try to see if this userdata is special (aka is it some userdata that we registered in our lookup databases during module registration?)
1156 if (lookupUserdata()) { 1141 if (lookupUserdata()) {
1157 LUA_ASSERT(L1, luaG_type(L2, kIdxTop) == LuaType::USERDATA || (lua_tocfunction(L2, kIdxTop) == userdata_lookup_sentinel)); // from lookup data. can also be userdata_lookup_sentinel if this is a userdata we know 1142 LUA_ASSERT(L1, luaW_type(L2, kIdxTop) == LuaType::USERDATA || (lua_tocfunction(L2, kIdxTop) == userdata_lookup_sentinel)); // from lookup data. can also be userdata_lookup_sentinel if this is a userdata we know
1158 return true; 1143 return true;
1159 } 1144 }
1160 1145
@@ -1291,8 +1276,8 @@ InterCopyResult InterCopyContext::interCopyPackage() const
1291 } const _onExit{ L2 }; 1276 } const _onExit{ L2 };
1292 1277
1293 STACK_CHECK_START_REL(L1, 0); 1278 STACK_CHECK_START_REL(L1, 0);
1294 if (luaG_type(L1, L1_i) != LuaType::TABLE) { 1279 if (luaW_type(L1, L1_i) != LuaType::TABLE) {
1295 std::string_view const _msg{ luaG_pushstring(L1, "expected package as table, got a %s", luaL_typename(L1, L1_i)) }; 1280 std::string_view const _msg{ luaW_pushstring(L1, "expected package as table, got a %s", luaL_typename(L1, L1_i)) };
1296 STACK_CHECK(L1, 1); 1281 STACK_CHECK(L1, 1);
1297 // raise the error when copying from lane to lane, else just leave it on the stack to be raised later 1282 // raise the error when copying from lane to lane, else just leave it on the stack to be raised later
1298 if (mode == LookupMode::LaneBody) { 1283 if (mode == LookupMode::LaneBody) {
@@ -1300,7 +1285,7 @@ InterCopyResult InterCopyContext::interCopyPackage() const
1300 } 1285 }
1301 return InterCopyResult::Error; 1286 return InterCopyResult::Error;
1302 } 1287 }
1303 if (luaG_getmodule(L2, LUA_LOADLIBNAME) == LuaType::NIL) { // package library not loaded: do nothing 1288 if (luaW_getmodule(L2, LUA_LOADLIBNAME) == LuaType::NIL) { // package library not loaded: do nothing
1304 DEBUGSPEW_CODE(DebugSpew(U) << "'package' not loaded, nothing to do" << std::endl); 1289 DEBUGSPEW_CODE(DebugSpew(U) << "'package' not loaded, nothing to do" << std::endl);
1305 STACK_CHECK(L1, 0); 1290 STACK_CHECK(L1, 0);
1306 return InterCopyResult::Success; 1291 return InterCopyResult::Success;
@@ -1317,7 +1302,7 @@ InterCopyResult InterCopyContext::interCopyPackage() const
1317 continue; 1302 continue;
1318 } 1303 }
1319 DEBUGSPEW_CODE(DebugSpew(U) << "package." << _entry << std::endl); 1304 DEBUGSPEW_CODE(DebugSpew(U) << "package." << _entry << std::endl);
1320 if (luaG_getfield(L1, L1_i, _entry) == LuaType::NIL) { 1305 if (luaW_getfield(L1, L1_i, _entry) == LuaType::NIL) {
1321 lua_pop(L1, 1); 1306 lua_pop(L1, 1);
1322 } else { 1307 } else {
1323 { 1308 {
@@ -1328,9 +1313,9 @@ InterCopyResult InterCopyContext::interCopyPackage() const
1328 STACK_CHECK(L1, 0); 1313 STACK_CHECK(L1, 0);
1329 } 1314 }
1330 if (_result == InterCopyResult::Success) { 1315 if (_result == InterCopyResult::Success) {
1331 luaG_setfield(L2, StackIndex{ -2 }, _entry); // set package[entry] 1316 luaW_setfield(L2, StackIndex{ -2 }, _entry); // set package[entry]
1332 } else { 1317 } else {
1333 std::string_view const _msg{ luaG_pushstring(L1, "failed to copy package.%s", _entry.data()) }; 1318 std::string_view const _msg{ luaW_pushstring(L1, "failed to copy package.%s", _entry.data()) };
1334 // raise the error when copying from lane to lane, else just leave it on the stack to be raised later 1319 // raise the error when copying from lane to lane, else just leave it on the stack to be raised later
1335 if (mode == LookupMode::LaneBody) { 1320 if (mode == LookupMode::LaneBody) {
1336 raise_luaL_error(getErrL(), _msg); 1321 raise_luaL_error(getErrL(), _msg);
diff --git a/src/keeper.cpp b/src/keeper.cpp
index c8c470f..4af0d86 100644
--- a/src/keeper.cpp
+++ b/src/keeper.cpp
@@ -77,7 +77,7 @@ class KeyUD final
77 77
78 // a fifo full userdata has one uservalue, the table that holds the actual fifo contents 78 // a fifo full userdata has one uservalue, the table that holds the actual fifo contents
79 [[nodiscard]] 79 [[nodiscard]]
80 static void* operator new([[maybe_unused]] size_t size_, KeeperState L_) noexcept { return luaG_newuserdatauv<KeyUD>(L_, UserValueCount{ 1 }); } 80 static void* operator new([[maybe_unused]] size_t size_, KeeperState L_) noexcept { return luaW_newuserdatauv<KeyUD>(L_, UserValueCount{ 1 }); }
81 // always embedded somewhere else or "in-place constructed" as a full userdata 81 // always embedded somewhere else or "in-place constructed" as a full userdata
82 // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception 82 // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception
83 static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] KeeperState L_) { LUA_ASSERT(L_, !"should never be called"); } 83 static void operator delete([[maybe_unused]] void* p_, [[maybe_unused]] KeeperState L_) { LUA_ASSERT(L_, !"should never be called"); }
@@ -104,6 +104,7 @@ class KeyUD final
104 104
105// ################################################################################################# 105// #################################################################################################
106 106
107[[nodiscard]]
107bool KeyUD::changeLimit(LindaLimit const limit_) 108bool KeyUD::changeLimit(LindaLimit const limit_)
108{ 109{
109 bool const _newSlackAvailable{ 110 bool const _newSlackAvailable{
@@ -127,6 +128,7 @@ LindaRestrict KeyUD::changeRestrict(LindaRestrict const restrict_)
127 128
128// in: nothing 129// in: nothing
129// out: { first = 1, count = 0, limit = -1} 130// out: { first = 1, count = 0, limit = -1}
131[[nodiscard]]
130KeyUD* KeyUD::Create(KeeperState const K_) 132KeyUD* KeyUD::Create(KeeperState const K_)
131{ 133{
132 STACK_GROW(K_, 2); 134 STACK_GROW(K_, 2);
@@ -141,9 +143,10 @@ KeyUD* KeyUD::Create(KeeperState const K_)
141 143
142// ################################################################################################# 144// #################################################################################################
143 145
146[[nodiscard]]
144KeyUD* KeyUD::GetPtr(KeeperState const K_, StackIndex const idx_) 147KeyUD* KeyUD::GetPtr(KeeperState const K_, StackIndex const idx_)
145{ 148{
146 return luaG_tofulluserdata<KeyUD>(K_, idx_); 149 return luaW_tofulluserdata<KeyUD>(K_, idx_);
147} 150}
148 151
149// ################################################################################################# 152// #################################################################################################
@@ -181,6 +184,7 @@ void KeyUD::peek(KeeperState const K_, int const count_) const
181 184
182// in: fifo 185// in: fifo
183// out: remove the fifo table from the stack, push as many items as required on the stack (function assumes they exist in sufficient number) 186// out: remove the fifo table from the stack, push as many items as required on the stack (function assumes they exist in sufficient number)
187[[nodiscard]]
184int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_) 188int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_)
185{ 189{
186 if (count < minCount_) { 190 if (count < minCount_) {
@@ -191,23 +195,33 @@ int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_)
191 int const _popCount{ std::min(count, maxCount_) }; 195 int const _popCount{ std::min(count, maxCount_) };
192 LUA_ASSERT(K_, KeyUD::GetPtr(K_, kIdxTop) == this); // K_: ... this 196 LUA_ASSERT(K_, KeyUD::GetPtr(K_, kIdxTop) == this); // K_: ... this
193 prepareAccess(K_, kIdxTop); // K_: ... fifo 197 prepareAccess(K_, kIdxTop); // K_: ... fifo
198
199 STACK_CHECK_START_REL(K_, 0);
194 StackIndex const _fifo_idx{ lua_gettop(K_) }; 200 StackIndex const _fifo_idx{ lua_gettop(K_) };
195 // each iteration pushes a value on the stack! 201 // each iteration pushes a value on the stack!
196 STACK_GROW(K_, _popCount + 2); 202 STACK_GROW(K_, _popCount + 2);
197 // skip first item, we will push it last 203
198 for (int const _i : std::ranges::iota_view{ 1, _popCount }) { 204 // remove an element from fifo sequence and push it on the stack
205 auto _extractFifoItem = [K = K_, first = first, fifo_idx = lua_gettop(K_)](int const _i)
206 {
207 STACK_CHECK_START_REL(K, 0);
199 int const _at{ first + _i }; 208 int const _at{ first + _i };
200 // push item on the stack 209 // push item on the stack
201 lua_rawgeti(K_, _fifo_idx, _at); // K_: ... fifo val 210 lua_rawgeti(K, fifo_idx, _at); // K_: ... fifo val
202 // remove item from the fifo 211 // remove item from the fifo
203 lua_pushnil(K_); // K_: ... fifo val nil 212 lua_pushnil(K); // K_: ... fifo val nil
204 lua_rawseti(K_, _fifo_idx, _at); // K_: ... fifo val 213 lua_rawseti(K, fifo_idx, _at); // K_: ... fifo val
214 STACK_CHECK(K, 1);
215 };
216
217 // skip first item, we will push it last to avoid shifting the whole stack when removing 'fifo'
218 for (int const _i : std::ranges::iota_view{ 1, _popCount }) {
219 _extractFifoItem(_i); // K_: ... fifo val1...valN
205 } 220 }
206 // now process first item 221 // now process first item
207 lua_rawgeti(K_, _fifo_idx, first); // K_: ... fifo vals val 222 _extractFifoItem(0); // K_: ... fifo val1...valN val0
208 lua_pushnil(K_); // K_: ... fifo vals val nil 223 STACK_CHECK(K_, _popCount);
209 lua_rawseti(K_, _fifo_idx, first); // K_: ... fifo vals val 224 lua_replace(K_, _fifo_idx); // K_: ... val0...valN
210 lua_replace(K_, _fifo_idx); // K_: ... vals
211 225
212 // avoid ever-growing indexes by resetting each time we detect the fifo is empty 226 // avoid ever-growing indexes by resetting each time we detect the fifo is empty
213 int const _new_count{ count - _popCount }; 227 int const _new_count{ count - _popCount };
@@ -222,7 +236,7 @@ int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_)
222// replaces it by its uservalue on the stack (the table holding the fifo values) 236// replaces it by its uservalue on the stack (the table holding the fifo values)
223void KeyUD::prepareAccess(KeeperState const K_, StackIndex const idx_) const 237void KeyUD::prepareAccess(KeeperState const K_, StackIndex const idx_) const
224{ 238{
225 StackIndex const _idx{ luaG_absindex(K_, idx_) }; 239 StackIndex const _idx{ luaW_absindex(K_, idx_) };
226 LUA_ASSERT(K_, KeyUD::GetPtr(K_, idx_) == this); 240 LUA_ASSERT(K_, KeyUD::GetPtr(K_, idx_) == this);
227 // we can replace the key userdata in the stack without fear of it being GCed, there are other references around 241 // we can replace the key userdata in the stack without fear of it being GCed, there are other references around
228 lua_getiuservalue(K_, _idx, kContentsTableIndex); 242 lua_getiuservalue(K_, _idx, kContentsTableIndex);
@@ -233,9 +247,10 @@ void KeyUD::prepareAccess(KeeperState const K_, StackIndex const idx_) const
233 247
234// in: expect this val... on top of the stack 248// in: expect this val... on top of the stack
235// out: nothing, removes all pushed values from the stack 249// out: nothing, removes all pushed values from the stack
250[[nodiscard]]
236bool KeyUD::push(KeeperState const K_, int const count_, bool const enforceLimit_) 251bool KeyUD::push(KeeperState const K_, int const count_, bool const enforceLimit_)
237{ 252{
238 StackIndex const _fifoIdx{ luaG_absindex(K_, StackIndex{ -1 - count_ }) }; 253 StackIndex const _fifoIdx{ luaW_absindex(K_, StackIndex{ -1 - count_ }) };
239 LUA_ASSERT(K_, KeyUD::GetPtr(K_, _fifoIdx) == this); // K_: this val... 254 LUA_ASSERT(K_, KeyUD::GetPtr(K_, _fifoIdx) == this); // K_: this val...
240 if (enforceLimit_ && (limit >= 0) && (count + count_ > limit)) { // not enough room 255 if (enforceLimit_ && (limit >= 0) && (count + count_ > limit)) { // not enough room
241 return false; 256 return false;
@@ -259,16 +274,16 @@ bool KeyUD::push(KeeperState const K_, int const count_, bool const enforceLimit
259void KeyUD::pushFillStatus(KeeperState const K_) const 274void KeyUD::pushFillStatus(KeeperState const K_) const
260{ 275{
261 if (limit < 0) { 276 if (limit < 0) {
262 luaG_pushstring(K_, kUnder); 277 luaW_pushstring(K_, kUnder);
263 return; 278 return;
264 } 279 }
265 int const _delta{limit - count}; 280 int const _delta{ limit - count };
266 if (_delta < 0) { 281 if (_delta < 0) {
267 luaG_pushstring(K_, kOver); 282 luaW_pushstring(K_, kOver);
268 } else if (_delta > 0) { 283 } else if (_delta > 0) {
269 luaG_pushstring(K_, kUnder); 284 luaW_pushstring(K_, kUnder);
270 } else { 285 } else {
271 luaG_pushstring(K_, kExact); 286 luaW_pushstring(K_, kExact);
272 } 287 }
273} 288}
274 289
@@ -279,13 +294,16 @@ void KeyUD::PushFillStatus(KeeperState const K_, KeyUD const* const key_)
279 if (key_) { 294 if (key_) {
280 key_->pushFillStatus(K_); // _K: ... <fill status> 295 key_->pushFillStatus(K_); // _K: ... <fill status>
281 } else { 296 } else {
282 luaG_pushstring(K_, KeyUD::kUnder); // _K: ... "under" 297 luaW_pushstring(K_, KeyUD::kUnder); // _K: ... "under"
283 } 298 }
284} 299}
285 300
286// ################################################################################################# 301// #################################################################################################
287 302
288// expects 'this' on top of the stack 303// in: expects 'this' on top of the stack
304// out: nothing
305// returns true if the channel was full
306[[nodiscard]]
289bool KeyUD::reset(KeeperState const K_) 307bool KeyUD::reset(KeeperState const K_)
290{ 308{
291 LUA_ASSERT(K_, KeyUD::GetPtr(K_, kIdxTop) == this); 309 LUA_ASSERT(K_, KeyUD::GetPtr(K_, kIdxTop) == this);
@@ -312,10 +330,10 @@ static void PushKeysDB(KeeperState const K_, StackIndex const idx_)
312{ 330{
313 STACK_GROW(K_, 5); 331 STACK_GROW(K_, 5);
314 STACK_CHECK_START_REL(K_, 0); 332 STACK_CHECK_START_REL(K_, 0);
315 StackIndex const _absidx{ luaG_absindex(K_, idx_) }; 333 StackIndex const _absidx{ luaW_absindex(K_, idx_) };
316 kLindasRegKey.pushValue(K_); // K_: ... LindasDB 334 kLindasRegKey.pushValue(K_); // K_: ... LindasDB
317 lua_pushvalue(K_, _absidx); // K_: ... LindasDB linda 335 lua_pushvalue(K_, _absidx); // K_: ... LindasDB linda
318 if (luaG_rawget(K_, StackIndex{ -2 }) == LuaType::NIL) { // K_: ... LindasDB KeysDB 336 if (luaW_rawget(K_, StackIndex{ -2 }) == LuaType::NIL) { // K_: ... LindasDB KeysDB
319 lua_pop(K_, 1); // K_: ... LindasDB 337 lua_pop(K_, 1); // K_: ... LindasDB
320 // add a new KeysDB table for this linda 338 // add a new KeysDB table for this linda
321 lua_newtable(K_); // K_: ... LindasDB KeysDB 339 lua_newtable(K_); // K_: ... LindasDB KeysDB
@@ -337,6 +355,7 @@ static void PushKeysDB(KeeperState const K_, StackIndex const idx_)
337 355
338// in: linda 356// in: linda
339// out: nothing 357// out: nothing
358[[nodiscard]]
340int keepercall_collectgarbage(lua_State* const L_) 359int keepercall_collectgarbage(lua_State* const L_)
341{ 360{
342 lua_gc(L_, LUA_GCCOLLECT, 0); 361 lua_gc(L_, LUA_GCCOLLECT, 0);
@@ -346,6 +365,7 @@ int keepercall_collectgarbage(lua_State* const L_)
346// ################################################################################################# 365// #################################################################################################
347 366
348// in: linda [, key [, ...]] 367// in: linda [, key [, ...]]
368[[nodiscard]]
349int keepercall_count(lua_State* const L_) 369int keepercall_count(lua_State* const L_)
350{ 370{
351 KeeperState const _K{ L_ }; 371 KeeperState const _K{ L_ };
@@ -370,7 +390,7 @@ int keepercall_count(lua_State* const L_)
370 case 2: // _K: linda key 390 case 2: // _K: linda key
371 PushKeysDB(_K, StackIndex{ 1 }); // _K: linda key KeysDB 391 PushKeysDB(_K, StackIndex{ 1 }); // _K: linda key KeysDB
372 lua_replace(_K, 1); // _K: KeysDB key 392 lua_replace(_K, 1); // _K: KeysDB key
373 if (luaG_rawget(_K, StackIndex{ -2 }) == LuaType::NIL) { // the key is unknown // _K: KeysDB KeyUD|nil 393 if (luaW_rawget(_K, StackIndex{ -2 }) == LuaType::NIL) { // the key is unknown // _K: KeysDB KeyUD|nil
374 lua_remove(_K, -2); // _K: nil 394 lua_remove(_K, -2); // _K: nil
375 } else { // the key is known // _K: KeysDB KeyUD 395 } else { // the key is known // _K: KeysDB KeyUD
376 KeyUD* const _key{ KeyUD::GetPtr(_K, kIdxTop) }; 396 KeyUD* const _key{ KeyUD::GetPtr(_K, kIdxTop) };
@@ -409,6 +429,7 @@ int keepercall_count(lua_State* const L_)
409 429
410// in: linda 430// in: linda
411// not part of the linda public API, only used for cleanup at linda GC 431// not part of the linda public API, only used for cleanup at linda GC
432[[nodiscard]]
412int keepercall_destruct(lua_State* const L_) 433int keepercall_destruct(lua_State* const L_)
413{ 434{
414 STACK_GROW(L_, 3); 435 STACK_GROW(L_, 3);
@@ -427,6 +448,7 @@ int keepercall_destruct(lua_State* const L_)
427 448
428// in: linda_ud key [count] 449// in: linda_ud key [count]
429// out: N <N values>|kRestrictedChannel 450// out: N <N values>|kRestrictedChannel
451[[nodiscard]]
430int keepercall_get(lua_State* const L_) 452int keepercall_get(lua_State* const L_)
431{ 453{
432 KeeperState const _K{ L_ }; 454 KeeperState const _K{ L_ };
@@ -461,6 +483,7 @@ int keepercall_get(lua_State* const L_)
461 483
462// in: linda key [n|nil] 484// in: linda key [n|nil]
463// out: boolean, <fill status: string> 485// out: boolean, <fill status: string>
486[[nodiscard]]
464int keepercall_limit(lua_State* const L_) 487int keepercall_limit(lua_State* const L_)
465{ 488{
466 KeeperState const _K{ L_ }; 489 KeeperState const _K{ L_ };
@@ -480,7 +503,7 @@ int keepercall_limit(lua_State* const L_)
480 if (_key && _key->limit >= 0) { 503 if (_key && _key->limit >= 0) {
481 lua_pushinteger(_K, _key->limit); // _K: limit 504 lua_pushinteger(_K, _key->limit); // _K: limit
482 } else { // if the key doesn't exist, it is unlimited by default 505 } else { // if the key doesn't exist, it is unlimited by default
483 luaG_pushstring(_K, "unlimited"); // _K: "unlimited" 506 luaW_pushstring(_K, "unlimited"); // _K: "unlimited"
484 } 507 }
485 // return a single value: the limit of the key 508 // return a single value: the limit of the key
486 } else { 509 } else {
@@ -504,6 +527,7 @@ int keepercall_limit(lua_State* const L_)
504 527
505// in: linda, key [, key]? 528// in: linda, key [, key]?
506// out: (key, val) or nothing 529// out: (key, val) or nothing
530[[nodiscard]]
507int keepercall_receive(lua_State* const L_) 531int keepercall_receive(lua_State* const L_)
508{ 532{
509 KeeperState const _K{ L_ }; 533 KeeperState const _K{ L_ };
@@ -548,6 +572,7 @@ int keepercall_receive(lua_State* const L_)
548// ################################################################################################# 572// #################################################################################################
549 573
550// in: linda key mincount [maxcount] 574// in: linda key mincount [maxcount]
575[[nodiscard]]
551int keepercall_receive_batched(lua_State* const L_) 576int keepercall_receive_batched(lua_State* const L_)
552{ 577{
553 KeeperState const _K{ L_ }; 578 KeeperState const _K{ L_ };
@@ -581,6 +606,7 @@ int keepercall_receive_batched(lua_State* const L_)
581 606
582// in: linda key [mode] 607// in: linda key [mode]
583// out: mode 608// out: mode
609[[nodiscard]]
584int keepercall_restrict(lua_State* const L_) 610int keepercall_restrict(lua_State* const L_)
585{ 611{
586 KeeperState const _K{ L_ }; 612 KeeperState const _K{ L_ };
@@ -591,7 +617,7 @@ int keepercall_restrict(lua_State* const L_)
591 if (_reading) { 617 if (_reading) {
592 return LindaRestrict::None; 618 return LindaRestrict::None;
593 } 619 }
594 std::string_view const _val{ luaG_tostring(_K, StackIndex{ 3 }) }; 620 std::string_view const _val{ luaW_tostring(_K, StackIndex{ 3 }) };
595 if (_val == "set/get") { 621 if (_val == "set/get") {
596 return LindaRestrict::SetGet; 622 return LindaRestrict::SetGet;
597 } 623 }
@@ -623,7 +649,7 @@ int keepercall_restrict(lua_State* const L_)
623 lua_settop(_K, 0); // _K: 649 lua_settop(_K, 0); // _K:
624 auto const _prevRstrct{ _key ? _key->restrict : LindaRestrict::None }; 650 auto const _prevRstrct{ _key ? _key->restrict : LindaRestrict::None };
625 // return a single value: the restrict mode of the key 651 // return a single value: the restrict mode of the key
626 luaG_pushstring(_K, _encodeRestrict(_prevRstrct)); // _K: _previous 652 luaW_pushstring(_K, _encodeRestrict(_prevRstrct)); // _K: _previous
627 } else { 653 } else {
628 if (_key == nullptr) { // _K: KeysDB key nil 654 if (_key == nullptr) { // _K: KeysDB key nil
629 lua_pop(_K, 1); // _K: KeysDB key 655 lua_pop(_K, 1); // _K: KeysDB key
@@ -635,7 +661,7 @@ int keepercall_restrict(lua_State* const L_)
635 // return true if we decide that blocked threads waiting to write on that key should be awakened 661 // return true if we decide that blocked threads waiting to write on that key should be awakened
636 // this is the case if we detect the key was full but it is no longer the case 662 // this is the case if we detect the key was full but it is no longer the case
637 LindaRestrict const _previous{ _key->changeRestrict(_rstrct) }; 663 LindaRestrict const _previous{ _key->changeRestrict(_rstrct) };
638 luaG_pushstring(_K, _encodeRestrict(_previous)); // _K: _previous 664 luaW_pushstring(_K, _encodeRestrict(_previous)); // _K: _previous
639 } 665 }
640 STACK_CHECK(_K, 1); 666 STACK_CHECK(_K, 1);
641 return 1; 667 return 1;
@@ -645,6 +671,7 @@ int keepercall_restrict(lua_State* const L_)
645 671
646// in: linda, key, ... 672// in: linda, key, ...
647// out: true|false|kRestrictedChannel 673// out: true|false|kRestrictedChannel
674[[nodiscard]]
648int keepercall_send(lua_State* const L_) 675int keepercall_send(lua_State* const L_)
649{ 676{
650 KeeperState const _K{ L_ }; 677 KeeperState const _K{ L_ };
@@ -653,7 +680,7 @@ int keepercall_send(lua_State* const L_)
653 PushKeysDB(_K, StackIndex{ 1 }); // _K: linda key val... KeysDB 680 PushKeysDB(_K, StackIndex{ 1 }); // _K: linda key val... KeysDB
654 // get the fifo associated to this key in this linda, create it if it doesn't exist 681 // get the fifo associated to this key in this linda, create it if it doesn't exist
655 lua_pushvalue(_K, 2); // _K: linda key val... KeysDB key 682 lua_pushvalue(_K, 2); // _K: linda key val... KeysDB key
656 if (luaG_rawget(_K, StackIndex{ -2 }) == LuaType::NIL) { // _K: linda key val... KeysDB KeyUD|nil 683 if (luaW_rawget(_K, StackIndex{ -2 }) == LuaType::NIL) { // _K: linda key val... KeysDB KeyUD|nil
657 lua_pop(_K, 1); // _K: linda key val... KeysDB 684 lua_pop(_K, 1); // _K: linda key val... KeysDB
658 std::ignore = KeyUD::Create(KeeperState{ _K }); // _K: linda key val... KeysDB KeyUD 685 std::ignore = KeyUD::Create(KeeperState{ _K }); // _K: linda key val... KeysDB KeyUD
659 // KeysDB[key] = KeyUD 686 // KeysDB[key] = KeyUD
@@ -684,6 +711,7 @@ int keepercall_send(lua_State* const L_)
684 711
685// in: linda key [val...] 712// in: linda key [val...]
686// out: true if the linda was full but it's no longer the case, else false, or kRestrictedChannel if the key is restricted 713// out: true if the linda was full but it's no longer the case, else false, or kRestrictedChannel if the key is restricted
714[[nodiscard]]
687int keepercall_set(lua_State* const L_) 715int keepercall_set(lua_State* const L_)
688{ 716{
689 KeeperState const _K{ L_ }; 717 KeeperState const _K{ L_ };
@@ -753,6 +781,7 @@ int keepercall_set(lua_State* const L_)
753 * 781 *
754 * Returns: number of return values (pushed to 'L'), unset in case of error 782 * Returns: number of return values (pushed to 'L'), unset in case of error
755 */ 783 */
784[[nodiscard]]
756KeeperCallResult keeper_call(KeeperState const K_, keeper_api_t const func_, lua_State* const L_, Linda* const linda_, StackIndex const starting_index_) 785KeeperCallResult keeper_call(KeeperState const K_, keeper_api_t const func_, lua_State* const L_, Linda* const linda_, StackIndex const starting_index_)
757{ 786{
758 KeeperCallResult _result; 787 KeeperCallResult _result;
@@ -822,6 +851,7 @@ KeeperCallResult keeper_call(KeeperState const K_, keeper_api_t const func_, lua
822// } 851// }
823// ... 852// ...
824// } 853// }
854[[nodiscard]]
825int Keeper::PushLindaStorage(Linda& linda_, DestState const L_) 855int Keeper::PushLindaStorage(Linda& linda_, DestState const L_)
826{ 856{
827 Keeper* const _keeper{ linda_.whichKeeper() }; 857 Keeper* const _keeper{ linda_.whichKeeper() };
@@ -833,7 +863,7 @@ int Keeper::PushLindaStorage(Linda& linda_, DestState const L_)
833 STACK_CHECK_START_REL(_K, 0); 863 STACK_CHECK_START_REL(_K, 0);
834 kLindasRegKey.pushValue(_K); // _K: LindasDB L_: 864 kLindasRegKey.pushValue(_K); // _K: LindasDB L_:
835 lua_pushlightuserdata(_K, &linda_); // _K: LindasDB linda L_: 865 lua_pushlightuserdata(_K, &linda_); // _K: LindasDB linda L_:
836 LuaType const _type{ luaG_rawget(_K, StackIndex{ -2 }) }; // _K: LindasDB KeysDB L_: 866 LuaType const _type{ luaW_rawget(_K, StackIndex{ -2 }) }; // _K: LindasDB KeysDB L_:
837 lua_remove(_K, -2); // _K: KeysDB L_: 867 lua_remove(_K, -2); // _K: KeysDB L_:
838 if (_type != LuaType::TABLE) { // possible if we didn't send anything through that linda 868 if (_type != LuaType::TABLE) { // possible if we didn't send anything through that linda
839 lua_pop(_K, 1); // _K: L_: 869 lua_pop(_K, 1); // _K: L_:
@@ -870,20 +900,20 @@ int Keeper::PushLindaStorage(Linda& linda_, DestState const L_)
870 if (_key->limit >= 0) { 900 if (_key->limit >= 0) {
871 lua_pushinteger(L_, _key->limit); // _K: KeysDB key L_: out key keyout fifo limit 901 lua_pushinteger(L_, _key->limit); // _K: KeysDB key L_: out key keyout fifo limit
872 } else { 902 } else {
873 luaG_pushstring(L_, "unlimited"); // _K: KeysDB key L_: out key keyout fifo limit 903 luaW_pushstring(L_, "unlimited"); // _K: KeysDB key L_: out key keyout fifo limit
874 } 904 }
875 STACK_CHECK(L_, 5); 905 STACK_CHECK(L_, 5);
876 lua_setfield(L_, -3, "limit"); // _K: KeysDB key L_: out key keyout fifo 906 lua_setfield(L_, -3, "limit"); // _K: KeysDB key L_: out key keyout fifo
877 // keyout.restrict 907 // keyout.restrict
878 switch (_key->restrict) { 908 switch (_key->restrict) {
879 case LindaRestrict::None: 909 case LindaRestrict::None:
880 luaG_pushstring(L_, "none"); // _K: KeysDB key L_: out key keyout fifo restrict 910 luaW_pushstring(L_, "none"); // _K: KeysDB key L_: out key keyout fifo restrict
881 break; 911 break;
882 case LindaRestrict::SetGet: 912 case LindaRestrict::SetGet:
883 luaG_pushstring(L_, "set/get"); // _K: KeysDB key L_: out key keyout fifo restrict 913 luaW_pushstring(L_, "set/get"); // _K: KeysDB key L_: out key keyout fifo restrict
884 break; 914 break;
885 case LindaRestrict::SendReceive: 915 case LindaRestrict::SendReceive:
886 luaG_pushstring(L_, "send/receive"); // _K: KeysDB key L_: out key keyout fifo restrict 916 luaW_pushstring(L_, "send/receive"); // _K: KeysDB key L_: out key keyout fifo restrict
887 break; 917 break;
888 } 918 }
889 STACK_CHECK(L_, 5); 919 STACK_CHECK(L_, 5);
@@ -951,16 +981,16 @@ void Keepers::collectGarbage()
951 981
952// ################################################################################################# 982// #################################################################################################
953 983
954 984[[nodiscard]]
955void Keepers::close() 985bool Keepers::close()
956{ 986{
957 if (isClosing.test_and_set(std::memory_order_release)) { 987 if (isClosing.test_and_set(std::memory_order_release)) {
958 assert(false); // should never close more than once in practice 988 return false; // should never close more than once in practice
959 return;
960 } 989 }
961 990
991 // We may have not initialized the keepers if an error was raised in Universe::Create because of bad settings
962 if (std::holds_alternative<std::monostate>(keeper_array)) { 992 if (std::holds_alternative<std::monostate>(keeper_array)) {
963 return; 993 return true;
964 } 994 }
965 995
966 auto _closeOneKeeper = [](Keeper& keeper_) { 996 auto _closeOneKeeper = [](Keeper& keeper_) {
@@ -989,6 +1019,7 @@ void Keepers::close()
989 } 1019 }
990 1020
991 keeper_array.emplace<std::monostate>(); 1021 keeper_array.emplace<std::monostate>();
1022 return true;
992} 1023}
993 1024
994// ################################################################################################# 1025// #################################################################################################
@@ -1059,7 +1090,7 @@ void Keepers::initialize(Universe& U_, lua_State* L_, size_t const nbKeepers_, i
1059 keeper_.K = _K; 1090 keeper_.K = _K;
1060 1091
1061 // Give a name to the state 1092 // Give a name to the state
1062 luaG_pushstring(_K, "Keeper #%d", i_ + 1); // L_: settings _K: "Keeper #n" 1093 luaW_pushstring(_K, "Keeper #%d", i_ + 1); // L_: settings _K: "Keeper #n"
1063 if constexpr (HAVE_DECODA_SUPPORT()) { 1094 if constexpr (HAVE_DECODA_SUPPORT()) {
1064 lua_pushvalue(_K, -1); // _K: "Keeper #n" Keeper #n" 1095 lua_pushvalue(_K, -1); // _K: "Keeper #n" Keeper #n"
1065 lua_setglobal(_K, "decoda_name"); // L_: settings _K: "Keeper #n" 1096 lua_setglobal(_K, "decoda_name"); // L_: settings _K: "Keeper #n"
@@ -1081,9 +1112,9 @@ void Keepers::initialize(Universe& U_, lua_State* L_, size_t const nbKeepers_, i
1081 STACK_CHECK(_K, 0); 1112 STACK_CHECK(_K, 0);
1082 1113
1083 // copy package.path and package.cpath from the source state 1114 // copy package.path and package.cpath from the source state
1084 if (luaG_getmodule(L, LUA_LOADLIBNAME) != LuaType::NIL) { // L_: settings package _K: 1115 if (luaW_getmodule(L, LUA_LOADLIBNAME) != LuaType::NIL) { // L_: settings package _K:
1085 // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately 1116 // when copying with mode LookupMode::ToKeeper, error message is pushed at the top of the stack, not raised immediately
1086 InterCopyContext _c{ U, DestState{ _K.value() }, SourceState{ L }, {}, SourceIndex{ luaG_absindex(L, kIdxTop).value() }, {}, LookupMode::ToKeeper, {} }; 1117 InterCopyContext _c{ U, DestState{ _K.value() }, SourceState{ L }, {}, SourceIndex{ luaW_absindex(L, kIdxTop).value() }, {}, LookupMode::ToKeeper, {} };
1087 if (_c.interCopyPackage() != InterCopyResult::Success) { // L_: settings ... error_msg _K: 1118 if (_c.interCopyPackage() != InterCopyResult::Success) { // L_: settings ... error_msg _K:
1088 // if something went wrong, the error message is at the top of the stack 1119 // if something went wrong, the error message is at the top of the stack
1089 lua_remove(L, -2); // L_: settings error_msg 1120 lua_remove(L, -2); // L_: settings error_msg
diff --git a/src/keeper.hpp b/src/keeper.hpp
index f1083b3..955577c 100644
--- a/src/keeper.hpp
+++ b/src/keeper.hpp
@@ -68,7 +68,8 @@ struct Keepers
68 68
69 Keepers() = default; 69 Keepers() = default;
70 void collectGarbage(); 70 void collectGarbage();
71 void close(); 71 [[nodiscard]]
72 bool close();
72 [[nodiscard]] 73 [[nodiscard]]
73 Keeper* getKeeper(KeeperIndex idx_); 74 Keeper* getKeeper(KeeperIndex idx_);
74 [[nodiscard]] 75 [[nodiscard]]
diff --git a/src/lane.cpp b/src/lane.cpp
index 5cebdfa..b23ff78 100644
--- a/src/lane.cpp
+++ b/src/lane.cpp
@@ -49,7 +49,7 @@ static LUAG_FUNC(lane_get_threadname)
49{ 49{
50 Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; 50 Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) };
51 luaL_argcheck(L_, lua_gettop(L_) == 1, 2, "too many arguments"); 51 luaL_argcheck(L_, lua_gettop(L_) == 1, 2, "too many arguments");
52 luaG_pushstring(L_, _lane->getDebugName()); 52 luaW_pushstring(L_, _lane->getDebugName());
53 return 1; 53 return 1;
54} 54}
55 55
@@ -85,17 +85,17 @@ static LUAG_FUNC(set_finalizer)
85static LUAG_FUNC(lane_threadname) 85static LUAG_FUNC(lane_threadname)
86{ 86{
87 // C s_lane structure is a light userdata upvalue 87 // C s_lane structure is a light userdata upvalue
88 Lane* const _lane{ luaG_tolightuserdata<Lane>(L_, StackIndex{ lua_upvalueindex(1) }) }; 88 Lane* const _lane{ luaW_tolightuserdata<Lane>(L_, StackIndex{ lua_upvalueindex(1) }) };
89 LUA_ASSERT(L_, L_ == _lane->L); // this function is exported in a lane's state, therefore it is callable only from inside the Lane's state 89 LUA_ASSERT(L_, L_ == _lane->L); // this function is exported in a lane's state, therefore it is callable only from inside the Lane's state
90 if (lua_gettop(L_) == 1) { 90 if (lua_gettop(L_) == 1) {
91 lua_settop(L_, 1); 91 lua_settop(L_, 1);
92 STACK_CHECK_START_REL(L_, 0); 92 STACK_CHECK_START_REL(L_, 0);
93 _lane->storeDebugName(luaG_tostring(L_, kIdxTop)); 93 _lane->storeDebugName(luaW_tostring(L_, kIdxTop));
94 _lane->applyDebugName(); 94 _lane->applyDebugName();
95 STACK_CHECK(L_, 0); 95 STACK_CHECK(L_, 0);
96 return 0; 96 return 0;
97 } else if (lua_gettop(L_) == 0) { 97 } else if (lua_gettop(L_) == 0) {
98 luaG_pushstring(L_, _lane->getDebugName()); 98 luaW_pushstring(L_, _lane->getDebugName());
99 return 1; 99 return 1;
100 } else { 100 } else {
101 raise_luaL_error(L_, "Wrong number of arguments"); 101 raise_luaL_error(L_, "Wrong number of arguments");
@@ -105,7 +105,7 @@ static LUAG_FUNC(lane_threadname)
105// ################################################################################################# 105// #################################################################################################
106 106
107//--- 107//---
108// [...] | [nil, err_any, stack_tbl]= lane:join([wait_secs]) 108// [true, ...] | [nil, err_any, stack_tbl]= lane:join([wait_secs])
109// 109//
110// timeout: returns nil 110// timeout: returns nil
111// done: returns return values (0..N) 111// done: returns return values (0..N)
@@ -117,7 +117,7 @@ static LUAG_FUNC(lane_join)
117 Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; 117 Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) };
118 118
119 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; 119 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() };
120 if (luaG_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion 120 if (luaW_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion
121 lua_Duration const duration{ lua_tonumber(L_, 2) }; 121 lua_Duration const duration{ lua_tonumber(L_, 2) };
122 if (duration.count() >= 0.0) { 122 if (duration.count() >= 0.0) {
123 _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); 123 _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration);
@@ -128,71 +128,20 @@ static LUAG_FUNC(lane_join)
128 } else if (!lua_isnoneornil(L_, 2)) { 128 } else if (!lua_isnoneornil(L_, 2)) {
129 raise_luaL_argerror(L_, StackIndex{ 2 }, "incorrect duration type"); 129 raise_luaL_argerror(L_, StackIndex{ 2 }, "incorrect duration type");
130 } 130 }
131
132 lua_settop(L_, 1); // L_: lane 131 lua_settop(L_, 1); // L_: lane
133 bool const _done{ !_lane->thread.joinable() || _lane->waitForCompletion(_until) };
134 132
135 if (!_done) { 133 // wait until suspended or done
136 lua_pushnil(L_); // L_: lane nil 134 STACK_CHECK_START_REL(L_, 0); // L_: lane
137 luaG_pushstring(L_, "timeout"); // L_: lane nil "timeout" 135 if (!_lane->waitForJoin(L_, _until)) {
136 // in that case, should have pushed nil, "timeout"
137 STACK_CHECK(L_, 2);
138 return 2; 138 return 2;
139 } 139 }
140 STACK_CHECK(L_, 0); // L_: lane
141 // Thread is Done/Error/Cancelled; the Lane thread isn't working with it, therefore we can.
140 142
141 STACK_CHECK_START_REL(L_, 0); // L_: lane 143 std::ignore = _lane->storeResults(L_);
142 // Thread is Suspended or Done/Error/Cancelled; the Lane thread isn't working with it, therefore we can. 144 int const _ret{ _lane->pushStoredResults(L_) };
143
144 int _ret{ 0 };
145 int const _stored{ _lane->storeResults(L_) };
146 STACK_GROW(L_, std::max(3, _stored + 1));
147 switch (_lane->status.load(std::memory_order_acquire)) {
148 case Lane::Suspended: // got yielded values
149 case Lane::Done: // got regular return values
150 {
151 if (_stored == 0) {
152 raise_luaL_error(L_, _lane->L ? "First return value must be non-nil when using join()" : "Can't join() more than once or after indexing");
153 }
154 lua_getiuservalue(L_, StackIndex{ 1 }, UserValueIndex{ 1 }); // L_: lane {uv}
155 for (int _i = 2; _i <= _stored; ++_i) {
156 lua_rawgeti(L_, 2, _i); // L_: lane {uv} results2...N
157 }
158 lua_rawgeti(L_, 2, 1); // L_: lane {uv} results2...N result1
159 lua_replace(L_, 2); // L_: lane results
160 _ret = _stored;
161 }
162 break;
163
164 case Lane::Error:
165 {
166 LUA_ASSERT(L_, _stored == 2 || _stored == 3);
167 lua_getiuservalue(L_, StackIndex{ 1 }, UserValueIndex{ 1 }); // L_: lane {uv}
168 lua_rawgeti(L_, 2, 2); // L_: lane {uv} <error>
169 lua_rawgeti(L_, 2, 3); // L_: lane {uv} <error> <trace>|nil
170 if (lua_isnil(L_, -1)) {
171 lua_replace(L_, 2); // L_: lane nil <error>
172 } else {
173 lua_rawgeti(L_, 2, 1); // L_: lane {uv} <error> <trace> nil
174 lua_replace(L_, 2); // L_: lane nil <error> <trace>
175 }
176 _ret = lua_gettop(L_) - 1; // 2 or 3
177 }
178 break;
179
180 case Lane::Cancelled:
181 LUA_ASSERT(L_, _stored == 2);
182 lua_getiuservalue(L_, StackIndex{ 1 }, UserValueIndex{ 1 }); // L_: lane {uv}
183 lua_rawgeti(L_, 2, 2); // L_: lane {uv} cancel_error
184 lua_rawgeti(L_, 2, 1); // L_: lane {uv} cancel_error nil
185 lua_replace(L_, -3); // L_: lane nil cancel_error
186 LUA_ASSERT(L_, lua_isnil(L_, -2) && kCancelError.equals(L_, kIdxTop));
187 _ret = 2;
188 break;
189
190 default:
191 DEBUGSPEW_CODE(DebugSpew(nullptr) << "Unknown Lane status: " << static_cast<int>(_lane->status.load(std::memory_order_relaxed)) << std::endl);
192 LUA_ASSERT(L_, false);
193 _ret = 0;
194 }
195 STACK_CHECK(L_, _ret);
196 return _ret; 145 return _ret;
197} 146}
198 147
@@ -204,23 +153,13 @@ LUAG_FUNC(lane_resume)
204 Lane* const _lane{ ToLane(L_, kIdxSelf) }; 153 Lane* const _lane{ ToLane(L_, kIdxSelf) };
205 lua_State* const _L2{ _lane->L }; 154 lua_State* const _L2{ _lane->L };
206 155
207 // wait until the lane yields 156 // wait until the lane yields or returns
208 std::optional<Lane::Status> _hadToWait{}; // for debugging, if we ever raise the error just below 157 std::ignore = _lane->waitForCompletion(std::chrono::time_point<std::chrono::steady_clock>::max(), true);
209 { 158
210 std::unique_lock _guard{ _lane->doneMutex };
211 Lane::Status const _status{ _lane->status.load(std::memory_order_acquire) };
212 if (_status == Lane::Pending || _status == Lane::Running || _status == Lane::Resuming) {
213 _hadToWait = _status;
214 _lane->doneCondVar.wait(_guard, [_lane]() { return _lane->status.load(std::memory_order_acquire) == Lane::Suspended; });
215 }
216 }
217 if (_lane->status.load(std::memory_order_acquire) != Lane::Suspended) { 159 if (_lane->status.load(std::memory_order_acquire) != Lane::Suspended) {
218 if (_hadToWait) { 160 raise_luaL_error(L_, "cannot resume non-suspended coroutine Lane");
219 raise_luaL_error(L_, "INTERNAL ERROR: Lane status is %s instead of 'suspended'", _lane->threadStatusString().data());
220 } else {
221 raise_luaL_error(L_, "Can't resume a non-suspended coroutine-type Lane");
222 }
223 } 161 }
162
224 int const _nargs{ lua_gettop(L_) - 1 }; 163 int const _nargs{ lua_gettop(L_) - 1 };
225 int const _nresults{ lua_gettop(_L2) }; 164 int const _nresults{ lua_gettop(_L2) };
226 STACK_CHECK_START_ABS(L_, 1 + _nargs); // L_: self args... _L2: results... 165 STACK_CHECK_START_ABS(L_, 1 + _nargs); // L_: self args... _L2: results...
@@ -263,12 +202,17 @@ static int lane_index_number(lua_State* L_)
263 int const _key{ static_cast<int>(lua_tointeger(L_, 2)) }; 202 int const _key{ static_cast<int>(lua_tointeger(L_, 2)) };
264 lua_pop(L_, 1); // L_: lane 203 lua_pop(L_, 1); // L_: lane
265 204
205 // wait until suspended or done
206 STACK_CHECK_START_REL(L_, 0); // L_: lane
266 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; 207 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() };
267 if (!_lane->waitForCompletion(_until)) { 208 if (!_lane->waitForJoin(L_, _until)) {
268 raise_luaL_error(L_, "INTERNAL ERROR: Failed to join"); 209 // in that case, should have pushed nil, "timeout"
210 STACK_CHECK(L_, 2);
211 return 2;
269 } 212 }
213 STACK_CHECK(L_, 0); // L_: lane
214 // Thread is Done/Error/Cancelled; the Lane thread isn't working with it, therefore we can.
270 215
271 // make sure results are stored
272 int const _stored{ _lane->storeResults(L_) }; 216 int const _stored{ _lane->storeResults(L_) };
273 if (_key > _stored) { 217 if (_key > _stored) {
274 // get nil if indexing beyond the actual returned value count 218 // get nil if indexing beyond the actual returned value count
@@ -276,6 +220,7 @@ static int lane_index_number(lua_State* L_)
276 } else { 220 } else {
277 _lane->pushIndexedResult(L_, _key); // L_: lane result 221 _lane->pushIndexedResult(L_, _key); // L_: lane result
278 } 222 }
223
279 return 1; 224 return 1;
280} 225}
281 226
@@ -292,13 +237,13 @@ static int lane_index_string(lua_State* L_)
292 Lane* const _lane{ ToLane(L_, kIdxSelf) }; 237 Lane* const _lane{ ToLane(L_, kIdxSelf) };
293 LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane "key" 238 LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane "key"
294 239
295 std::string_view const _keystr{ luaG_tostring(L_, kIdxKey) }; 240 std::string_view const _keystr{ luaW_tostring(L_, kIdxKey) };
296 lua_settop(L_, 2); // keep only our original arguments on the stack 241 lua_settop(L_, 2); // keep only our original arguments on the stack
297 242
298 // look in metatable first 243 // look in metatable first
299 lua_getmetatable(L_, kIdxSelf); // L_: lane "key" mt 244 lua_getmetatable(L_, kIdxSelf); // L_: lane "key" mt
300 lua_replace(L_, -3); // L_: mt "key" 245 lua_replace(L_, -3); // L_: mt "key"
301 if (luaG_rawget(L_, StackIndex{ -2 }) != LuaType::NIL) { // found something? // L_: mt value 246 if (luaW_rawget(L_, StackIndex{ -2 }) != LuaType::NIL) { // found something? // L_: mt value
302 return 1; // done 247 return 1; // done
303 } 248 }
304 249
@@ -324,7 +269,7 @@ static LUAG_FUNC(lane_index)
324 Lane* const _lane{ ToLane(L_, kIdxSelf) }; 269 Lane* const _lane{ ToLane(L_, kIdxSelf) };
325 LUA_ASSERT(L_, lua_gettop(L_) == 2); 270 LUA_ASSERT(L_, lua_gettop(L_) == 2);
326 271
327 switch (luaG_type(L_, kKey)) { 272 switch (luaW_type(L_, kKey)) {
328 case LuaType::NUMBER: 273 case LuaType::NUMBER:
329 return lane_index_number(L_); // stack modification is undefined, returned value is at the top 274 return lane_index_number(L_); // stack modification is undefined, returned value is at the top
330 275
@@ -334,19 +279,19 @@ static LUAG_FUNC(lane_index)
334 default: // unknown key 279 default: // unknown key
335 lua_getmetatable(L_, kIdxSelf); // L_: mt 280 lua_getmetatable(L_, kIdxSelf); // L_: mt
336 kCachedError.pushKey(L_); // L_: mt kCachedError 281 kCachedError.pushKey(L_); // L_: mt kCachedError
337 if (luaG_rawget(L_, StackIndex{ -2 }) != LuaType::FUNCTION) { // L_: mt error() 282 if (luaW_rawget(L_, StackIndex{ -2 }) != LuaType::FUNCTION) { // L_: mt error()
338 raise_luaL_error(L_, "INTERNAL ERROR: cached error() is a %s, not a function", luaG_typename(L_, kIdxTop).data()); 283 raise_luaL_error(L_, "INTERNAL ERROR: cached error() is a %s, not a function", luaW_typename(L_, kIdxTop).data());
339 } 284 }
340 luaG_pushstring(L_, "Unknown key: "); // L_: mt error() "Unknown key: " 285 luaW_pushstring(L_, "Unknown key: "); // L_: mt error() "Unknown key: "
341 kCachedTostring.pushKey(L_); // L_: mt error() "Unknown key: " kCachedTostring 286 kCachedTostring.pushKey(L_); // L_: mt error() "Unknown key: " kCachedTostring
342 if (luaG_rawget(L_, StackIndex{ -4 }) != LuaType::FUNCTION) { // L_: mt error() "Unknown key: " tostring() 287 if (luaW_rawget(L_, StackIndex{ -4 }) != LuaType::FUNCTION) { // L_: mt error() "Unknown key: " tostring()
343 raise_luaL_error(L_, "INTERNAL ERROR: cached tostring() is a %s, not a function", luaG_typename(L_, kIdxTop).data()); 288 raise_luaL_error(L_, "INTERNAL ERROR: cached tostring() is a %s, not a function", luaW_typename(L_, kIdxTop).data());
344 } 289 }
345 lua_pushvalue(L_, kKey); // L_: mt error() "Unknown key: " tostring() k 290 lua_pushvalue(L_, kKey); // L_: mt error() "Unknown key: " tostring() k
346 lua_call(L_, 1, 1); // L_: mt error() "Unknown key: " "k" 291 lua_call(L_, 1, 1); // L_: mt error() "Unknown key: " "k"
347 lua_concat(L_, 2); // L_: mt error() "Unknown key: <k>" 292 lua_concat(L_, 2); // L_: mt error() "Unknown key: <k>"
348 lua_call(L_, 1, 0); // error( "Unknown key: " .. key) -> doesn't return // L_: mt 293 lua_call(L_, 1, 0); // error( "Unknown key: " .. key) -> doesn't return // L_: mt
349 raise_luaL_error(L_, "%s[%s]: should not get here!", _lane->getDebugName().data(), luaG_typename(L_, kKey).data()); 294 raise_luaL_error(L_, "%s[%s]: should not get here!", _lane->getDebugName().data(), luaW_typename(L_, kKey).data());
350 } 295 }
351} 296}
352 297
@@ -437,7 +382,7 @@ int Lane::LuaErrorHandler(lua_State* L_)
437 // table of { "sourcefile.lua:<line>", ... } 382 // table of { "sourcefile.lua:<line>", ... }
438 // 383 //
439 lua_newtable(L_); // L_: some_error {} 384 lua_newtable(L_); // L_: some_error {}
440 StackIndex const kIdxTraceTbl{ luaG_absindex(L_, kIdxTop) }; 385 StackIndex const kIdxTraceTbl{ luaW_absindex(L_, kIdxTop) };
441 386
442 // Best to start from level 1, but in some cases it might be a C function 387 // Best to start from level 1, but in some cases it might be a C function
443 // and we don't get '.currentline' for that. It's okay - just keep level 388 // and we don't get '.currentline' for that. It's okay - just keep level
@@ -448,25 +393,25 @@ int Lane::LuaErrorHandler(lua_State* L_)
448 lua_getinfo(L_, _extended ? "Sln" : "Sl", &_ar); 393 lua_getinfo(L_, _extended ? "Sln" : "Sl", &_ar);
449 if (_extended) { 394 if (_extended) {
450 lua_newtable(L_); // L_: some_error {} {} 395 lua_newtable(L_); // L_: some_error {} {}
451 StackIndex const kIdxFrameTbl{ luaG_absindex(L_, kIdxTop) }; 396 StackIndex const kIdxFrameTbl{ luaW_absindex(L_, kIdxTop) };
452 lua_pushstring(L_, _ar.source); // L_: some_error {} {} source 397 lua_pushstring(L_, _ar.source); // L_: some_error {} {} source
453 luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "source" }); // L_: some_error {} {} 398 luaW_setfield(L_, kIdxFrameTbl, std::string_view{ "source" }); // L_: some_error {} {}
454 399
455 lua_pushinteger(L_, _ar.currentline); // L_: some_error {} {} currentline 400 lua_pushinteger(L_, _ar.currentline); // L_: some_error {} {} currentline
456 luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "currentline" }); // L_: some_error {} {} 401 luaW_setfield(L_, kIdxFrameTbl, std::string_view{ "currentline" }); // L_: some_error {} {}
457 402
458 lua_pushstring(L_, _ar.name ? _ar.name : "<?>"); // L_: some_error {} {} name 403 lua_pushstring(L_, _ar.name ? _ar.name : "<?>"); // L_: some_error {} {} name
459 luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "name" }); // L_: some_error {} {} 404 luaW_setfield(L_, kIdxFrameTbl, std::string_view{ "name" }); // L_: some_error {} {}
460 405
461 lua_pushstring(L_, _ar.namewhat); // L_: some_error {} {} namewhat 406 lua_pushstring(L_, _ar.namewhat); // L_: some_error {} {} namewhat
462 luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "namewhat" }); // L_: some_error {} {} 407 luaW_setfield(L_, kIdxFrameTbl, std::string_view{ "namewhat" }); // L_: some_error {} {}
463 408
464 lua_pushstring(L_, _ar.what); // L_: some_error {} {} what 409 lua_pushstring(L_, _ar.what); // L_: some_error {} {} what
465 luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "what" }); // L_: some_error {} {} 410 luaW_setfield(L_, kIdxFrameTbl, std::string_view{ "what" }); // L_: some_error {} {}
466 } else if (_ar.currentline > 0) { 411 } else if (_ar.currentline > 0) {
467 luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah" 412 luaW_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah"
468 } else { 413 } else {
469 luaG_pushstring(L_, "%s:?", _ar.short_src); // L_: some_error {} "blah" 414 luaW_pushstring(L_, "%s:?", _ar.short_src); // L_: some_error {} "blah"
470 } 415 }
471 lua_rawseti(L_, kIdxTraceTbl, static_cast<lua_Integer>(_n)); // L_: some_error {} 416 lua_rawseti(L_, kIdxTraceTbl, static_cast<lua_Integer>(_n)); // L_: some_error {}
472 } 417 }
@@ -489,6 +434,7 @@ static int PushStackTrace(lua_State* const L_, Lane::ErrorTraceLevel const error
489 StackIndex const _top{ lua_gettop(L_) }; 434 StackIndex const _top{ lua_gettop(L_) };
490 switch (rc_) { 435 switch (rc_) {
491 case LuaError::OK: // no error, body return values are on the stack 436 case LuaError::OK: // no error, body return values are on the stack
437 case LuaError::YIELD:
492 break; 438 break;
493 439
494 case LuaError::ERRRUN: // cancellation or a runtime error 440 case LuaError::ERRRUN: // cancellation or a runtime error
@@ -502,7 +448,7 @@ static int PushStackTrace(lua_State* const L_, Lane::ErrorTraceLevel const error
502 448
503 // For cancellation the error message is kCancelError, and a stack trace isn't placed 449 // For cancellation the error message is kCancelError, and a stack trace isn't placed
504 // For other errors, the message can be whatever was thrown, and we should have a stack trace table 450 // For other errors, the message can be whatever was thrown, and we should have a stack trace table
505 LUA_ASSERT(L_, luaG_type(L_, StackIndex{ 1 + stk_base_ }) == (kCancelError.equals(L_, stk_base_) ? LuaType::NIL : LuaType::TABLE)); 451 LUA_ASSERT(L_, luaW_type(L_, StackIndex{ 1 + stk_base_ }) == (kCancelError.equals(L_, stk_base_) ? LuaType::NIL : LuaType::TABLE));
506 // Just leaving the stack trace table on the stack is enough to get it through to the master. 452 // Just leaving the stack trace table on the stack is enough to get it through to the master.
507 } else { 453 } else {
508 // any kind of error can be thrown with error(), or through a lane/linda cancellation 454 // any kind of error can be thrown with error(), or through a lane/linda cancellation
@@ -514,7 +460,7 @@ static int PushStackTrace(lua_State* const L_, Lane::ErrorTraceLevel const error
514 case LuaError::ERRERR: // error while running the error handler (if any, for example an out-of-memory condition) 460 case LuaError::ERRERR: // error while running the error handler (if any, for example an out-of-memory condition)
515 default: 461 default:
516 // the Lua core provides a string error message in those situations 462 // the Lua core provides a string error message in those situations
517 LUA_ASSERT(L_, (lua_gettop(L_) == stk_base_) && (luaG_type(L_, stk_base_) == LuaType::STRING)); 463 LUA_ASSERT(L_, (lua_gettop(L_) == stk_base_) && (luaW_type(L_, stk_base_) == LuaType::STRING));
518 break; 464 break;
519 } 465 }
520 return lua_gettop(L_) - _top; // either 0 or 1 466 return lua_gettop(L_) - _top; // either 0 or 1
@@ -563,7 +509,7 @@ static LuaError run_finalizers(Lane* const lane_, Lane::ErrorTraceLevel const er
563 LUA_ASSERT(_L, lua_isfunction(_L, -1)); 509 LUA_ASSERT(_L, lua_isfunction(_L, -1));
564 if (lua_rc_ != LuaError::OK) { // we have <error>, [trace] on the thread stack 510 if (lua_rc_ != LuaError::OK) { // we have <error>, [trace] on the thread stack
565 LUA_ASSERT(_L, lane_->nresults == 1 || lane_->nresults == 2); 511 LUA_ASSERT(_L, lane_->nresults == 1 || lane_->nresults == 2);
566 //std::string_view const _err_msg{ luaG_tostring(_L, 1) }; 512 //std::string_view const _err_msg{ luaW_tostring(_L, 1) };
567 if (lane_->isCoroutine()) { 513 if (lane_->isCoroutine()) {
568 // transfer them on the main state 514 // transfer them on the main state
569 lua_pushvalue(lane_->L, 1); 515 lua_pushvalue(lane_->L, 1);
@@ -615,7 +561,7 @@ static LuaError run_finalizers(Lane* const lane_, Lane::ErrorTraceLevel const er
615 561
616 if (lane_->isCoroutine()) { 562 if (lane_->isCoroutine()) {
617 // only the coroutine thread should remain on the master state when we are done 563 // only the coroutine thread should remain on the master state when we are done
618 LUA_ASSERT(_L, lua_gettop(_L) == 1 && luaG_type(_L, StackIndex{ 1 }) == LuaType::THREAD); 564 LUA_ASSERT(_L, lua_gettop(_L) == 1 && luaW_type(_L, StackIndex{ 1 }) == LuaType::THREAD);
619 } 565 }
620 566
621 return _rc; 567 return _rc;
@@ -711,7 +657,7 @@ static void lane_main(Lane* const lane_)
711 LuaError _rc{ LuaError::ERRRUN }; 657 LuaError _rc{ LuaError::ERRRUN };
712 if (lane_->status.load(std::memory_order_acquire) == Lane::Pending) { // nothing wrong happened during preparation, we can work 658 if (lane_->status.load(std::memory_order_acquire) == Lane::Pending) { // nothing wrong happened during preparation, we can work
713 // At this point, the lane function and arguments are on the stack, possibly preceded by the error handler 659 // At this point, the lane function and arguments are on the stack, possibly preceded by the error handler
714 int const _errorHandlerCount{ lane_->errorHandlerCount() }; 660 int const _errorHandlerCount{ lane_->errorHandlerCount() }; // no error handler for coroutines, ever.
715 int _nargs{ lua_gettop(_L) - 1 - _errorHandlerCount }; 661 int _nargs{ lua_gettop(_L) - 1 - _errorHandlerCount };
716 { 662 {
717 std::unique_lock _guard{ lane_->doneMutex }; 663 std::unique_lock _guard{ lane_->doneMutex };
@@ -724,27 +670,60 @@ static void lane_main(Lane* const lane_)
724 lane_->nresults = lua_gettop(_L) - _errorHandlerCount; 670 lane_->nresults = lua_gettop(_L) - _errorHandlerCount;
725 } else { 671 } else {
726 // S and L are different: we run as a coroutine in Lua thread L created in state S 672 // S and L are different: we run as a coroutine in Lua thread L created in state S
673 bool _shouldClose{ false };
727 do { 674 do {
728 // starting with Lua 5.4, lua_resume can leave more stuff on the stack below the actual yielded values. 675 // starting with Lua 5.4, lua_resume can leave more stuff on the stack below the actual yielded values.
729 // that's why we have lane_->nresults 676 // that's why we have lane_->nresults
730 _rc = luaG_resume(_L, nullptr, _nargs, &lane_->nresults); // L: eh? ... retvals|err... 677 _rc = luaW_resume(_L, nullptr, _nargs, &lane_->nresults); // L: ... retvals|err...
731 if (_rc == LuaError::YIELD) { 678 if (_rc == LuaError::YIELD) {
732 // change our status to suspended, and wait until someone wants us to resume
733 std::unique_lock _guard{ lane_->doneMutex };
734 lane_->status.store(Lane::Suspended, std::memory_order_release); // Running -> Suspended
735 lane_->doneCondVar.notify_one();
736 // wait until the user wants us to resume
737 // TODO: do I update waiting_on or not, so that the lane can be woken by cancellation requests here?
738 // lane_->waiting_on = &lane_->doneCondVar;
739 lane_->doneCondVar.wait(_guard, [lane_]() { return lane_->status.load(std::memory_order_acquire) == Lane::Resuming; });
740 // here lane_->doneMutex is locked again
741 // lane_->waiting_on = nullptr;
742 lane_->status.store(Lane::Running, std::memory_order_release); // Resuming -> Running
743 // on the stack we find the values pushed by lane:resume() 679 // on the stack we find the values pushed by lane:resume()
744 _nargs = lua_gettop(_L); 680 _nargs = lua_gettop(_L);
681 if (std::unique_lock _guard{ lane_->doneMutex }; true) {
682 // change our status to suspended, and wait until someone wants us to resume
683 lane_->status.store(Lane::Suspended, std::memory_order_release); // Running -> Suspended
684 lane_->doneCondVar.notify_one();
685 // wait until the user wants us to resume
686 // update waiting_on, so that the lane can be woken by cancellation requests here
687 lane_->waiting_on = &lane_->doneCondVar;
688 lane_->doneCondVar.wait(_guard,
689 [lane_,&_shouldClose]()
690 {
691 auto const _status{ lane_->status.load(std::memory_order_acquire) };
692 // wait interrupted because of a cancellation or join request means we have to abort the resume loop
693 _shouldClose = (_status == Lane::Closing);
694 return _shouldClose || (_status == Lane::Resuming) || (lane_->cancelRequest.load(std::memory_order_relaxed) != CancelRequest::None);
695 }
696 );
697 // here lane_->doneMutex is locked again
698 lane_->waiting_on = nullptr;
699 lane_->status.store(Lane::Running, std::memory_order_release); // Resuming -> Running
700 }
701 } else {
702 _shouldClose = true;
745 } 703 }
746 } while (_rc == LuaError::YIELD); 704 } while (!_shouldClose);
747 if (_rc != LuaError::OK) { // : err... 705 if (_rc == LuaError::YIELD) {
706#if LUA_VERSION_NUM >= 504
707 lua_State* const _S{ lane_->S };
708 STACK_CHECK_START_REL(_S, 0);
709 // lua_closethread cleans the stack, meaning we lose the yielded values! -> store
710 lua_xmove(_L, _S, lane_->nresults);
711 // lane is cancelled before completion (for example at Lanes shutdown), close everything
712 _rc = static_cast<LuaError>(lua_closethread(_L, nullptr)); // L: ... retvals|err <close_err>
713 // then restore the yielded values
714 if (_rc == LuaError::OK) {
715 lua_xmove(_S, _L, lane_->nresults);
716 } else {
717 lua_pop(_S, lane_->nresults);
718 }
719 STACK_CHECK(_S, 0);
720
721#else // LUA_VERSION_NUM
722 // Lua prior to 5.4 do not have lua_closethread.
723 _rc = LuaError::OK;
724#endif // LUA_VERSION_NUM
725 }
726 if (_rc != LuaError::OK) { // an error occurred // L: err...
748 // for some reason, in my tests with Lua 5.4, when the coroutine raises an error, I have 3 copies of it on the stack 727 // for some reason, in my tests with Lua 5.4, when the coroutine raises an error, I have 3 copies of it on the stack
749 // or false + the error message when running Lua 5.1 728 // or false + the error message when running Lua 5.1
750 // since the rest of our code wants only the error message, let us keep only the latter. 729 // since the rest of our code wants only the error message, let us keep only the latter.
@@ -769,7 +748,7 @@ static void lane_main(Lane* const lane_)
769 // in case of error and if it exists, fetch stack trace from registry and push it 748 // in case of error and if it exists, fetch stack trace from registry and push it
770 lane_->nresults += PushStackTrace(_L, lane_->errorTraceLevel, _rc, StackIndex{ 1 }); // L: retvals|error [trace] 749 lane_->nresults += PushStackTrace(_L, lane_->errorTraceLevel, _rc, StackIndex{ 1 }); // L: retvals|error [trace]
771 750
772 DEBUGSPEW_CODE(DebugSpew(lane_->U) << "Lane " << _L << " body: " << GetErrcodeName(_rc) << " (" << (kCancelError.equals(_L, StackIndex{ 1 }) ? "cancelled" : luaG_typename(_L, StackIndex{ 1 })) << ")" << std::endl); 751 DEBUGSPEW_CODE(DebugSpew(lane_->U) << "Lane " << _L << " body: " << GetErrcodeName(_rc) << " (" << (kCancelError.equals(_L, StackIndex{ 1 }) ? "cancelled" : luaW_typename(_L, StackIndex{ 1 })) << ")" << std::endl);
773 // Call finalizers, if the script has set them up. 752 // Call finalizers, if the script has set them up.
774 // If the lane is not a coroutine, there is only a regular state, so everything is the same whether we use S or L. 753 // If the lane is not a coroutine, there is only a regular state, so everything is the same whether we use S or L.
775 // If the lane is a coroutine, this has to be done from the master state (S), not the thread (L), because we can't lua_pcall in a thread state 754 // If the lane is a coroutine, this has to be done from the master state (S), not the thread (L), because we can't lua_pcall in a thread state
@@ -783,10 +762,12 @@ static void lane_main(Lane* const lane_)
783 if (lane_->selfdestructRemove()) { // check and remove (under lock!) 762 if (lane_->selfdestructRemove()) { // check and remove (under lock!)
784 // We're a free-running thread and no-one is there to clean us up. 763 // We're a free-running thread and no-one is there to clean us up.
785 lane_->closeState(); 764 lane_->closeState();
786 lane_->U->selfdestructMutex.lock(); 765
787 // done with lua_close(), terminal shutdown sequence may proceed 766 // let's try not to crash if the lane didn't terminate gracefully and the Universe met its end
788 lane_->U->selfdestructingCount.fetch_sub(1, std::memory_order_release); 767 if (!lane_->flaggedAfterUniverseGC.load(std::memory_order_relaxed)) {
789 lane_->U->selfdestructMutex.unlock(); 768 // done with lua_close(), terminal shutdown sequence may proceed
769 lane_->U->selfdestructingCount.fetch_sub(1, std::memory_order_release);
770 }
790 771
791 // we destroy ourselves, therefore our thread member too, from inside the thread body 772 // we destroy ourselves, therefore our thread member too, from inside the thread body
792 // detach so that we don't try to join, as this doesn't seem a good idea 773 // detach so that we don't try to join, as this doesn't seem a good idea
@@ -807,6 +788,8 @@ static void lane_main(Lane* const lane_)
807// ################################################################################################# 788// #################################################################################################
808 789
809#if LUA_VERSION_NUM >= 504 790#if LUA_VERSION_NUM >= 504
791
792// __close(lane_ud, <err>)
810static LUAG_FUNC(lane_close) 793static LUAG_FUNC(lane_close)
811{ 794{
812 [[maybe_unused]] Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: lane err|nil 795 [[maybe_unused]] Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: lane err|nil
@@ -814,12 +797,13 @@ static LUAG_FUNC(lane_close)
814 lua_settop(L_, 1); // L_: lane 797 lua_settop(L_, 1); // L_: lane
815 798
816 // no error if the lane body doesn't return a non-nil first value 799 // no error if the lane body doesn't return a non-nil first value
817 luaG_pushstring(L_, "close"); // L_: lane "close" 800 luaW_pushstring(L_, "close"); // L_: lane "close"
818 lua_pushcclosure(L_, LG_lane_join, 1); // L_: lane join() 801 lua_pushcclosure(L_, LG_lane_join, 1); // L_: lane join()
819 lua_insert(L_, 1); // L_: join() lane 802 lua_insert(L_, 1); // L_: join() lane
820 lua_call(L_, 1, LUA_MULTRET); // L_: join() results 803 lua_call(L_, 1, LUA_MULTRET); // L_: join() results
821 return lua_gettop(L_); 804 return lua_gettop(L_);
822} 805}
806
823#endif // LUA_VERSION_NUM >= 504 807#endif // LUA_VERSION_NUM >= 504
824 808
825// ################################################################################################# 809// #################################################################################################
@@ -843,9 +827,9 @@ static LUAG_FUNC(lane_gc)
843 // if there a gc callback? 827 // if there a gc callback?
844 lua_getiuservalue(L_, StackIndex{ 1 }, UserValueIndex{ 1 }); // L_: ud uservalue 828 lua_getiuservalue(L_, StackIndex{ 1 }, UserValueIndex{ 1 }); // L_: ud uservalue
845 kLaneGC.pushKey(L_); // L_: ud uservalue __gc 829 kLaneGC.pushKey(L_); // L_: ud uservalue __gc
846 if (luaG_rawget(L_, StackIndex{ -2 }) != LuaType::NIL) { // L_: ud uservalue gc_cb|nil 830 if (luaW_rawget(L_, StackIndex{ -2 }) != LuaType::NIL) { // L_: ud uservalue gc_cb|nil
847 lua_remove(L_, -2); // L_: ud gc_cb|nil 831 lua_remove(L_, -2); // L_: ud gc_cb|nil
848 luaG_pushstring(L_, _lane->getDebugName()); // L_: ud gc_cb name 832 luaW_pushstring(L_, _lane->getDebugName()); // L_: ud gc_cb name
849 _have_gc_cb = true; 833 _have_gc_cb = true;
850 } else { 834 } else {
851 lua_pop(L_, 2); // L_: ud 835 lua_pop(L_, 2); // L_: ud
@@ -856,7 +840,7 @@ static LUAG_FUNC(lane_gc)
856 // still running: will have to be cleaned up later 840 // still running: will have to be cleaned up later
857 _lane->selfdestructAdd(); 841 _lane->selfdestructAdd();
858 if (_have_gc_cb) { 842 if (_have_gc_cb) {
859 luaG_pushstring(L_, "selfdestruct"); // L_: ud gc_cb name status 843 luaW_pushstring(L_, "selfdestruct"); // L_: ud gc_cb name status
860 lua_call(L_, 2, 0); // L_: ud 844 lua_call(L_, 2, 0); // L_: ud
861 } 845 }
862 return 0; 846 return 0;
@@ -871,7 +855,7 @@ static LUAG_FUNC(lane_gc)
871 855
872 // do this after lane cleanup in case the callback triggers an error 856 // do this after lane cleanup in case the callback triggers an error
873 if (_have_gc_cb) { 857 if (_have_gc_cb) {
874 luaG_pushstring(L_, "closed"); // L_: ud gc_cb name status 858 luaW_pushstring(L_, "closed"); // L_: ud gc_cb name status
875 lua_call(L_, 2, 0); // L_: ud 859 lua_call(L_, 2, 0); // L_: ud
876 } 860 }
877 return 0; 861 return 0;
@@ -916,7 +900,7 @@ void Lane::applyDebugName() const
916{ 900{
917 if constexpr (HAVE_DECODA_SUPPORT()) { 901 if constexpr (HAVE_DECODA_SUPPORT()) {
918 // to see VM name in Decoda debugger Virtual Machine window 902 // to see VM name in Decoda debugger Virtual Machine window
919 luaG_pushstring(L, debugName); // L: ... "name" 903 luaW_pushstring(L, debugName); // L: ... "name"
920 lua_setglobal(L, "decoda_name"); // L: ... 904 lua_setglobal(L, "decoda_name"); // L: ...
921 } 905 }
922 // and finally set the OS thread name 906 // and finally set the OS thread name
@@ -941,7 +925,8 @@ CancelResult Lane::cancel(CancelOp const op_, std::chrono::time_point<std::chron
941 925
942 // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here 926 // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here
943 // We can read status without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN) 927 // We can read status without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN)
944 if (status.load(std::memory_order_acquire) >= Lane::Done) { 928 auto const _status{ status.load(std::memory_order_acquire) };
929 if (_status == Lane::Done || _status == Lane::Error || _status == Lane::Cancelled) {
945 // say "ok" by default, including when lane is already done 930 // say "ok" by default, including when lane is already done
946 return CancelResult::Cancelled; 931 return CancelResult::Cancelled;
947 } 932 }
@@ -968,14 +953,15 @@ CancelResult Lane::internalCancel(CancelRequest const rq_, std::chrono::time_poi
968 // lane_->thread.get_stop_source().request_stop(); 953 // lane_->thread.get_stop_source().request_stop();
969 } 954 }
970 if (wakeLane_ == WakeLane::Yes) { // wake the thread so that execution returns from any pending linda operation if desired 955 if (wakeLane_ == WakeLane::Yes) { // wake the thread so that execution returns from any pending linda operation if desired
971 if (status.load(std::memory_order_acquire) == Lane::Waiting) { // waiting_on is updated under control of status acquire/release semantics 956 auto const _status{ status.load(std::memory_order_acquire) };
957 if (_status == Lane::Waiting || _status == Lane::Suspended) { // waiting_on is updated under control of status acquire/release semantics
972 if (std::condition_variable* const _waiting_on{ waiting_on }) { 958 if (std::condition_variable* const _waiting_on{ waiting_on }) {
973 _waiting_on->notify_all(); 959 _waiting_on->notify_all();
974 } 960 }
975 } 961 }
976 } 962 }
977 // wait until the lane stops working with its state (either Suspended or Done+) 963 // wait until the lane stops working with its state (either Suspended or Done+)
978 CancelResult const result{ waitForCompletion(until_) ? CancelResult::Cancelled : CancelResult::Timeout }; 964 CancelResult const result{ waitForCompletion(until_, false) ? CancelResult::Cancelled : CancelResult::Timeout };
979 return result; 965 return result;
980} 966}
981 967
@@ -1027,7 +1013,7 @@ void Lane::PushMetatable(lua_State* const L_)
1027{ 1013{
1028 STACK_CHECK_START_REL(L_, 0); 1014 STACK_CHECK_START_REL(L_, 0);
1029 if (luaL_newmetatable(L_, kLaneMetatableName.data())) { // L_: mt 1015 if (luaL_newmetatable(L_, kLaneMetatableName.data())) { // L_: mt
1030 luaG_registerlibfuncs(L_, local::sLaneFunctions); 1016 luaW_registerlibfuncs(L_, local::sLaneFunctions);
1031 // cache error() and tostring() 1017 // cache error() and tostring()
1032 kCachedError.pushKey(L_); // L_: mt kCachedError 1018 kCachedError.pushKey(L_); // L_: mt kCachedError
1033 lua_getglobal(L_, "error"); // L_: mt kCachedError error() 1019 lua_getglobal(L_, "error"); // L_: mt kCachedError error()
@@ -1036,7 +1022,7 @@ void Lane::PushMetatable(lua_State* const L_)
1036 lua_getglobal(L_, "tostring"); // L_: mt kCachedTostring tostring() 1022 lua_getglobal(L_, "tostring"); // L_: mt kCachedTostring tostring()
1037 lua_rawset(L_, -3); // L_: mt 1023 lua_rawset(L_, -3); // L_: mt
1038 // hide the actual metatable from getmetatable() 1024 // hide the actual metatable from getmetatable()
1039 luaG_pushstring(L_, kLaneMetatableName); // L_: mt "Lane" 1025 luaW_pushstring(L_, kLaneMetatableName); // L_: mt "Lane"
1040 lua_setfield(L_, -2, "__metatable"); // L_: mt 1026 lua_setfield(L_, -2, "__metatable"); // L_: mt
1041 } 1027 }
1042 STACK_CHECK(L_, 1); 1028 STACK_CHECK(L_, 1);
@@ -1049,7 +1035,7 @@ void Lane::pushStatusString(lua_State* const L_) const
1049 std::string_view const _str{ threadStatusString() }; 1035 std::string_view const _str{ threadStatusString() };
1050 LUA_ASSERT(L_, !_str.empty()); 1036 LUA_ASSERT(L_, !_str.empty());
1051 1037
1052 luaG_pushstring(L_, _str); 1038 luaW_pushstring(L_, _str);
1053} 1039}
1054 1040
1055// ################################################################################################# 1041// #################################################################################################
@@ -1108,12 +1094,88 @@ void Lane::pushIndexedResult(lua_State* const L_, int const key_) const
1108// ################################################################################################# 1094// #################################################################################################
1109 1095
1110[[nodiscard]] 1096[[nodiscard]]
1097int Lane::pushStoredResults(lua_State* const L_) const
1098{
1099 STACK_CHECK_START_ABS(L_, 1); // should only have the lane UD on the stack
1100 static constexpr StackIndex kIdxSelf{ 1 };
1101 static constexpr UserValueIndex kUvResults{ 1 };
1102 LUA_ASSERT(L_, ToLane(L_, kIdxSelf) == this); // L_: lane
1103 lua_getiuservalue(L_, kIdxSelf, kUvResults); // L_: lane {uv}
1104 lua_rawgeti(L_, kIdxTop, 0); // L_: lane {uv} stored
1105 int const _stored{ static_cast<int>(lua_tointeger(L_, kIdxTop)) };
1106 lua_pop(L_, 1); // L_: lane {uv}
1107
1108 int _ret{};
1109 STACK_GROW(L_, std::max(3, _stored + 1));
1110 switch (status.load(std::memory_order_acquire)) {
1111 case Lane::Suspended:
1112 raise_luaL_error(L_, "INTERNAL ERROR: SHOULD NEVER BE SUSPENDED HERE");
1113 break;
1114
1115 case Lane::Done: // got regular return values
1116 if (_stored > 0) {
1117 for (int _i = 2; _i <= _stored; ++_i) {
1118 lua_rawgeti(L_, 2, _i); // L_: lane {uv} results2...N
1119 }
1120 lua_rawgeti(L_, 2, 1); // L_: lane {uv} results2...N result1
1121 lua_replace(L_, 2); // L_: lane results
1122 } else {
1123 lua_pop(L_, 1); // L_: lane
1124 }
1125 // we precede the lane body returned values with boolean true
1126 lua_pushboolean(L_, 1); // L_: lane results true
1127 lua_replace(L_, 1); // L_: true results
1128 _ret = _stored + 1;
1129 STACK_CHECK(L_, _ret);
1130 break;
1131
1132 case Lane::Error:
1133 {
1134 LUA_ASSERT(L_, _stored == 2 || _stored == 3); // contains nil error [trace]
1135 lua_rawgeti(L_, 2, 2); // L_: lane {uv} <error>
1136 lua_rawgeti(L_, 2, 3); // L_: lane {uv} <error> <trace>|nil
1137 if (lua_isnil(L_, -1)) {
1138 lua_replace(L_, 2); // L_: lane nil <error>
1139 } else {
1140 lua_rawgeti(L_, 2, 1); // L_: lane {uv} <error> <trace> nil
1141 lua_replace(L_, 2); // L_: lane nil <error> <trace>
1142 }
1143 _ret = _stored; // 2 or 3
1144 STACK_CHECK(L_, _ret + 1); // stack still contains the lane UD below
1145 }
1146 break;
1147
1148 case Lane::Cancelled:
1149 {
1150 LUA_ASSERT(L_, _stored == 2);
1151 lua_rawgeti(L_, 2, 2); // L_: lane {uv} cancel_error
1152 lua_rawgeti(L_, 2, 1); // L_: lane {uv} cancel_error nil
1153 lua_replace(L_, -3); // L_: lane nil cancel_error
1154 LUA_ASSERT(L_, lua_isnil(L_, -2) && kCancelError.equals(L_, kIdxTop));
1155 _ret = 2;
1156 STACK_CHECK(L_, _ret + 1); // stack still contains the lane UD below
1157 }
1158 break;
1159
1160 default:
1161 DEBUGSPEW_CODE(DebugSpew(nullptr) << "Unknown Lane status: " << static_cast<int>(_lane->status.load(std::memory_order_relaxed)) << std::endl);
1162 LUA_ASSERT(L_, false);
1163 _ret = 0;
1164 STACK_CHECK(L_, _ret);
1165 }
1166 LUA_ASSERT(L_, lua_gettop(L_) >= _ret);
1167 return _ret;
1168}
1169
1170// #################################################################################################
1171
1172[[nodiscard]]
1111std::string_view Lane::pushErrorTraceLevel(lua_State* L_) const 1173std::string_view Lane::pushErrorTraceLevel(lua_State* L_) const
1112{ 1174{
1113 std::string_view const _str{ errorTraceLevelString() }; 1175 std::string_view const _str{ errorTraceLevelString() };
1114 LUA_ASSERT(L_, !_str.empty()); 1176 LUA_ASSERT(L_, !_str.empty());
1115 1177
1116 return luaG_pushstring(L_, _str); 1178 return luaW_pushstring(L_, _str);
1117} 1179}
1118 1180
1119// ################################################################################################# 1181// #################################################################################################
@@ -1124,7 +1186,7 @@ void Lane::resetResultsStorage(lua_State* const L_, StackIndex const self_idx_)
1124{ 1186{
1125 STACK_GROW(L_, 4); 1187 STACK_GROW(L_, 4);
1126 STACK_CHECK_START_REL(L_, 0); 1188 STACK_CHECK_START_REL(L_, 0);
1127 StackIndex const _self_idx{ luaG_absindex(L_, self_idx_) }; 1189 StackIndex const _self_idx{ luaW_absindex(L_, self_idx_) };
1128 LUA_ASSERT(L_, ToLane(L_, _self_idx) == this); // L_: ... self ... 1190 LUA_ASSERT(L_, ToLane(L_, _self_idx) == this); // L_: ... self ...
1129 // create the new table 1191 // create the new table
1130 lua_newtable(L_); // L_: ... self ... {} 1192 lua_newtable(L_); // L_: ... self ... {}
@@ -1158,7 +1220,7 @@ void Lane::securizeDebugName(lua_State* const L_)
1158 lua_newtable(L_); // L_: lane ... {uv} {} 1220 lua_newtable(L_); // L_: lane ... {uv} {}
1159 { 1221 {
1160 std::lock_guard<std::mutex> _guard{ debugNameMutex }; 1222 std::lock_guard<std::mutex> _guard{ debugNameMutex };
1161 debugName = luaG_pushstring(L_, debugName); // L_: lane ... {uv} {} name 1223 debugName = luaW_pushstring(L_, debugName); // L_: lane ... {uv} {} name
1162 } 1224 }
1163 lua_rawset(L_, -3); // L_: lane ... {uv} 1225 lua_rawset(L_, -3); // L_: lane ... {uv}
1164 lua_pop(L_, 1); // L_: lane 1226 lua_pop(L_, 1); // L_: lane
@@ -1167,11 +1229,11 @@ void Lane::securizeDebugName(lua_State* const L_)
1167 1229
1168// ################################################################################################# 1230// #################################################################################################
1169 1231
1170void Lane::startThread(int const priority_) 1232void Lane::startThread(lua_State* const L_, int const priority_, NativePrioFlag native_)
1171{ 1233{
1172 thread = std::thread([this]() { lane_main(this); }); 1234 thread = std::thread([this]() { lane_main(this); });
1173 if (priority_ != kThreadPrioDefault) { 1235 if (priority_ != kThreadPrioDefault) {
1174 THREAD_SET_PRIORITY(thread, priority_, U->sudo); 1236 THREAD_SET_PRIORITY(L_, thread, priority_, native_, U->sudo);
1175 } 1237 }
1176} 1238}
1177 1239
@@ -1181,13 +1243,13 @@ void Lane::storeDebugName(std::string_view const& name_)
1181{ 1243{
1182 STACK_CHECK_START_REL(L, 0); 1244 STACK_CHECK_START_REL(L, 0);
1183 // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... 1245 // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global...
1184 kLaneNameRegKey.setValue(L, [name = name_](lua_State* L_) { luaG_pushstring(L_, name); }); 1246 kLaneNameRegKey.setValue(L, [name = name_](lua_State* L_) { luaW_pushstring(L_, name); });
1185 STACK_CHECK(L, 0); 1247 STACK_CHECK(L, 0);
1186 kLaneNameRegKey.pushValue(L); // L: ... "name" ... 1248 kLaneNameRegKey.pushValue(L); // L: ... "name" ...
1187 // keep a direct view on the stored string 1249 // keep a direct view on the stored string
1188 { 1250 {
1189 std::lock_guard<std::mutex> _guard{ debugNameMutex }; 1251 std::lock_guard<std::mutex> _guard{ debugNameMutex };
1190 debugName = luaG_tostring(L, kIdxTop); 1252 debugName = luaW_tostring(L, kIdxTop);
1191 } 1253 }
1192 lua_pop(L, 1); 1254 lua_pop(L, 1);
1193 STACK_CHECK(L, 0); 1255 STACK_CHECK(L, 0);
@@ -1207,20 +1269,21 @@ int Lane::storeResults(lua_State* const L_)
1207 lua_getiuservalue(L_, kIdxSelf, UserValueIndex{ 1 }); // L_: lane ... {uv} 1269 lua_getiuservalue(L_, kIdxSelf, UserValueIndex{ 1 }); // L_: lane ... {uv}
1208 StackIndex const _tidx{ lua_gettop(L_) }; 1270 StackIndex const _tidx{ lua_gettop(L_) };
1209 1271
1210 int _stored{}; 1272 // if the results were already stored from a previous indexing, just say how many values we have in store
1211 if (nresults == 0) { 1273 if (!L) {
1212 lua_rawgeti(L_, -1, 0); // L_: lane ... {uv} nresults 1274 lua_rawgeti(L_, -1, 0); // L_: lane ... {uv} nresults
1213 _stored = static_cast<int>(lua_tointeger(L_, -1)); 1275 auto const _stored{ static_cast<int>(lua_tointeger(L_, -1)) };
1214 lua_pop(L_, 2); 1276 lua_pop(L_, 2);
1215 STACK_CHECK(L_, 0); 1277 STACK_CHECK(L_, 0);
1216 return _stored; 1278 return _stored;
1217 } 1279 }
1218 1280
1281 int _stored{};
1219 switch (status.load(std::memory_order_acquire)) { 1282 switch (status.load(std::memory_order_acquire)) {
1220 default: 1283 default:
1221 // this is an internal error, we probably never get here 1284 // this is an internal error, we probably never get here
1222 lua_settop(L_, 0); // L_: 1285 lua_settop(L_, 0); // L_:
1223 luaG_pushstring(L_, "Unexpected status: "); // L_: "Unexpected status: " 1286 luaW_pushstring(L_, "Unexpected status: "); // L_: "Unexpected status: "
1224 pushStatusString(L_); // L_: "Unexpected status: " "<status>" 1287 pushStatusString(L_); // L_: "Unexpected status: " "<status>"
1225 lua_concat(L_, 2); // L_: "Unexpected status: <status>" 1288 lua_concat(L_, 2); // L_: "Unexpected status: <status>"
1226 raise_lua_error(L_); 1289 raise_lua_error(L_);
@@ -1295,12 +1358,13 @@ int Lane::storeResults(lua_State* const L_)
1295//--- 1358//---
1296// str= thread_status( lane ) 1359// str= thread_status( lane )
1297// 1360//
1298// "pending" -> | ("running" <-> "waiting") <-> "suspended" <-> "resuming" | -> "done"/"error"/"cancelled" 1361// "pending" -> | ("running" <-> "waiting") <-> "suspended" <-> "resuming/closing" | -> "done"/"error"/"cancelled"
1299 1362
1300// "pending" not started yet 1363// "pending" not started yet
1301// "running" started, doing its work.. 1364// "running" started, doing its work..
1302// "suspended" returned from a lua_resume 1365// "suspended" returned from a lua_resume
1303// "resuming" told by its parent state to resume 1366// "resuming" told by its parent state to resume
1367// "closing" not observable from the outside: happens only inside a join()/indexation call to unblock a suspended coroutine Lane so that it can join properly
1304// "waiting" blocked in a send()/receive() 1368// "waiting" blocked in a send()/receive()
1305// "done" finished, results are there 1369// "done" finished, results are there
1306// "error" finished at an error, error value is there 1370// "error" finished at an error, error value is there
@@ -1311,7 +1375,7 @@ std::string_view Lane::threadStatusString() const
1311{ 1375{
1312 static constexpr std::string_view kStrs[] = { 1376 static constexpr std::string_view kStrs[] = {
1313 "pending", 1377 "pending",
1314 "running", "suspended", "resuming", 1378 "running", "suspended", "resuming", "closing",
1315 "waiting", 1379 "waiting",
1316 "done", "error", "cancelled" 1380 "done", "error", "cancelled"
1317 }; 1381 };
@@ -1319,12 +1383,13 @@ std::string_view Lane::threadStatusString() const
1319 static_assert(1 == static_cast<std::underlying_type_t<Lane::Status>>(Running)); 1383 static_assert(1 == static_cast<std::underlying_type_t<Lane::Status>>(Running));
1320 static_assert(2 == static_cast<std::underlying_type_t<Lane::Status>>(Suspended)); 1384 static_assert(2 == static_cast<std::underlying_type_t<Lane::Status>>(Suspended));
1321 static_assert(3 == static_cast<std::underlying_type_t<Lane::Status>>(Resuming)); 1385 static_assert(3 == static_cast<std::underlying_type_t<Lane::Status>>(Resuming));
1322 static_assert(4 == static_cast<std::underlying_type_t<Lane::Status>>(Waiting)); 1386 static_assert(4 == static_cast<std::underlying_type_t<Lane::Status>>(Closing));
1323 static_assert(5 == static_cast<std::underlying_type_t<Lane::Status>>(Done)); 1387 static_assert(5 == static_cast<std::underlying_type_t<Lane::Status>>(Waiting));
1324 static_assert(6 == static_cast<std::underlying_type_t<Lane::Status>>(Error)); 1388 static_assert(6 == static_cast<std::underlying_type_t<Lane::Status>>(Done));
1325 static_assert(7 == static_cast<std::underlying_type_t<Lane::Status>>(Cancelled)); 1389 static_assert(7 == static_cast<std::underlying_type_t<Lane::Status>>(Error));
1390 static_assert(8 == static_cast<std::underlying_type_t<Lane::Status>>(Cancelled));
1326 auto const _status{ static_cast<std::underlying_type_t<Lane::Status>>(status.load(std::memory_order_acquire)) }; 1391 auto const _status{ static_cast<std::underlying_type_t<Lane::Status>>(status.load(std::memory_order_acquire)) };
1327 if (_status < 0 || _status > 7) { // should never happen, but better safe than sorry 1392 if (_status < 0 || _status > 8) { // should never happen, but better safe than sorry
1328 return ""; 1393 return "";
1329 } 1394 }
1330 return kStrs[_status]; 1395 return kStrs[_status];
@@ -1332,17 +1397,52 @@ std::string_view Lane::threadStatusString() const
1332 1397
1333// ################################################################################################# 1398// #################################################################################################
1334 1399
1335bool Lane::waitForCompletion(std::chrono::time_point<std::chrono::steady_clock> until_) 1400bool Lane::waitForCompletion(std::chrono::time_point<std::chrono::steady_clock> until_, bool const _acceptSuspended)
1336{ 1401{
1337 std::unique_lock _guard{ doneMutex }; 1402 std::unique_lock _guard{ doneMutex };
1338 // std::stop_token token{ thread.get_stop_token() }; 1403 // std::stop_token token{ thread.get_stop_token() };
1339 // return doneCondVar.wait_until(lock, token, secs_, [this](){ return status >= Lane::Done; }); 1404 // return doneCondVar.wait_until(lock, token, secs_, [this](){ return status >= Lane::Done; });
1340 1405
1341 // wait until the lane stops working with its state (either Suspended or Done+) 1406 // wait until the lane exits lane_main (which is the only place where status can become one of the 3 tested values)
1342 return doneCondVar.wait_until(_guard, until_, [this]() 1407 return doneCondVar.wait_until(_guard, until_, [this, suspended = _acceptSuspended ? Lane::Suspended : Lane::Done]() {
1408 auto const _status{ status.load(std::memory_order_acquire) };
1409 return _status == Lane::Done || _status == Lane::Error || _status == Lane::Cancelled || _status == suspended;
1410 });
1411}
1412
1413// #################################################################################################
1414
1415[[nodiscard]]
1416bool Lane::waitForJoin(lua_State* const L_, std::chrono::time_point<std::chrono::steady_clock> until_)
1417{
1418 // wait until suspended or done
1419 {
1420 bool const _done{ !thread.joinable() || waitForCompletion(until_, true) };
1421
1422 if (!_done) {
1423 lua_pushnil(L_); // L_: lane nil
1424 luaW_pushstring(L_, "timeout"); // L_: lane nil "timeout"
1425 return false;
1426 }
1427 }
1428
1429 // if lane is suspended, force the yield loop to break, and the termination of the thread
1430 if (status.load(std::memory_order_acquire) == Lane::Suspended) {
1431 LUA_ASSERT(L_, waiting_on == &doneCondVar);
1432 status.store(Lane::Closing, std::memory_order_release);
1433 doneCondVar.notify_all();
1434 // wait until done
1343 { 1435 {
1344 auto const _status{ status.load(std::memory_order_acquire) }; 1436 bool const _done{ !thread.joinable() || waitForCompletion(until_, true) };
1345 return _status == Lane::Suspended || _status >= Lane::Done; 1437
1438 if (!_done) {
1439 lua_pushnil(L_); // L_: lane nil
1440 luaW_pushstring(L_, "timeout"); // L_: lane nil "timeout"
1441 return false;
1442 }
1346 } 1443 }
1347 ); 1444 LUA_ASSERT(L_, status.load(std::memory_order_acquire) != Lane::Closing);
1445 }
1446 LUA_ASSERT(L_, status.load(std::memory_order_acquire) != Lane::Suspended);
1447 return true;
1348} 1448}
diff --git a/src/lane.hpp b/src/lane.hpp
index 5fe36b6..bd328b1 100644
--- a/src/lane.hpp
+++ b/src/lane.hpp
@@ -56,6 +56,7 @@ class Lane final
56 /* 56 /*
57 Pending: The Lua VM hasn't done anything yet. 57 Pending: The Lua VM hasn't done anything yet.
58 Resuming: The user requested the lane to resume execution from Suspended state. 58 Resuming: The user requested the lane to resume execution from Suspended state.
59 Closing: The user is joining the lane, specifically interrupting a suspended Lane.
59 Suspended: returned from lua_resume, waiting for the client to request a lua_resume. 60 Suspended: returned from lua_resume, waiting for the client to request a lua_resume.
60 Running, Suspended, Waiting: Thread is inside the Lua VM. 61 Running, Suspended, Waiting: Thread is inside the Lua VM.
61 Done, Error, Cancelled: Thread execution is outside the Lua VM. It can be lua_close()d. 62 Done, Error, Cancelled: Thread execution is outside the Lua VM. It can be lua_close()d.
@@ -66,6 +67,7 @@ class Lane final
66 Running, 67 Running,
67 Suspended, 68 Suspended,
68 Resuming, 69 Resuming,
70 Closing,
69 Waiting, 71 Waiting,
70 Done, 72 Done,
71 Error, 73 Error,
@@ -199,12 +201,14 @@ class Lane final
199 static void PushMetatable(lua_State* L_); 201 static void PushMetatable(lua_State* L_);
200 void pushStatusString(lua_State* L_) const; 202 void pushStatusString(lua_State* L_) const;
201 void pushIndexedResult(lua_State* L_, int key_) const; 203 void pushIndexedResult(lua_State* L_, int key_) const;
204 [[nodiscard]]
205 int pushStoredResults(lua_State* L_) const;
202 void resetResultsStorage(lua_State* L_, StackIndex self_idx_); 206 void resetResultsStorage(lua_State* L_, StackIndex self_idx_);
203 void selfdestructAdd(); 207 void selfdestructAdd();
204 [[nodiscard]] 208 [[nodiscard]]
205 bool selfdestructRemove(); 209 bool selfdestructRemove();
206 void securizeDebugName(lua_State* L_); 210 void securizeDebugName(lua_State* L_);
207 void startThread(int priority_); 211 void startThread(lua_State* L_, int priority_, NativePrioFlag native_);
208 void storeDebugName( std::string_view const& name_); 212 void storeDebugName( std::string_view const& name_);
209 [[nodiscard]] 213 [[nodiscard]]
210 int storeResults(lua_State* L_); 214 int storeResults(lua_State* L_);
@@ -212,7 +216,9 @@ class Lane final
212 std::string_view threadStatusString() const; 216 std::string_view threadStatusString() const;
213 // wait until the lane stops working with its state (either Suspended or Done+) 217 // wait until the lane stops working with its state (either Suspended or Done+)
214 [[nodiscard]] 218 [[nodiscard]]
215 bool waitForCompletion(std::chrono::time_point<std::chrono::steady_clock> until_); 219 bool waitForCompletion(std::chrono::time_point<std::chrono::steady_clock> until_, bool const _acceptSuspended);
220 [[nodiscard]]
221 bool waitForJoin(lua_State* _L, std::chrono::time_point<std::chrono::steady_clock> until_);
216}; 222};
217 223
218// ################################################################################################# 224// #################################################################################################
diff --git a/src/lanes.cpp b/src/lanes.cpp
index d1a353b..4373aee 100644
--- a/src/lanes.cpp
+++ b/src/lanes.cpp
@@ -137,13 +137,15 @@ LUAG_FUNC(set_singlethreaded)
137LUAG_FUNC(set_thread_priority) 137LUAG_FUNC(set_thread_priority)
138{ 138{
139 lua_Integer const _prio{ luaL_checkinteger(L_, 1) }; 139 lua_Integer const _prio{ luaL_checkinteger(L_, 1) };
140 NativePrioFlag const _native{ std::string_view{ "native" } == luaL_optstring(L_, 2, "mapped") };
140 // public Lanes API accepts a generic range -3/+3 141 // public Lanes API accepts a generic range -3/+3
141 // that will be remapped into the platform-specific scheduler priority scheme 142 // that will be remapped into the platform-specific scheduler priority scheme
142 // On some platforms, -3 is equivalent to -2 and +3 to +2 143 // On some platforms, -3 is equivalent to -2 and +3 to +2
143 if (_prio < kThreadPrioMin || _prio > kThreadPrioMax) { 144 if (!_native && (_prio < kThreadPrioMin || _prio > kThreadPrioMax)) {
144 raise_luaL_error(L_, "priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _prio); 145 raise_luaL_error(L_, "priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _prio);
145 } 146 }
146 THREAD_SET_PRIORITY(static_cast<int>(_prio), Universe::Get(L_)->sudo); 147
148 THREAD_SET_PRIORITY(L_, static_cast<int>(_prio), _native, Universe::Get(L_)->sudo);
147 return 0; 149 return 0;
148} 150}
149 151
@@ -155,7 +157,8 @@ LUAG_FUNC(set_thread_affinity)
155 if (_affinity <= 0) { 157 if (_affinity <= 0) {
156 raise_luaL_error(L_, "invalid affinity (%d)", _affinity); 158 raise_luaL_error(L_, "invalid affinity (%d)", _affinity);
157 } 159 }
158 THREAD_SET_AFFINITY(static_cast<unsigned int>(_affinity)); 160
161 THREAD_SET_AFFINITY(L_, static_cast<unsigned int>(_affinity));
159 return 0; 162 return 0;
160} 163}
161 164
@@ -170,17 +173,21 @@ LUAG_FUNC(sleep)
170 lua_pushcfunction(L_, LG_linda_receive); // L_: duration|nil receive() 173 lua_pushcfunction(L_, LG_linda_receive); // L_: duration|nil receive()
171 STACK_CHECK_START_REL(L_, 0); // we pushed the function we intend to call, now prepare the arguments 174 STACK_CHECK_START_REL(L_, 0); // we pushed the function we intend to call, now prepare the arguments
172 _U->timerLinda->push(L_); // L_: duration|nil receive() timerLinda 175 _U->timerLinda->push(L_); // L_: duration|nil receive() timerLinda
173 if (luaG_tostring(L_, StackIndex{ 1 }) == "indefinitely") { 176 if (luaW_tostring(L_, StackIndex{ 1 }) == "indefinitely") {
174 lua_pushnil(L_); // L_: duration? receive() timerLinda nil 177 lua_pushnil(L_); // L_: duration? receive() timerLinda nil
175 } else if (lua_isnoneornil(L_, 1)) { 178 } else if (lua_isnoneornil(L_, 1)) {
176 lua_pushnumber(L_, 0); // L_: duration? receive() timerLinda 0 179 lua_pushnumber(L_, 0); // L_: duration? receive() timerLinda 0
177 } else if (!lua_isnumber(L_, 1)) { 180 } else if (!lua_isnumber(L_, 1)) {
178 raise_luaL_argerror(L_, StackIndex{ 1 }, "invalid duration"); 181 raise_luaL_argerror(L_, StackIndex{ 1 }, "duration must be a number");
179 } 182 }
180 else { 183 else {
184 auto const _n{ lua_tonumber(L_, 1) };
185 if (_n < 0) {
186 raise_luaL_argerror(L_, StackIndex{ 1 }, "duration must be >= 0");
187 }
181 lua_pushnumber(L_, lua_tonumber(L_, 1)); // L_: duration? receive() timerLinda duration 188 lua_pushnumber(L_, lua_tonumber(L_, 1)); // L_: duration? receive() timerLinda duration
182 } 189 }
183 luaG_pushstring(L_, "ac100de1-a696-4619-b2f0-a26de9d58ab8"); // L_: duration? receive() timerLinda duration key 190 luaW_pushstring(L_, "ac100de1-a696-4619-b2f0-a26de9d58ab8"); // L_: duration? receive() timerLinda duration key
184 STACK_CHECK(L_, 3); // 3 arguments ready 191 STACK_CHECK(L_, 3); // 3 arguments ready
185 lua_call(L_, 3, LUA_MULTRET); // timerLinda:receive(duration,key) // L_: duration? result... 192 lua_call(L_, 3, LUA_MULTRET); // timerLinda:receive(duration,key) // L_: duration? result...
186 return lua_gettop(L_) - 1; 193 return lua_gettop(L_) - 1;
@@ -194,7 +201,7 @@ LUAG_FUNC(sleep)
194// upvalue[1]: _G.require 201// upvalue[1]: _G.require
195LUAG_FUNC(require) 202LUAG_FUNC(require)
196{ 203{
197 std::string_view const _name{ luaG_tostring(L_, StackIndex{ 1 }) }; // L_: "name" ... 204 std::string_view const _name{ luaW_tostring(L_, StackIndex{ 1 }) }; // L_: "name" ...
198 int const _nargs{ lua_gettop(L_) }; 205 int const _nargs{ lua_gettop(L_) };
199 DEBUGSPEW_CODE(Universe * _U{ Universe::Get(L_) }); 206 DEBUGSPEW_CODE(Universe * _U{ Universe::Get(L_) });
200 STACK_CHECK_START_REL(L_, 0); 207 STACK_CHECK_START_REL(L_, 0);
@@ -220,8 +227,8 @@ int lanes_register(lua_State* const L_)
220 if (!_U) { 227 if (!_U) {
221 raise_luaL_error(L_, "Lanes is not ready"); 228 raise_luaL_error(L_, "Lanes is not ready");
222 } 229 }
223 std::string_view const _name{ luaG_checkstring(L_, StackIndex{ 1 }) }; 230 std::string_view const _name{ luaW_checkstring(L_, StackIndex{ 1 }) };
224 LuaType const _mod_type{ luaG_type(L_, StackIndex{ 2 }) }; 231 LuaType const _mod_type{ luaW_type(L_, StackIndex{ 2 }) };
225 // ignore extra arguments, just in case 232 // ignore extra arguments, just in case
226 lua_settop(L_, 2); 233 lua_settop(L_, 2);
227 luaL_argcheck(L_, (_mod_type == LuaType::TABLE) || (_mod_type == LuaType::FUNCTION), 2, "unexpected module type"); 234 luaL_argcheck(L_, (_mod_type == LuaType::TABLE) || (_mod_type == LuaType::FUNCTION), 2, "unexpected module type");
@@ -236,9 +243,26 @@ int lanes_register(lua_State* const L_)
236 243
237// ################################################################################################# 244// #################################################################################################
238 245
246LUAG_FUNC(thread_priority_range)
247{
248 NativePrioFlag const _native{ std::string_view{ "native" } == luaL_optstring(L_, 1, "mapped") };
249 if (_native) {
250 auto const [_prio_min, _prio_max] = THREAD_NATIVE_PRIOS();
251 lua_pushinteger(L_, _prio_min);
252 lua_pushinteger(L_, _prio_max);
253 } else {
254 lua_pushinteger(L_, kThreadPrioMin);
255 lua_pushinteger(L_, kThreadPrioMax);
256 }
257 return 2;
258}
259
260// #################################################################################################
261
239//--- [] means can be nil 262//--- [] means can be nil
240// lane_ud = lane_new( function 263// lane_ud = lane_new( function
241// , [libs_str] 264// , [libs_str]
265// , [prio_is_native_bool]
242// , [priority_int] 266// , [priority_int]
243// , [globals_tbl] 267// , [globals_tbl]
244// , [package_tbl] 268// , [package_tbl]
@@ -255,15 +279,16 @@ LUAG_FUNC(lane_new)
255{ 279{
256 static constexpr StackIndex kFuncIdx{ 1 }; 280 static constexpr StackIndex kFuncIdx{ 1 };
257 static constexpr StackIndex kLibsIdx{ 2 }; 281 static constexpr StackIndex kLibsIdx{ 2 };
258 static constexpr StackIndex kPrioIdx{ 3 }; 282 static constexpr StackIndex kPrinIdx{ 3 };
259 static constexpr StackIndex kGlobIdx{ 4 }; 283 static constexpr StackIndex kPrioIdx{ 4 };
260 static constexpr StackIndex kPackIdx{ 5 }; 284 static constexpr StackIndex kGlobIdx{ 5 };
261 static constexpr StackIndex kRequIdx{ 6 }; 285 static constexpr StackIndex kPackIdx{ 6 };
262 static constexpr StackIndex kGcCbIdx{ 7 }; 286 static constexpr StackIndex kRequIdx{ 7 };
263 static constexpr StackIndex kNameIdx{ 8 }; 287 static constexpr StackIndex kGcCbIdx{ 8 };
264 static constexpr StackIndex kErTlIdx{ 9 }; 288 static constexpr StackIndex kNameIdx{ 9 };
265 static constexpr StackIndex kAsCoro{ 10 }; 289 static constexpr StackIndex kErTlIdx{ 10 };
266 static constexpr StackIndex kFixedArgsIdx{ 10 }; 290 static constexpr StackIndex kAsCoro{ 11 };
291 static constexpr StackIndex kFixedArgsIdx{ 11 };
267 292
268 int const _nargs{ lua_gettop(L_) - kFixedArgsIdx }; 293 int const _nargs{ lua_gettop(L_) - kFixedArgsIdx };
269 LUA_ASSERT(L_, _nargs >= 0); 294 LUA_ASSERT(L_, _nargs >= 0);
@@ -271,7 +296,7 @@ LUAG_FUNC(lane_new)
271 Universe* const _U{ Universe::Get(L_) }; 296 Universe* const _U{ Universe::Get(L_) };
272 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl); 297 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: setup" << std::endl);
273 298
274 std::optional<std::string_view> _libs_str{ lua_isnil(L_, kLibsIdx) ? std::nullopt : std::make_optional(luaG_tostring(L_, kLibsIdx)) }; 299 std::optional<std::string_view> _libs_str{ lua_isnil(L_, kLibsIdx) ? std::nullopt : std::make_optional(luaW_tostring(L_, kLibsIdx)) };
275 lua_State* const _S{ state::NewLaneState(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2: 300 lua_State* const _S{ state::NewLaneState(_U, SourceState{ L_ }, _libs_str) }; // L_: [fixed] ... L2:
276 STACK_CHECK_START_REL(_S, 0); 301 STACK_CHECK_START_REL(_S, 0);
277 302
@@ -333,7 +358,7 @@ LUAG_FUNC(lane_new)
333 DEBUGSPEW_CODE(DebugSpew(lane->U) << "lane_new: preparing lane userdata" << std::endl); 358 DEBUGSPEW_CODE(DebugSpew(lane->U) << "lane_new: preparing lane userdata" << std::endl);
334 STACK_CHECK_START_REL(L, 0); 359 STACK_CHECK_START_REL(L, 0);
335 // a Lane full userdata needs a single uservalue 360 // a Lane full userdata needs a single uservalue
336 Lane** const _ud{ luaG_newuserdatauv<Lane*>(L, UserValueCount{ 1 }) }; // L: ... lane 361 Lane** const _ud{ luaW_newuserdatauv<Lane*>(L, UserValueCount{ 1 }) }; // L: ... lane
337 *_ud = lane; // don't forget to store the pointer in the userdata! 362 *_ud = lane; // don't forget to store the pointer in the userdata!
338 363
339 // Set metatable for the userdata 364 // Set metatable for the userdata
@@ -357,25 +382,25 @@ LUAG_FUNC(lane_new)
357 lua_setiuservalue(L, StackIndex{ -2 }, UserValueIndex{ 1 }); // L: ... lane 382 lua_setiuservalue(L, StackIndex{ -2 }, UserValueIndex{ 1 }); // L: ... lane
358 383
359 StackIndex const _name_idx{ lua_isnoneornil(L, kNameIdx) ? kIdxNone : kNameIdx }; 384 StackIndex const _name_idx{ lua_isnoneornil(L, kNameIdx) ? kIdxNone : kNameIdx };
360 std::string_view _debugName{ (_name_idx > 0) ? luaG_tostring(L, _name_idx) : std::string_view{} }; 385 std::string_view _debugName{ (_name_idx > 0) ? luaW_tostring(L, _name_idx) : std::string_view{} };
361 if (!_debugName.empty()) 386 if (!_debugName.empty())
362 { 387 {
363 if (_debugName == "auto") { 388 if (_debugName == "auto") {
364 if (luaG_type(L, kFuncIdx) == LuaType::STRING) { 389 if (luaW_type(L, kFuncIdx) == LuaType::STRING) {
365 lua_Debug _ar; 390 lua_Debug _ar;
366 if (lua_getstack(L, 2, &_ar) == 0) { // 0 is here, 1 is lanes.gen, 2 is its caller 391 if (lua_getstack(L, 2, &_ar) == 0) { // 0 is here, 1 is lanes.gen, 2 is its caller
367 lua_getstack(L, 1, &_ar); // level 2 may not exist with LuaJIT, try again with level 1 392 lua_getstack(L, 1, &_ar); // level 2 may not exist with LuaJIT, try again with level 1
368 } 393 }
369 lua_getinfo(L, "Sl", &_ar); 394 lua_getinfo(L, "Sl", &_ar);
370 luaG_pushstring(L, "%s:%d", _ar.short_src, _ar.currentline); // L: ... lane "<name>" 395 luaW_pushstring(L, "%s:%d", _ar.short_src, _ar.currentline); // L: ... lane "<name>"
371 } else { 396 } else {
372 lua_Debug _ar; 397 lua_Debug _ar;
373 lua_pushvalue(L, kFuncIdx); // L: ... lane func 398 lua_pushvalue(L, kFuncIdx); // L: ... lane func
374 lua_getinfo(L, ">S", &_ar); // L: ... lane 399 lua_getinfo(L, ">S", &_ar); // L: ... lane
375 luaG_pushstring(L, "%s:%d", _ar.short_src, _ar.linedefined); // L: ... lane "<name>" 400 luaW_pushstring(L, "%s:%d", _ar.short_src, _ar.linedefined); // L: ... lane "<name>"
376 } 401 }
377 lua_replace(L, _name_idx); // L: ... lane 402 lua_replace(L, _name_idx); // L: ... lane
378 _debugName = luaG_tostring(L, _name_idx); 403 _debugName = luaW_tostring(L, _name_idx);
379 } 404 }
380 lane->storeDebugName(_debugName); 405 lane->storeDebugName(_debugName);
381 } 406 }
@@ -400,21 +425,22 @@ LUAG_FUNC(lane_new)
400 // public Lanes API accepts a generic range -3/+3 425 // public Lanes API accepts a generic range -3/+3
401 // that will be remapped into the platform-specific scheduler priority scheme 426 // that will be remapped into the platform-specific scheduler priority scheme
402 // On some platforms, -3 is equivalent to -2 and +3 to +2 427 // On some platforms, -3 is equivalent to -2 and +3 to +2
403 int const _priority{ 428 auto const [_priority, _native] {
404 std::invoke([L = L_]() { 429 std::invoke([L = L_]() {
430 NativePrioFlag const _native{ static_cast<bool>(lua_toboolean(L, kPrinIdx)) };
405 StackIndex const _prio_idx{ lua_isnoneornil(L, kPrioIdx) ? kIdxNone : kPrioIdx }; 431 StackIndex const _prio_idx{ lua_isnoneornil(L, kPrioIdx) ? kIdxNone : kPrioIdx };
406 if (_prio_idx == 0) { 432 if (_prio_idx == kIdxNone) {
407 return kThreadPrioDefault; 433 return std::make_pair(kThreadPrioDefault, _native);
408 } 434 }
409 int const _priority{ static_cast<int>(lua_tointeger(L, _prio_idx)) }; 435 int const _priority{ static_cast<int>(lua_tointeger(L, _prio_idx)) };
410 if ((_priority < kThreadPrioMin || _priority > kThreadPrioMax)) { 436 if (!_native && (_priority < kThreadPrioMin || _priority > kThreadPrioMax)) {
411 raise_luaL_error(L, "Priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _priority); 437 raise_luaL_error(L, "Priority out of range: %d..+%d (%d)", kThreadPrioMin, kThreadPrioMax, _priority);
412 } 438 }
413 return _priority; 439 return std::make_pair(_priority, _native);
414 }) 440 })
415 }; 441 };
416 442
417 _lane->startThread(_priority); 443 _lane->startThread(L_, _priority, _native);
418 444
419 STACK_GROW(_L2, _nargs + 3); 445 STACK_GROW(_L2, _nargs + 3);
420 STACK_GROW(L_, 3); 446 STACK_GROW(L_, 3);
@@ -439,17 +465,17 @@ LUAG_FUNC(lane_new)
439 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: process 'required' list" << std::endl); 465 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: process 'required' list" << std::endl);
440 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); 466 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U });
441 // should not happen, was checked in lanes.lua before calling lane_new() 467 // should not happen, was checked in lanes.lua before calling lane_new()
442 if (luaG_type(L_, _required_idx) != LuaType::TABLE) { 468 if (luaW_type(L_, _required_idx) != LuaType::TABLE) {
443 raise_luaL_error(L_, "expected required module list as a table, got %s", luaL_typename(L_, _required_idx)); 469 raise_luaL_error(L_, "expected required module list as a table, got %s", luaL_typename(L_, _required_idx));
444 } 470 }
445 471
446 lua_pushnil(L_); // L_: [fixed] args... nil L2: 472 lua_pushnil(L_); // L_: [fixed] args... nil L2:
447 while (lua_next(L_, _required_idx) != 0) { // L_: [fixed] args... n "modname" L2: 473 while (lua_next(L_, _required_idx) != 0) { // L_: [fixed] args... n "modname" L2:
448 if (luaG_type(L_, kIdxTop) != LuaType::STRING || luaG_type(L_, StackIndex{ -2 }) != LuaType::NUMBER || lua_tonumber(L_, -2) != _nbRequired) { 474 if (luaW_type(L_, kIdxTop) != LuaType::STRING || luaW_type(L_, StackIndex{ -2 }) != LuaType::NUMBER || lua_tonumber(L_, -2) != _nbRequired) {
449 raise_luaL_error(L_, "required module list should be a list of strings"); 475 raise_luaL_error(L_, "required module list should be a list of strings");
450 } else { 476 } else {
451 // require the module in the target state, and populate the lookup table there too 477 // require the module in the target state, and populate the lookup table there too
452 std::string_view const _name{ luaG_tostring(L_, kIdxTop) }; 478 std::string_view const _name{ luaW_tostring(L_, kIdxTop) };
453 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: require '" << _name << "'" << std::endl); 479 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: require '" << _name << "'" << std::endl);
454 480
455 // require the module in the target lane 481 // require the module in the target lane
@@ -458,7 +484,7 @@ LUAG_FUNC(lane_new)
458 lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2: 484 lua_pop(_L2, 1); // L_: [fixed] args... n "modname" L2:
459 raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first"); 485 raise_luaL_error(L_, "cannot pre-require modules without loading 'package' library first");
460 } else { 486 } else {
461 luaG_pushstring(_L2, _name); // L_: [fixed] args... n "modname" L2: require() name 487 luaW_pushstring(_L2, _name); // L_: [fixed] args... n "modname" L2: require() name
462 LuaError const _rc{ lua_pcall(_L2, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode 488 LuaError const _rc{ lua_pcall(_L2, 1, 1, 0) }; // L_: [fixed] args... n "modname" L2: ret/errcode
463 if (_rc != LuaError::OK) { 489 if (_rc != LuaError::OK) {
464 // propagate error to main state if any 490 // propagate error to main state if any
@@ -493,7 +519,7 @@ LUAG_FUNC(lane_new)
493 lua_pushnil(L_); // L_: [fixed] args... nil L2: 519 lua_pushnil(L_); // L_: [fixed] args... nil L2:
494 // Lua 5.2 wants us to push the globals table on the stack 520 // Lua 5.2 wants us to push the globals table on the stack
495 InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} }; 521 InterCopyContext _c{ _U, DestState{ _L2 }, SourceState{ L_ }, {}, {}, {}, {}, {} };
496 luaG_pushglobaltable(_L2); // L_: [fixed] args... nil L2: _G 522 luaW_pushglobaltable(_L2); // L_: [fixed] args... nil L2: _G
497 while (lua_next(L_, _globals_idx)) { // L_: [fixed] args... k v L2: _G 523 while (lua_next(L_, _globals_idx)) { // L_: [fixed] args... k v L2: _G
498 std::ignore = _c.interCopy(2); // L_: [fixed] args... k v L2: _G k v 524 std::ignore = _c.interCopy(2); // L_: [fixed] args... k v L2: _G k v
499 // assign it in L2's globals table 525 // assign it in L2's globals table
@@ -507,7 +533,7 @@ LUAG_FUNC(lane_new)
507 533
508 // Lane main function 534 // Lane main function
509 [[maybe_unused]] int const _errorHandlerCount{ _lane->pushErrorHandler() }; // L_: [fixed] args... L2: eh? 535 [[maybe_unused]] int const _errorHandlerCount{ _lane->pushErrorHandler() }; // L_: [fixed] args... L2: eh?
510 LuaType const _func_type{ luaG_type(L_, kFuncIdx) }; 536 LuaType const _func_type{ luaW_type(L_, kFuncIdx) };
511 if (_func_type == LuaType::FUNCTION) { 537 if (_func_type == LuaType::FUNCTION) {
512 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer lane body" << std::endl); 538 DEBUGSPEW_CODE(DebugSpew(_U) << "lane_new: transfer lane body" << std::endl);
513 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); 539 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U });
@@ -524,7 +550,7 @@ LUAG_FUNC(lane_new)
524 raise_luaL_error(L_, "error when parsing lane function code"); 550 raise_luaL_error(L_, "error when parsing lane function code");
525 } 551 }
526 } else { 552 } else {
527 raise_luaL_error(L_, "Expected function, got %s", luaG_typename(L_, _func_type).data()); 553 raise_luaL_error(L_, "Expected function, got %s", luaW_typename(L_, _func_type).data());
528 } 554 }
529 STACK_CHECK(L_, 0); 555 STACK_CHECK(L_, 0);
530 STACK_CHECK(_L2, _errorHandlerCount + 1); 556 STACK_CHECK(_L2, _errorHandlerCount + 1);
@@ -612,7 +638,7 @@ LUAG_FUNC(wakeup_conv)
612 638
613 STACK_CHECK_START_REL(L_, 0); 639 STACK_CHECK_START_REL(L_, 0);
614 auto _readInteger = [L = L_](std::string_view const& name_) { 640 auto _readInteger = [L = L_](std::string_view const& name_) {
615 std::ignore = luaG_getfield(L, StackIndex{ 1 }, name_); 641 std::ignore = luaW_getfield(L, StackIndex{ 1 }, name_);
616 lua_Integer const val{ lua_tointeger(L, -1) }; 642 lua_Integer const val{ lua_tointeger(L, -1) };
617 lua_pop(L, 1); 643 lua_pop(L, 1);
618 return static_cast<int>(val); 644 return static_cast<int>(val);
@@ -628,7 +654,7 @@ LUAG_FUNC(wakeup_conv)
628 // If Lua table has '.isdst' we trust that. If it does not, we'll let 654 // If Lua table has '.isdst' we trust that. If it does not, we'll let
629 // 'mktime' decide on whether the time is within DST or not (value -1). 655 // 'mktime' decide on whether the time is within DST or not (value -1).
630 // 656 //
631 int const _isdst{ (luaG_getfield(L_, StackIndex{ 1 }, "isdst") == LuaType::BOOLEAN) ? lua_toboolean(L_, -1) : -1 }; 657 int const _isdst{ (luaW_getfield(L_, StackIndex{ 1 }, "isdst") == LuaType::BOOLEAN) ? lua_toboolean(L_, -1) : -1 };
632 lua_pop(L_, 1); 658 lua_pop(L_, 1);
633 STACK_CHECK(L_, 0); 659 STACK_CHECK(L_, 0);
634 660
@@ -658,6 +684,7 @@ namespace {
658 { Universe::kFinally, Universe::InitializeFinalizer }, 684 { Universe::kFinally, Universe::InitializeFinalizer },
659 { "linda", LG_linda }, 685 { "linda", LG_linda },
660 { "nameof", LG_nameof }, 686 { "nameof", LG_nameof },
687 { "thread_priority_range", LG_thread_priority_range },
661 { "now_secs", LG_now_secs }, 688 { "now_secs", LG_now_secs },
662 { "register", lanes_register }, 689 { "register", lanes_register },
663 { "set_singlethreaded", LG_set_singlethreaded }, 690 { "set_singlethreaded", LG_set_singlethreaded },
@@ -692,8 +719,8 @@ LUAG_FUNC(configure)
692 719
693 Universe* _U{ Universe::Get(L_) }; 720 Universe* _U{ Universe::Get(L_) };
694 bool const _from_master_state{ _U == nullptr }; 721 bool const _from_master_state{ _U == nullptr };
695 std::string_view const _name{ luaG_checkstring(L_, StackIndex{ lua_upvalueindex(1) }) }; 722 std::string_view const _name{ luaW_checkstring(L_, StackIndex{ lua_upvalueindex(1) }) };
696 LUA_ASSERT(L_, luaG_type(L_, StackIndex{ 1 }) == LuaType::TABLE); 723 LUA_ASSERT(L_, luaW_type(L_, StackIndex{ 1 }) == LuaType::TABLE);
697 724
698 STACK_GROW(L_, 4); 725 STACK_GROW(L_, 4);
699 STACK_CHECK_START_ABS(L_, 1); // L_: settings 726 STACK_CHECK_START_ABS(L_, 1); // L_: settings
@@ -703,7 +730,7 @@ LUAG_FUNC(configure)
703 730
704 if (_U == nullptr) { 731 if (_U == nullptr) {
705 // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... 732 // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global...
706 kLaneNameRegKey.setValue(L_, [](lua_State* L_) { luaG_pushstring(L_, "main"); }); 733 kLaneNameRegKey.setValue(L_, [](lua_State* L_) { luaW_pushstring(L_, "main"); });
707 734
708 // create the universe 735 // create the universe
709 _U = Universe::Create(L_); // L_: settings universe 736 _U = Universe::Create(L_); // L_: settings universe
@@ -719,7 +746,7 @@ LUAG_FUNC(configure)
719 lua_pushnil(L_); // L_: settings M nil 746 lua_pushnil(L_); // L_: settings M nil
720 lua_setfield(L_, -2, "configure"); // L_: settings M 747 lua_setfield(L_, -2, "configure"); // L_: settings M
721 // add functions to the module's table 748 // add functions to the module's table
722 luaG_registerlibfuncs(L_, local::sLanesFunctions); 749 luaW_registerlibfuncs(L_, local::sLanesFunctions);
723 750
724 // register core.threads() only if settings say it should be available 751 // register core.threads() only if settings say it should be available
725 if (_U->tracker.isActive()) { 752 if (_U->tracker.isActive()) {
@@ -744,7 +771,7 @@ LUAG_FUNC(configure)
744 lua_pushcclosure(L_, LG_require, 1); // L_: settings M lanes.require 771 lua_pushcclosure(L_, LG_require, 1); // L_: settings M lanes.require
745 lua_setfield(L_, -2, "require"); // L_: settings M 772 lua_setfield(L_, -2, "require"); // L_: settings M
746 773
747 luaG_pushstring( 774 luaW_pushstring(
748 L_, 775 L_,
749 "%d.%d.%d", 776 "%d.%d.%d",
750 LANES_VERSION_MAJOR, 777 LANES_VERSION_MAJOR,
@@ -753,9 +780,6 @@ LUAG_FUNC(configure)
753 ); // L_: settings M VERSION 780 ); // L_: settings M VERSION
754 lua_setfield(L_, -2, "version"); // L_: settings M 781 lua_setfield(L_, -2, "version"); // L_: settings M
755 782
756 lua_pushinteger(L_, kThreadPrioMax); // L_: settings M kThreadPrioMax
757 lua_setfield(L_, -2, "max_prio"); // L_: settings M
758
759 kCancelError.pushKey(L_); // L_: settings M kCancelError 783 kCancelError.pushKey(L_); // L_: settings M kCancelError
760 lua_setfield(L_, -2, "cancel_error"); // L_: settings M 784 lua_setfield(L_, -2, "cancel_error"); // L_: settings M
761 785
@@ -779,7 +803,7 @@ LUAG_FUNC(configure)
779 // don't do this when called during the initialization of a new lane, 803 // don't do this when called during the initialization of a new lane,
780 // because we will do it after on_state_create() is called, 804 // because we will do it after on_state_create() is called,
781 // and we don't want to skip _G because of caching in case globals are created then 805 // and we don't want to skip _G because of caching in case globals are created then
782 luaG_pushglobaltable(L_); // L_: settings M _G 806 luaW_pushglobaltable(L_); // L_: settings M _G
783 tools::PopulateFuncLookupTable(L_, kIdxTop, {}); 807 tools::PopulateFuncLookupTable(L_, kIdxTop, {});
784 lua_pop(L_, 1); // L_: settings M 808 lua_pop(L_, 1); // L_: settings M
785 } 809 }
@@ -859,10 +883,10 @@ LANES_API int luaopen_lanes_core(lua_State* const L_)
859 883
860 // Prevent PUC-Lua/LuaJIT mismatch. Hopefully this works for MoonJIT too 884 // Prevent PUC-Lua/LuaJIT mismatch. Hopefully this works for MoonJIT too
861 if constexpr (LUAJIT_FLAVOR() == 0) { 885 if constexpr (LUAJIT_FLAVOR() == 0) {
862 if (luaG_getmodule(L_, LUA_JITLIBNAME) != LuaType::NIL) 886 if (luaW_getmodule(L_, LUA_JITLIBNAME) != LuaType::NIL)
863 raise_luaL_error(L_, "Lanes is built for PUC-Lua, don't run from LuaJIT"); 887 raise_luaL_error(L_, "Lanes is built for PUC-Lua, don't run from LuaJIT");
864 } else { 888 } else {
865 if (luaG_getmodule(L_, LUA_JITLIBNAME) == LuaType::NIL) 889 if (luaW_getmodule(L_, LUA_JITLIBNAME) == LuaType::NIL)
866 raise_luaL_error(L_, "Lanes is built for LuaJIT, don't run from PUC-Lua"); 890 raise_luaL_error(L_, "Lanes is built for LuaJIT, don't run from PUC-Lua");
867 } 891 }
868 lua_pop(L_, 1); // L_: 892 lua_pop(L_, 1); // L_:
diff --git a/src/lanes.lua b/src/lanes.lua
index 3ee959c..c5b3315 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -280,6 +280,10 @@ local opt_validators =
280 local tv = type(v_) 280 local tv = type(v_)
281 return (tv == "string") and v_ or raise_option_error("name", tv, v_) 281 return (tv == "string") and v_ or raise_option_error("name", tv, v_)
282 end, 282 end,
283 native_priority = function(v_)
284 local tv = type(v_)
285 return (tv == "number") and v_ or raise_option_error("native_priority", tv, v_)
286 end,
283 package = function(v_) 287 package = function(v_)
284 local tv = type(v_) 288 local tv = type(v_)
285 return (tv == "table") and v_ or raise_option_error("package", tv, v_) 289 return (tv == "table") and v_ or raise_option_error("package", tv, v_)
@@ -295,7 +299,7 @@ local opt_validators =
295} 299}
296 300
297-- ############################################################################################# 301-- #############################################################################################
298-- ##################################### lanes.gen() ########################################### 302-- ################################### lanes.gen/coro() ########################################
299-- ############################################################################################# 303-- #############################################################################################
300 304
301local process_gen_opt = function(...) 305local process_gen_opt = function(...)
@@ -367,9 +371,16 @@ local process_gen_opt = function(...)
367 opt[k] = validator(v) 371 opt[k] = validator(v)
368 end 372 end
369 end 373 end
374
375 -- special case: can't have priority and native_priority at the same time
376 if opt.priority and opt.native_priority then
377 error "priority and native_priority cannot be specified together"
378 end
370 return func, libs, opt 379 return func, libs, opt
371end -- process_gen_opt 380end -- process_gen_opt
372 381
382-- #################################################################################################
383
373-- lane_h[1..n]: lane results, same as via 'lane_h:join()' 384-- lane_h[1..n]: lane results, same as via 'lane_h:join()'
374-- lane_h[0]: can be read to make sure a thread has finished (gives the number of available results) 385-- lane_h[0]: can be read to make sure a thread has finished (gives the number of available results)
375-- lane_h[negative]: error message, without propagating the error 386-- lane_h[negative]: error message, without propagating the error
@@ -408,25 +419,28 @@ end -- process_gen_opt
408-- Calling with a function argument ('lane_func') ends the string/table 419-- Calling with a function argument ('lane_func') ends the string/table
409-- modifiers, and prepares a lane generator. 420-- modifiers, and prepares a lane generator.
410 421
411-- receives a sequence of strings and tables, plus a function 422local make_generator = function(is_coro_, ...)
412local gen = function(...)
413 local func, libs, opt = process_gen_opt(...) 423 local func, libs, opt = process_gen_opt(...)
414 local core_lane_new = assert(core.lane_new) 424 local core_lane_new = assert(core.lane_new)
415 local priority, globals, package, required, gc_cb, name, error_trace_level = opt.priority, opt.globals, opt.package or package, opt.required, opt.gc_cb, opt.name, error_trace_levels[opt.error_trace_level] 425 local prio_is_native = opt.native_priority and true or false
426 local priority, globals, package, required, gc_cb, name, error_trace_level = opt.priority or opt.native_priority, opt.globals, opt.package or package, opt.required, opt.gc_cb, opt.name, error_trace_levels[opt.error_trace_level]
416 return function(...) 427 return function(...)
417 -- must pass functions args last else they will be truncated to the first one 428 -- must pass functions args last else they will be truncated to the first one
418 return core_lane_new(func, libs, priority, globals, package, required, gc_cb, name, error_trace_level, false, ...) 429 return core_lane_new(func, libs, prio_is_native, priority, globals, package, required, gc_cb, name, error_trace_level, is_coro_, ...)
419 end 430 end
431end -- make_generator
432
433-- #################################################################################################
434
435-- receives a sequence of strings and tables, plus a function
436local gen = function(...)
437 return make_generator(false, ...)
420end -- gen() 438end -- gen()
421 439
440-- #################################################################################################
441
422local coro = function(...) 442local coro = function(...)
423 local func, libs, opt = process_gen_opt(...) 443 return make_generator(true, ...)
424 local core_lane_new = assert(core.lane_new)
425 local priority, globals, package, required, gc_cb, name, error_trace_level = opt.priority, opt.globals, opt.package or package, opt.required, opt.gc_cb, opt.name, error_trace_levels[opt.error_trace_level]
426 return function(...)
427 -- must pass functions args last else they will be truncated to the first one
428 return core_lane_new(func, libs, priority, globals, package, required, gc_cb, name, error_trace_level, true, ...)
429 end
430end -- coro() 444end -- coro()
431 445
432-- ################################################################################################# 446-- #################################################################################################
@@ -656,7 +670,8 @@ local configure_timers = function()
656 end 670 end
657 end 671 end
658 end -- timer_body() 672 end -- timer_body()
659 timer_lane = gen("lanes_core,table", { name = "LanesTimer", package = {}, priority = core.max_prio }, timer_body)() 673 local min_prio, max_prio = core.thread_priority_range()
674 timer_lane = gen("lanes_core,table", { name = "LanesTimer", package = {}, priority = max_prio }, timer_body)()
660 end -- first_time 675 end -- first_time
661 676
662 ----- 677 -----
@@ -876,6 +891,7 @@ local configure = function(settings_)
876 lanes.set_thread_affinity = core.set_thread_affinity 891 lanes.set_thread_affinity = core.set_thread_affinity
877 lanes.set_thread_priority = core.set_thread_priority 892 lanes.set_thread_priority = core.set_thread_priority
878 lanes.sleep = core.sleep 893 lanes.sleep = core.sleep
894 lanes.thread_priority_range = core.thread_priority_range
879 lanes.threads = core.threads or function() error "lane tracking is not available" end -- core.threads isn't registered if settings.track_lanes is false 895 lanes.threads = core.threads or function() error "lane tracking is not available" end -- core.threads isn't registered if settings.track_lanes is false
880 896
881 lanes.gen = gen 897 lanes.gen = gen
diff --git a/src/lanesconf.h b/src/lanesconf.h
index 0afd493..07f1d52 100644
--- a/src/lanesconf.h
+++ b/src/lanesconf.h
@@ -42,12 +42,12 @@
42#endif // __cplusplus 42#endif // __cplusplus
43#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 43#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
44 44
45// kind of MSVC-specific 45// LANES_DEBUG has to be provided externally (makefile, vcproj, whatever)
46#ifdef _DEBUG 46#ifdef LANES_DEBUG
47#define HAVE_LUA_ASSERT() 1 47#define HAVE_LUA_ASSERT() 1
48#else // NDEBUG 48#else // LANES_DEBUG
49#define HAVE_LUA_ASSERT() 0 49#define HAVE_LUA_ASSERT() 0
50#endif // NDEBUG 50#endif // LANES_DEBUG
51 51
52#define USE_DEBUG_SPEW() 0 52#define USE_DEBUG_SPEW() 0
53#define HAVE_DECODA_SUPPORT() 0 53#define HAVE_DECODA_SUPPORT() 0
diff --git a/src/linda.cpp b/src/linda.cpp
index fa28385..1f4b19d 100644
--- a/src/linda.cpp
+++ b/src/linda.cpp
@@ -47,7 +47,7 @@ namespace {
47 { 47 {
48 STACK_CHECK_START_REL(L_, 0); 48 STACK_CHECK_START_REL(L_, 0);
49 for (StackIndex const _i : std::ranges::iota_view{ start_, StackIndex{ end_ + 1 } }) { 49 for (StackIndex const _i : std::ranges::iota_view{ start_, StackIndex{ end_ + 1 } }) {
50 LuaType const _t{ luaG_type(L_, _i) }; 50 LuaType const _t{ luaW_type(L_, _i) };
51 switch (_t) { 51 switch (_t) {
52 case LuaType::BOOLEAN: 52 case LuaType::BOOLEAN:
53 case LuaType::NUMBER: 53 case LuaType::NUMBER:
@@ -109,13 +109,13 @@ namespace {
109 { 109 {
110 Linda* const _linda{ ToLinda<OPT>(L_, idx_) }; 110 Linda* const _linda{ ToLinda<OPT>(L_, idx_) };
111 if (_linda != nullptr) { 111 if (_linda != nullptr) {
112 luaG_pushstring(L_, "Linda: "); 112 luaW_pushstring(L_, "Linda: ");
113 std::string_view const _lindaName{ _linda->getName() }; 113 std::string_view const _lindaName{ _linda->getName() };
114 if (!_lindaName.empty()) { 114 if (!_lindaName.empty()) {
115 luaG_pushstring(L_, _lindaName); 115 luaW_pushstring(L_, _lindaName);
116 } else { 116 } else {
117 // obfuscate the pointer so that we can't read the value with our eyes out of a script 117 // obfuscate the pointer so that we can't read the value with our eyes out of a script
118 luaG_pushstring(L_, "%p", _linda->obfuscated()); 118 luaW_pushstring(L_, "%p", _linda->obfuscated());
119 } 119 }
120 lua_concat(L_, 2); 120 lua_concat(L_, 2);
121 return 1; 121 return 1;
@@ -132,7 +132,7 @@ namespace {
132 StackIndex _key_i{ 2 }; // index of first slot, if timeout not there 132 StackIndex _key_i{ 2 }; // index of first slot, if timeout not there
133 133
134 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; 134 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() };
135 if (luaG_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion 135 if (luaW_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion
136 lua_Duration const _duration{ lua_tonumber(L_, 2) }; 136 lua_Duration const _duration{ lua_tonumber(L_, 2) };
137 if (_duration.count() >= 0.0) { 137 if (_duration.count() >= 0.0) {
138 _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(_duration); 138 _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(_duration);
@@ -147,6 +147,42 @@ namespace {
147 } 147 }
148 148
149 // ############################################################################################# 149 // #############################################################################################
150 static bool WaitInternal([[maybe_unused]] lua_State* const L_, Lane* const lane_, Linda* const linda_, Keeper* const keeper_, std::condition_variable& waitingOn_, std::chrono::time_point<std::chrono::steady_clock> until_)
151 {
152 Lane::Status _prev_status{ Lane::Error }; // prevent 'might be used uninitialized' warnings
153 if (lane_ != nullptr) {
154 // change status of lane to "waiting"
155 _prev_status = lane_->status.load(std::memory_order_acquire); // Running, most likely
156 LUA_ASSERT(L_, _prev_status == Lane::Running); // but check, just in case
157 LUA_ASSERT(L_, lane_->waiting_on == nullptr);
158 lane_->waiting_on = &waitingOn_;
159 lane_->status.store(Lane::Waiting, std::memory_order_release);
160 }
161
162 // wait until the final target date by small increments, interrupting regularly so that we can check for cancel requests,
163 // in case some timing issue caused a cancel request to be issued, and the condvar signalled, before we actually wait for it
164 auto const [_forceTryAgain, _until_check_cancel] = std::invoke([until_, wakePeriod = linda_->getWakePeriod()] {
165 auto _until_check_cancel{ std::chrono::time_point<std::chrono::steady_clock>::max() };
166 if (wakePeriod.count() > 0.0f) {
167 _until_check_cancel = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(wakePeriod);
168 }
169 bool const _forceTryAgain{ _until_check_cancel < until_ };
170 return std::make_tuple(_forceTryAgain, _forceTryAgain ? _until_check_cancel : until_);
171 });
172
173 // operation can't complete: wake when it is signalled to be possible, or when timeout is reached
174 std::unique_lock<std::mutex> _guard{ keeper_->mutex, std::adopt_lock };
175 std::cv_status const _status{ waitingOn_.wait_until(_guard, _until_check_cancel) };
176 _guard.release(); // we don't want to unlock the mutex on exit!
177 bool const _try_again{ _forceTryAgain || (_status == std::cv_status::no_timeout) }; // detect spurious wakeups
178 if (lane_ != nullptr) {
179 lane_->waiting_on = nullptr;
180 lane_->status.store(_prev_status, std::memory_order_release);
181 }
182 return _try_again;
183 }
184
185 // #############################################################################################
150 186
151 // the implementation for linda:receive() and linda:receive_batched() 187 // the implementation for linda:receive() and linda:receive_batched()
152 static int ReceiveInternal(lua_State* const L_, bool const batched_) 188 static int ReceiveInternal(lua_State* const L_, bool const batched_)
@@ -201,6 +237,7 @@ namespace {
201 _cancel = (_cancel != CancelRequest::None) 237 _cancel = (_cancel != CancelRequest::None)
202 ? _cancel 238 ? _cancel
203 : ((_linda->cancelStatus == Linda::Cancelled) ? CancelRequest::Soft : CancelRequest::None); 239 : ((_linda->cancelStatus == Linda::Cancelled) ? CancelRequest::Soft : CancelRequest::None);
240
204 // if user wants to cancel, or looped because of a timeout, the call returns without sending anything 241 // if user wants to cancel, or looped because of a timeout, the call returns without sending anything
205 if (!_try_again || _cancel != CancelRequest::None) { 242 if (!_try_again || _cancel != CancelRequest::None) {
206 _pushed.emplace(0); 243 _pushed.emplace(0);
@@ -227,38 +264,7 @@ namespace {
227 } 264 }
228 265
229 // nothing received, wait until timeout or signalled that we should try again 266 // nothing received, wait until timeout or signalled that we should try again
230 { 267 _try_again = WaitInternal(L_, _lane, _linda, _keeper, _linda->writeHappened, _until);
231 Lane::Status _prev_status{ Lane::Error }; // prevent 'might be used uninitialized' warnings
232 if (_lane != nullptr) {
233 // change status of lane to "waiting"
234 _prev_status = _lane->status.load(std::memory_order_acquire); // Running, most likely
235 LUA_ASSERT(L_, _prev_status == Lane::Running); // but check, just in case
236 LUA_ASSERT(L_, _lane->waiting_on == nullptr);
237 _lane->waiting_on = &_linda->writeHappened;
238 _lane->status.store(Lane::Waiting, std::memory_order_release);
239 }
240
241 // wait until the final target date by small increments, interrupting regularly so that we can check for cancel requests,
242 // in case some timing issue caused a cancel request to be issued, and the condvar signalled, before we actually wait for it
243 auto const [_forceTryAgain, _until_check_cancel] = std::invoke([_until, wakePeriod = _linda->getWakePeriod()] {
244 auto _until_check_cancel{ std::chrono::time_point<std::chrono::steady_clock>::max() };
245 if (wakePeriod.count() > 0.0f) {
246 _until_check_cancel = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(wakePeriod);
247 }
248 bool const _forceTryAgain{ _until_check_cancel < _until };
249 return std::make_tuple(_forceTryAgain, _forceTryAgain ? _until_check_cancel : _until);
250 });
251
252 // not enough data to read: wakeup when data was sent, or when timeout is reached
253 std::unique_lock<std::mutex> _guard{ _keeper->mutex, std::adopt_lock };
254 std::cv_status const _status{ _linda->writeHappened.wait_until(_guard, _until_check_cancel) };
255 _guard.release(); // we don't want to unlock the mutex on exit!
256 _try_again = _forceTryAgain || (_status == std::cv_status::no_timeout); // detect spurious wakeups
257 if (_lane != nullptr) {
258 _lane->waiting_on = nullptr;
259 _lane->status.store(_prev_status, std::memory_order_release);
260 }
261 }
262 } 268 }
263 STACK_CHECK(_K, 0); 269 STACK_CHECK(_K, 0);
264 270
@@ -273,7 +279,7 @@ namespace {
273 if (_nbPushed == 0) { 279 if (_nbPushed == 0) {
274 // not enough data in the linda slot to fulfill the request, return nil, "timeout" 280 // not enough data in the linda slot to fulfill the request, return nil, "timeout"
275 lua_pushnil(L_); 281 lua_pushnil(L_);
276 luaG_pushstring(L_, "timeout"); 282 luaW_pushstring(L_, "timeout");
277 return 2; 283 return 2;
278 } 284 }
279 return _nbPushed; 285 return _nbPushed;
@@ -332,6 +338,7 @@ Keeper* Linda::acquireKeeper() const
332 Keeper* const _keeper{ whichKeeper() }; 338 Keeper* const _keeper{ whichKeeper() };
333 if (_keeper) { 339 if (_keeper) {
334 _keeper->mutex.lock(); 340 _keeper->mutex.lock();
341 keeperOperationCount.fetch_add(1, std::memory_order_seq_cst);
335 } 342 }
336 return _keeper; 343 return _keeper;
337} 344}
@@ -344,16 +351,16 @@ Linda* Linda::CreateTimerLinda(lua_State* const L_)
344 // Initialize 'timerLinda'; a common Linda object shared by all states 351 // Initialize 'timerLinda'; a common Linda object shared by all states
345 lua_pushcfunction(L_, LG_linda); // L_: lanes.linda 352 lua_pushcfunction(L_, LG_linda); // L_: lanes.linda
346 lua_createtable(L_, 0, 3); // L_: lanes.linda {} 353 lua_createtable(L_, 0, 3); // L_: lanes.linda {}
347 luaG_pushstring(L_, "lanes-timer"); // L_: lanes.linda {} "lanes-timer" 354 luaW_pushstring(L_, "lanes-timer"); // L_: lanes.linda {} "lanes-timer"
348 luaG_setfield(L_, StackIndex{ -2 }, std::string_view{ "name" }); // L_: lanes.linda { .name="lanes-timer" } 355 luaW_setfield(L_, StackIndex{ -2 }, std::string_view{ "name" }); // L_: lanes.linda { .name="lanes-timer" }
349 lua_pushinteger(L_, 0); // L_: lanes.linda { .name="lanes-timer" } 0 356 lua_pushinteger(L_, 0); // L_: lanes.linda { .name="lanes-timer" } 0
350 luaG_setfield(L_, StackIndex{ -2 }, std::string_view{ "group" }); // L_: lanes.linda { .name="lanes-timer" .group = 0 } 357 luaW_setfield(L_, StackIndex{ -2 }, std::string_view{ "group" }); // L_: lanes.linda { .name="lanes-timer" .group = 0 }
351 // note that wake_period is not set (will default to the value in the universe) 358 // note that wake_period is not set (will default to the value in the universe)
352 lua_call(L_, 1, 1); // L_: linda 359 lua_call(L_, 1, 1); // L_: linda
353 STACK_CHECK(L_, 1); 360 STACK_CHECK(L_, 1);
354 361
355 // Proxy userdata contents is only a 'DeepPrelude*' pointer 362 // Proxy userdata contents is only a 'DeepPrelude*' pointer
356 auto const _timerLinda{ *luaG_tofulluserdata<Linda*>(L_, kIdxTop) }; 363 auto const _timerLinda{ *luaW_tofulluserdata<Linda*>(L_, kIdxTop) };
357 // increment refcount so that this linda remains alive as long as the universe exists. 364 // increment refcount so that this linda remains alive as long as the universe exists.
358 _timerLinda->refcount.fetch_add(1, std::memory_order_relaxed); 365 _timerLinda->refcount.fetch_add(1, std::memory_order_relaxed);
359 lua_pop(L_, 1); // L_: 366 lua_pop(L_, 1); // L_:
@@ -416,7 +423,6 @@ int Linda::ProtectedCall(lua_State* const L_, lua_CFunction const f_)
416 // doing LindaFactory::deleteDeepObjectInternal -> keeper_call(clear) 423 // doing LindaFactory::deleteDeepObjectInternal -> keeper_call(clear)
417 lua_gc(L_, LUA_GCSTOP, 0); 424 lua_gc(L_, LUA_GCSTOP, 0);
418 425
419 LUA_ASSERT_CODE(auto const _koip{ _linda->startKeeperOperation(L_) });
420 // if we didn't do anything wrong, the keeper stack should be clean 426 // if we didn't do anything wrong, the keeper stack should be clean
421 LUA_ASSERT(L_, lua_gettop(_K) == 0); 427 LUA_ASSERT(L_, lua_gettop(_K) == 0);
422 428
@@ -424,7 +430,7 @@ int Linda::ProtectedCall(lua_State* const L_, lua_CFunction const f_)
424 lua_pushcfunction(L_, f_); 430 lua_pushcfunction(L_, f_);
425 lua_insert(L_, 1); 431 lua_insert(L_, 1);
426 // do a protected call 432 // do a protected call
427 LuaError const _rc{ lua_pcall(L_, lua_gettop(L_) - 1, LUA_MULTRET, 0) }; 433 LuaError const _rc{ ToLuaError(lua_pcall(L_, lua_gettop(L_) - 1, LUA_MULTRET, 0)) };
428 // whatever happens, the keeper state stack must be empty when we are done 434 // whatever happens, the keeper state stack must be empty when we are done
429 lua_settop(_K, 0); 435 lua_settop(_K, 0);
430 436
@@ -446,7 +452,7 @@ int Linda::ProtectedCall(lua_State* const L_, lua_CFunction const f_)
446 452
447void Linda::pushCancelString(lua_State* L_) const 453void Linda::pushCancelString(lua_State* L_) const
448{ 454{
449 luaG_pushstring(L_, cancelStatus == Status::Cancelled ? "cancelled" : "active"); 455 luaW_pushstring(L_, cancelStatus == Status::Cancelled ? "cancelled" : "active");
450} 456}
451 457
452// ################################################################################################# 458// #################################################################################################
@@ -455,6 +461,7 @@ void Linda::releaseKeeper(Keeper* const keeper_) const
455{ 461{
456 if (keeper_) { // can be nullptr if we tried to acquire during shutdown 462 if (keeper_) { // can be nullptr if we tried to acquire during shutdown
457 assert(keeper_ == whichKeeper()); 463 assert(keeper_ == whichKeeper());
464 keeperOperationCount.fetch_sub(1, std::memory_order_seq_cst);
458 keeper_->mutex.unlock(); 465 keeper_->mutex.unlock();
459 } 466 }
460} 467}
@@ -498,7 +505,7 @@ void Linda::setName(std::string_view const& name_)
498LUAG_FUNC(linda_cancel) 505LUAG_FUNC(linda_cancel)
499{ 506{
500 Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; 507 Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) };
501 std::string_view const _who{ luaG_optstring(L_, StackIndex{ 2 }, "both") }; 508 std::string_view const _who{ luaW_optstring(L_, StackIndex{ 2 }, "both") };
502 // make sure we got 2 arguments: the linda and the cancellation mode 509 // make sure we got 2 arguments: the linda and the cancellation mode
503 luaL_argcheck(L_, lua_gettop(L_) <= 2, 2, "wrong number of arguments"); 510 luaL_argcheck(L_, lua_gettop(L_) <= 2, 2, "wrong number of arguments");
504 511
@@ -586,13 +593,13 @@ static int linda_index_string(lua_State* L_)
586 Linda* const _linda{ ToLinda<false>(L_, kIdxSelf) }; 593 Linda* const _linda{ ToLinda<false>(L_, kIdxSelf) };
587 LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: linda "key" 594 LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: linda "key"
588 595
589 std::string_view const _keystr{ luaG_tostring(L_, kIdxKey) }; 596 std::string_view const _keystr{ luaW_tostring(L_, kIdxKey) };
590 lua_settop(L_, 2); // keep only our original arguments on the stack 597 lua_settop(L_, 2); // keep only our original arguments on the stack
591 598
592 // look in metatable first 599 // look in metatable first
593 lua_getmetatable(L_, kIdxSelf); // L_: linda "key" mt 600 lua_getmetatable(L_, kIdxSelf); // L_: linda "key" mt
594 lua_replace(L_, -3); // L_: mt "key" 601 lua_replace(L_, -3); // L_: mt "key"
595 if (luaG_rawget(L_, StackIndex{ -2 }) != LuaType::NIL) { // found something? // L_: mt value 602 if (luaW_rawget(L_, StackIndex{ -2 }) != LuaType::NIL) { // found something? // L_: mt value
596 return 1; // done 603 return 1; // done
597 } 604 }
598 605
@@ -612,12 +619,12 @@ static LUAG_FUNC(linda_index)
612 static constexpr StackIndex kIdxKey{ 2 }; 619 static constexpr StackIndex kIdxKey{ 2 };
613 LUA_ASSERT(L_, lua_gettop(L_) == 2); 620 LUA_ASSERT(L_, lua_gettop(L_) == 2);
614 621
615 switch (luaG_type(L_, kIdxKey)) { 622 switch (luaW_type(L_, kIdxKey)) {
616 case LuaType::STRING: 623 case LuaType::STRING:
617 return linda_index_string(L_); // stack modification is undefined, returned value is at the top 624 return linda_index_string(L_); // stack modification is undefined, returned value is at the top
618 625
619 default: // unknown key 626 default: // unknown key
620 raise_luaL_error(L_, "Unsupported linda indexing key type %s", luaG_typename(L_, kIdxKey).data()); 627 raise_luaL_error(L_, "Unsupported linda indexing key type %s", luaW_typename(L_, kIdxKey).data());
621 } 628 }
622} 629}
623 630
@@ -760,7 +767,7 @@ LUAG_FUNC(linda_limit)
760 int const _nargs{ lua_gettop(L_) }; 767 int const _nargs{ lua_gettop(L_) };
761 luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments"); 768 luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments");
762 // make sure we got a numeric limit, or "unlimited", (or nothing) 769 // make sure we got a numeric limit, or "unlimited", (or nothing)
763 bool const _unlimited{ luaG_tostring(L_, StackIndex{ 3 }) == "unlimited" }; 770 bool const _unlimited{ luaW_tostring(L_, StackIndex{ 3 }) == "unlimited" };
764 LindaLimit const _val{ _unlimited ? std::numeric_limits<LindaLimit::type>::max() : static_cast<LindaLimit::type>(luaL_optinteger(L_, 3, 0)) }; 771 LindaLimit const _val{ _unlimited ? std::numeric_limits<LindaLimit::type>::max() : static_cast<LindaLimit::type>(luaL_optinteger(L_, 3, 0)) };
765 if (_val < 0) { 772 if (_val < 0) {
766 raise_luaL_argerror(L_, StackIndex{ 3 }, "limit must be >= 0"); 773 raise_luaL_argerror(L_, StackIndex{ 3 }, "limit must be >= 0");
@@ -771,23 +778,23 @@ LUAG_FUNC(linda_limit)
771 KeeperCallResult _pushed; 778 KeeperCallResult _pushed;
772 if (_linda->cancelStatus == Linda::Active) { 779 if (_linda->cancelStatus == Linda::Active) {
773 if (_unlimited) { 780 if (_unlimited) {
774 LUA_ASSERT(L_, lua_gettop(L_) == 3 && luaG_tostring(L_, StackIndex{ 3 }) == "unlimited"); 781 LUA_ASSERT(L_, lua_gettop(L_) == 3 && luaW_tostring(L_, StackIndex{ 3 }) == "unlimited");
775 // inside the Keeper, unlimited is signified with a -1 limit (can't use nil because of nil kNilSentinel conversions!) 782 // inside the Keeper, unlimited is signified with a -1 limit (can't use nil because of nil kNilSentinel conversions!)
776 lua_pop(L_, 1); // L_: linda slot 783 lua_pop(L_, 1); // L_: linda slot
777 lua_pushinteger(L_, -1); // L_: linda slot nil 784 lua_pushinteger(L_, -1); // L_: linda slot nil
778 } 785 }
779 Keeper* const _keeper{ _linda->whichKeeper() }; 786 Keeper* const _keeper{ _linda->whichKeeper() };
780 _pushed = keeper_call(_keeper->K, KEEPER_API(limit), L_, _linda, StackIndex{ 2 }); 787 _pushed = keeper_call(_keeper->K, KEEPER_API(limit), L_, _linda, StackIndex{ 2 });
781 LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 2) && luaG_type(L_, kIdxTop) == LuaType::STRING); 788 LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 2) && luaW_type(L_, kIdxTop) == LuaType::STRING);
782 if (_nargs == 3) { // 3 args: setting the limit 789 if (_nargs == 3) { // 3 args: setting the limit
783 // changing the limit: no error, boolean value saying if we should wake blocked writer threads 790 // changing the limit: no error, boolean value saying if we should wake blocked writer threads
784 LUA_ASSERT(L_, luaG_type(L_, StackIndex{ -2 }) == LuaType::BOOLEAN); // L_: bool string 791 LUA_ASSERT(L_, luaW_type(L_, StackIndex{ -2 }) == LuaType::BOOLEAN); // L_: bool string
785 if (lua_toboolean(L_, -2)) { 792 if (lua_toboolean(L_, -2)) {
786 _linda->readHappened.notify_all(); // To be done from within the 'K' locking area 793 _linda->readHappened.notify_all(); // To be done from within the 'K' locking area
787 } 794 }
788 } else { // 2 args: reading the limit 795 } else { // 2 args: reading the limit
789 // reading the limit: a number >=0 or "unlimited" 796 // reading the limit: a number >=0 or "unlimited"
790 LUA_ASSERT(L_, luaG_type(L_, StackIndex{ -2 }) == LuaType::NUMBER || luaG_tostring(L_, StackIndex{ -2 }) == "unlimited"); 797 LUA_ASSERT(L_, luaW_type(L_, StackIndex{ -2 }) == LuaType::NUMBER || luaW_tostring(L_, StackIndex{ -2 }) == "unlimited");
791 } 798 }
792 } else { // linda is cancelled 799 } else { // linda is cancelled
793 // do nothing and return nil,lanes.cancel_error 800 // do nothing and return nil,lanes.cancel_error
@@ -843,7 +850,7 @@ LUAG_FUNC(linda_restrict)
843 int const _nargs{ lua_gettop(L_) }; 850 int const _nargs{ lua_gettop(L_) };
844 luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments"); 851 luaL_argcheck(L_, _nargs == 2 || _nargs == 3, 2, "wrong number of arguments");
845 // make sure we got a known restrict mode, (or nothing) 852 // make sure we got a known restrict mode, (or nothing)
846 std::string_view const _mode{ luaG_tostring(L_, StackIndex{ 3 }) }; 853 std::string_view const _mode{ luaW_tostring(L_, StackIndex{ 3 }) };
847 if (!_mode.empty() && (_mode != "none" && _mode != "set/get" && _mode != "send/receive")) { 854 if (!_mode.empty() && (_mode != "none" && _mode != "set/get" && _mode != "send/receive")) {
848 raise_luaL_argerror(L_, StackIndex{ 3 }, "unknown restrict mode"); 855 raise_luaL_argerror(L_, StackIndex{ 3 }, "unknown restrict mode");
849 } 856 }
@@ -855,7 +862,7 @@ LUAG_FUNC(linda_restrict)
855 Keeper* const _keeper{ _linda->whichKeeper() }; 862 Keeper* const _keeper{ _linda->whichKeeper() };
856 _pushed = keeper_call(_keeper->K, KEEPER_API(restrict), L_, _linda, StackIndex{ 2 }); 863 _pushed = keeper_call(_keeper->K, KEEPER_API(restrict), L_, _linda, StackIndex{ 2 });
857 // we should get a single return value: the string describing the previous restrict mode 864 // we should get a single return value: the string describing the previous restrict mode
858 LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 1) && luaG_type(L_, kIdxTop) == LuaType::STRING); 865 LUA_ASSERT(L_, _pushed.has_value() && (_pushed.value() == 1) && luaW_type(L_, kIdxTop) == LuaType::STRING);
859 } else { // linda is cancelled 866 } else { // linda is cancelled
860 // do nothing and return nil,lanes.cancel_error 867 // do nothing and return nil,lanes.cancel_error
861 lua_pushnil(L_); 868 lua_pushnil(L_);
@@ -916,6 +923,7 @@ LUAG_FUNC(linda_send)
916 _cancel = (_cancel != CancelRequest::None) 923 _cancel = (_cancel != CancelRequest::None)
917 ? _cancel 924 ? _cancel
918 : ((_linda->cancelStatus == Linda::Cancelled) ? CancelRequest::Soft : CancelRequest::None); 925 : ((_linda->cancelStatus == Linda::Cancelled) ? CancelRequest::Soft : CancelRequest::None);
926
919 // if user wants to cancel, or looped because of a timeout, the call returns without sending anything 927 // if user wants to cancel, or looped because of a timeout, the call returns without sending anything
920 if (!_try_again || _cancel != CancelRequest::None) { 928 if (!_try_again || _cancel != CancelRequest::None) {
921 _pushed.emplace(0); 929 _pushed.emplace(0);
@@ -948,38 +956,7 @@ LUAG_FUNC(linda_send)
948 } 956 }
949 957
950 // storage limit hit, wait until timeout or signalled that we should try again 958 // storage limit hit, wait until timeout or signalled that we should try again
951 { 959 _try_again = WaitInternal(L_, _lane, _linda, _keeper, _linda->readHappened, _until);
952 Lane::Status _prev_status{ Lane::Error }; // prevent 'might be used uninitialized' warnings
953 if (_lane != nullptr) {
954 // change status of lane to "waiting"
955 _prev_status = _lane->status.load(std::memory_order_acquire); // Running, most likely
956 LUA_ASSERT(L_, _prev_status == Lane::Running); // but check, just in case
957 LUA_ASSERT(L_, _lane->waiting_on == nullptr);
958 _lane->waiting_on = &_linda->readHappened;
959 _lane->status.store(Lane::Waiting, std::memory_order_release);
960 }
961
962 // wait until the final target date by small increments, interrupting regularly so that we can check for cancel requests,
963 // in case some timing issue caused a cancel request to be issued, and the condvar signalled, before we actually wait for it
964 auto const [_forceTryAgain, _until_check_cancel] = std::invoke([_until, wakePeriod = _linda->getWakePeriod()] {
965 auto _until_check_cancel{ std::chrono::time_point<std::chrono::steady_clock>::max() };
966 if (wakePeriod.count() > 0.0f) {
967 _until_check_cancel = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(wakePeriod);
968 }
969 bool const _forceTryAgain{ _until_check_cancel < _until };
970 return std::make_tuple(_forceTryAgain, _forceTryAgain ? _until_check_cancel : _until);
971 });
972
973 // could not send because no room: wait until some data was read before trying again, or until timeout is reached
974 std::unique_lock<std::mutex> _guard{ _keeper->mutex, std::adopt_lock };
975 std::cv_status const status{ _linda->readHappened.wait_until(_guard, _until_check_cancel) };
976 _guard.release(); // we don't want to unlock the mutex on exit!
977 _try_again = _forceTryAgain || (status == std::cv_status::no_timeout); // detect spurious wakeups
978 if (_lane != nullptr) {
979 _lane->waiting_on = nullptr;
980 _lane->status.store(_prev_status, std::memory_order_release);
981 }
982 }
983 } 960 }
984 STACK_CHECK(_K, 0); 961 STACK_CHECK(_K, 0);
985 962
@@ -1005,7 +982,7 @@ LUAG_FUNC(linda_send)
1005 } else { 982 } else {
1006 // not enough room in the Linda slot to fulfill the request, return nil, "timeout" 983 // not enough room in the Linda slot to fulfill the request, return nil, "timeout"
1007 lua_pushnil(L_); 984 lua_pushnil(L_);
1008 luaG_pushstring(L_, "timeout"); 985 luaW_pushstring(L_, "timeout");
1009 return 2; 986 return 2;
1010 } 987 }
1011 } 988 }
@@ -1040,7 +1017,7 @@ LUAG_FUNC(linda_set)
1040 if (kRestrictedChannel.equals(L_, kIdxTop)) { 1017 if (kRestrictedChannel.equals(L_, kIdxTop)) {
1041 raise_luaL_error(L_, "Key is restricted"); 1018 raise_luaL_error(L_, "Key is restricted");
1042 } 1019 }
1043 LUA_ASSERT(L_, _pushed.value() == 2 && luaG_type(L_, kIdxTop) == LuaType::STRING && luaG_type(L_, StackIndex{ -2 }) == LuaType::BOOLEAN); 1020 LUA_ASSERT(L_, _pushed.value() == 2 && luaW_type(L_, kIdxTop) == LuaType::STRING && luaW_type(L_, StackIndex{ -2 }) == LuaType::BOOLEAN);
1044 1021
1045 if (_has_data) { 1022 if (_has_data) {
1046 // we put some data in the slot, tell readers that they should wake 1023 // we put some data in the slot, tell readers that they should wake
@@ -1102,7 +1079,7 @@ LUAG_FUNC(linda_towatch)
1102LUAG_FUNC(linda_wake) 1079LUAG_FUNC(linda_wake)
1103{ 1080{
1104 Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; 1081 Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) };
1105 std::string_view const _who{ luaG_optstring(L_, StackIndex{ 2 }, "both") }; 1082 std::string_view const _who{ luaW_optstring(L_, StackIndex{ 2 }, "both") };
1106 // make sure we got 2 arguments: the linda and the wake targets 1083 // make sure we got 2 arguments: the linda and the wake targets
1107 luaL_argcheck(L_, lua_gettop(L_) <= 2, 2, "wrong number of arguments"); 1084 luaL_argcheck(L_, lua_gettop(L_) <= 2, 2, "wrong number of arguments");
1108 1085
@@ -1178,8 +1155,8 @@ LUAG_FUNC(linda)
1178 if (lua_isnil(L_, kIdxTop)) { 1155 if (lua_isnil(L_, kIdxTop)) {
1179 lua_pop(L_, 1); 1156 lua_pop(L_, 1);
1180 lua_pushnumber(L_, _U->lindaWakePeriod.count()); 1157 lua_pushnumber(L_, _U->lindaWakePeriod.count());
1181 } else if (luaG_type(L_, kIdxTop) == LuaType::STRING) { 1158 } else if (luaW_type(L_, kIdxTop) == LuaType::STRING) {
1182 if (luaG_tostring(L_, kIdxTop) != "never") { 1159 if (luaW_tostring(L_, kIdxTop) != "never") {
1183 luaL_argerror(L_, 1, "invalid wake_period"); 1160 luaL_argerror(L_, 1, "invalid wake_period");
1184 } else { 1161 } else {
1185 lua_pop(L_, 1); 1162 lua_pop(L_, 1);
@@ -1201,7 +1178,7 @@ LUAG_FUNC(linda)
1201 1178
1202#if LUA_VERSION_NUM >= 504 // to-be-closed support starts with Lua 5.4 1179#if LUA_VERSION_NUM >= 504 // to-be-closed support starts with Lua 5.4
1203 lua_getfield(L_, 1, "close_handler"); // L_: {} wake_period group close_handler 1180 lua_getfield(L_, 1, "close_handler"); // L_: {} wake_period group close_handler
1204 LuaType const _handlerType{ luaG_type(L_, kIdxTop) }; 1181 LuaType const _handlerType{ luaW_type(L_, kIdxTop) };
1205 if (_handlerType == LuaType::NIL) { 1182 if (_handlerType == LuaType::NIL) {
1206 lua_pop(L_, 1); // L_: {} wake_period group 1183 lua_pop(L_, 1); // L_: {} wake_period group
1207 } else if (_handlerType == LuaType::USERDATA || _handlerType == LuaType::TABLE) { 1184 } else if (_handlerType == LuaType::USERDATA || _handlerType == LuaType::TABLE) {
@@ -1212,7 +1189,7 @@ LUAG_FUNC(linda)
1212 } 1189 }
1213#endif // LUA_VERSION_NUM >= 504 1190#endif // LUA_VERSION_NUM >= 504
1214 1191
1215 auto const _nameType{ luaG_getfield(L_, StackIndex{ 1 }, "name") }; // L_: {} wake_period group [close_handler] name 1192 auto const _nameType{ luaW_getfield(L_, StackIndex{ 1 }, "name") }; // L_: {} wake_period group [close_handler] name
1216 luaL_argcheck(L_, _nameType == LuaType::NIL || _nameType == LuaType::STRING, 1, "name is not a string"); 1193 luaL_argcheck(L_, _nameType == LuaType::NIL || _nameType == LuaType::STRING, 1, "name is not a string");
1217 lua_replace(L_, 1); // L_: name wake_period group [close_handler] 1194 lua_replace(L_, 1); // L_: name wake_period group [close_handler]
1218 } 1195 }
diff --git a/src/linda.hpp b/src/linda.hpp
index cff30e5..f02c46e 100644
--- a/src/linda.hpp
+++ b/src/linda.hpp
@@ -14,26 +14,6 @@ class Linda final
14: public DeepPrelude // Deep userdata MUST start with this header 14: public DeepPrelude // Deep userdata MUST start with this header
15{ 15{
16 public: 16 public:
17 class [[nodiscard]] KeeperOperationInProgress final
18 {
19 private:
20 Linda& linda;
21 lua_State* const L{}; // just here for inspection while debugging
22
23 public:
24 KeeperOperationInProgress(Linda& linda_, lua_State* const L_)
25 : linda{ linda_ }
26 , L{ L_ }
27 {
28 [[maybe_unused]] UnusedInt const _prev{ linda.keeperOperationCount.fetch_add(1, std::memory_order_seq_cst) };
29 }
30
31 public:
32 ~KeeperOperationInProgress()
33 {
34 [[maybe_unused]] UnusedInt const _prev{ linda.keeperOperationCount.fetch_sub(1, std::memory_order_seq_cst) };
35 }
36 };
37 17
38 enum class [[nodiscard]] Status 18 enum class [[nodiscard]] Status
39 { 19 {
@@ -51,7 +31,7 @@ class Linda final
51 // depending on the name length, it is either embedded inside the Linda, or allocated separately 31 // depending on the name length, it is either embedded inside the Linda, or allocated separately
52 std::variant<std::string_view, EmbeddedName> nameVariant{}; 32 std::variant<std::string_view, EmbeddedName> nameVariant{};
53 // counts the keeper operations in progress 33 // counts the keeper operations in progress
54 std::atomic<int> keeperOperationCount{}; 34 mutable std::atomic<int> keeperOperationCount{};
55 lua_Duration wakePeriod{}; 35 lua_Duration wakePeriod{};
56 36
57 public: 37 public:
@@ -110,7 +90,5 @@ class Linda final
110 static int ProtectedCall(lua_State* L_, lua_CFunction f_); 90 static int ProtectedCall(lua_State* L_, lua_CFunction f_);
111 void pushCancelString(lua_State* L_) const; 91 void pushCancelString(lua_State* L_) const;
112 [[nodiscard]] 92 [[nodiscard]]
113 KeeperOperationInProgress startKeeperOperation(lua_State* const L_) { return KeeperOperationInProgress{ *this, L_ }; };
114 [[nodiscard]]
115 Keeper* whichKeeper() const { return U->keepers.getKeeper(keeperIndex); } 93 Keeper* whichKeeper() const { return U->keepers.getKeeper(keeperIndex); }
116}; 94};
diff --git a/src/lindafactory.cpp b/src/lindafactory.cpp
index 4eab0c1..483037f 100644
--- a/src/lindafactory.cpp
+++ b/src/lindafactory.cpp
@@ -47,22 +47,22 @@ void LindaFactory::createMetatable(lua_State* L_) const
47 lua_newtable(L_); // L_: mt 47 lua_newtable(L_); // L_: mt
48 48
49 // protect metatable from external access 49 // protect metatable from external access
50 luaG_pushstring(L_, kLindaMetatableName); // L_: mt "<name>" 50 luaW_pushstring(L_, kLindaMetatableName); // L_: mt "<name>"
51 lua_setfield(L_, -2, "__metatable"); // L_: mt 51 lua_setfield(L_, -2, "__metatable"); // L_: mt
52 52
53 // the linda functions 53 // the linda functions
54 luaG_registerlibfuncs(L_, mLindaMT); 54 luaW_registerlibfuncs(L_, mLindaMT);
55 55
56 kNilSentinel.pushKey(L_); // L_: mt kNilSentinel 56 kNilSentinel.pushKey(L_); // L_: mt kNilSentinel
57 lua_setfield(L_, -2, "null"); // L_: mt 57 lua_setfield(L_, -2, "null"); // L_: mt
58 58
59 // if the metatable contains __index, leave it as is 59 // if the metatable contains __index, leave it as is
60 if (luaG_getfield(L_, kIdxTop, kIndex) != LuaType::NIL) { // L_: mt __index 60 if (luaW_getfield(L_, kIdxTop, kIndex) != LuaType::NIL) { // L_: mt __index
61 lua_pop(L_, 1); // L_: mt __index 61 lua_pop(L_, 1); // L_: mt __index
62 } else { 62 } else {
63 // metatable is its own index 63 // metatable is its own index
64 lua_pushvalue(L_, kIdxTop); // L_: mt mt 64 lua_pushvalue(L_, kIdxTop); // L_: mt mt
65 luaG_setfield(L_, StackIndex{ -2 }, kIndex); // L_: mt 65 luaW_setfield(L_, StackIndex{ -2 }, kIndex); // L_: mt
66 } 66 }
67 67
68 STACK_CHECK(L_, 1); 68 STACK_CHECK(L_, 1);
@@ -110,7 +110,7 @@ DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* const L_) const
110{ 110{
111 STACK_CHECK_START_REL(L_, 0); 111 STACK_CHECK_START_REL(L_, 0);
112 // we always expect name, wake_period, group at the bottom of the stack (either can be nil). any extra stuff we ignore and keep unmodified 112 // we always expect name, wake_period, group at the bottom of the stack (either can be nil). any extra stuff we ignore and keep unmodified
113 std::string_view _linda_name{ luaG_tostring(L_, StackIndex{ 1 }) }; 113 std::string_view _linda_name{ luaW_tostring(L_, StackIndex{ 1 }) };
114 auto const _wake_period{ static_cast<lua_Duration>(lua_tonumber(L_, 2)) }; 114 auto const _wake_period{ static_cast<lua_Duration>(lua_tonumber(L_, 2)) };
115 LindaGroup const _linda_group{ static_cast<int>(lua_tointeger(L_, 3)) }; 115 LindaGroup const _linda_group{ static_cast<int>(lua_tointeger(L_, 3)) };
116 116
@@ -119,12 +119,12 @@ DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* const L_) const
119 lua_Debug _ar; 119 lua_Debug _ar;
120 if (lua_getstack(L_, 1, &_ar) == 1) { // 1 because we want the name of the function that called lanes.linda (where we currently are) 120 if (lua_getstack(L_, 1, &_ar) == 1) { // 1 because we want the name of the function that called lanes.linda (where we currently are)
121 lua_getinfo(L_, "Sln", &_ar); 121 lua_getinfo(L_, "Sln", &_ar);
122 _linda_name = luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); 122 _linda_name = luaW_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline);
123 } else { 123 } else {
124 _linda_name = luaG_pushstring(L_, "<unresolved>"); 124 _linda_name = luaW_pushstring(L_, "<unresolved>");
125 } 125 }
126 // since the name is not empty, it is at slot 1, and we can replace "auto" with the result, just in case 126 // since the name is not empty, it is at slot 1, and we can replace "auto" with the result, just in case
127 LUA_ASSERT(L_, luaG_tostring(L_, StackIndex{ 1 }) == "auto"); 127 LUA_ASSERT(L_, luaW_tostring(L_, StackIndex{ 1 }) == "auto");
128 lua_replace(L_, 1); 128 lua_replace(L_, 1);
129 } 129 }
130 130
diff --git a/src/nameof.cpp b/src/nameof.cpp
index f236f73..992569b 100644
--- a/src/nameof.cpp
+++ b/src/nameof.cpp
@@ -52,25 +52,25 @@ FqnLength DiscoverObjectNameRecur(lua_State* const L_, FqnLength const shortest_
52 static constexpr auto _pushNameOnFQN = [](lua_State* const L_) { 52 static constexpr auto _pushNameOnFQN = [](lua_State* const L_) {
53 STACK_CHECK_START_REL(L_, 0); 53 STACK_CHECK_START_REL(L_, 0);
54 lua_pushvalue(L_, -2); // L_: o "r" {c} {fqn} ... k v k 54 lua_pushvalue(L_, -2); // L_: o "r" {c} {fqn} ... k v k
55 auto const _keyType{ luaG_type(L_, kIdxTop) }; 55 auto const _keyType{ luaW_type(L_, kIdxTop) };
56 if (_keyType != LuaType::STRING) { 56 if (_keyType != LuaType::STRING) {
57 lua_pop(L_, 1); // L_: o "r" {c} {fqn} ... k v 57 lua_pop(L_, 1); // L_: o "r" {c} {fqn} ... k v
58 luaG_pushstring(L_, "<%s>", luaG_typename(L_, _keyType).data()); // L_: o "r" {c} {fqn} ... k v "<type of k>" 58 luaW_pushstring(L_, "<%s>", luaW_typename(L_, _keyType).data()); // L_: o "r" {c} {fqn} ... k v "<type of k>"
59 } else { 59 } else {
60 // decorate the key string with something that tells us the type of the value 60 // decorate the key string with something that tells us the type of the value
61 switch (luaG_type(L_, StackIndex{ -2 })) { 61 switch (luaW_type(L_, StackIndex{ -2 })) {
62 default: 62 default:
63 LUA_ASSERT(L_, false); // there is something wrong if we end up here 63 LUA_ASSERT(L_, false); // there is something wrong if we end up here
64 luaG_pushstring(L_, "??"); // L_: o "r" {c} {fqn} ... k v "k" "??" 64 luaW_pushstring(L_, "??"); // L_: o "r" {c} {fqn} ... k v "k" "??"
65 break; 65 break;
66 case LuaType::FUNCTION: 66 case LuaType::FUNCTION:
67 luaG_pushstring(L_, "()"); // L_: o "r" {c} {fqn} ... k v "k" "()" 67 luaW_pushstring(L_, "()"); // L_: o "r" {c} {fqn} ... k v "k" "()"
68 break; 68 break;
69 case LuaType::TABLE: 69 case LuaType::TABLE:
70 luaG_pushstring(L_, "[]"); // L_: o "r" {c} {fqn} ... k v "k" "[]" 70 luaW_pushstring(L_, "[]"); // L_: o "r" {c} {fqn} ... k v "k" "[]"
71 break; 71 break;
72 case LuaType::USERDATA: 72 case LuaType::USERDATA:
73 luaG_pushstring(L_, "<>"); // L_: o "r" {c} {fqn} ... k v "k" "<>" 73 luaW_pushstring(L_, "<>"); // L_: o "r" {c} {fqn} ... k v "k" "<>"
74 break; 74 break;
75 } 75 }
76 lua_concat(L_, 2); // L_: o "r" {c} {fqn} ... k v "k??" 76 lua_concat(L_, 2); // L_: o "r" {c} {fqn} ... k v "k??"
@@ -92,7 +92,7 @@ FqnLength DiscoverObjectNameRecur(lua_State* const L_, FqnLength const shortest_
92 static constexpr auto _recurseThenPop = [](lua_State* const L_, FqnLength const shortest_) -> FqnLength { 92 static constexpr auto _recurseThenPop = [](lua_State* const L_, FqnLength const shortest_) -> FqnLength {
93 STACK_CHECK_START_REL(L_, 0); // L_: o "r" {c} {fqn} ... <> 93 STACK_CHECK_START_REL(L_, 0); // L_: o "r" {c} {fqn} ... <>
94 FqnLength r_{ shortest_ }; 94 FqnLength r_{ shortest_ };
95 auto const _type{ luaG_type(L_, kIdxTop) }; 95 auto const _type{ luaW_type(L_, kIdxTop) };
96 if (_type == LuaType::TABLE || _type == LuaType::USERDATA || _type == LuaType::FUNCTION) { 96 if (_type == LuaType::TABLE || _type == LuaType::USERDATA || _type == LuaType::FUNCTION) {
97 r_ = DiscoverObjectNameRecur(L_, shortest_); 97 r_ = DiscoverObjectNameRecur(L_, shortest_);
98 STACK_CHECK(L_, 0); 98 STACK_CHECK(L_, 0);
@@ -113,7 +113,7 @@ FqnLength DiscoverObjectNameRecur(lua_State* const L_, FqnLength const shortest_
113 STACK_CHECK_START_REL(L_, 0); // L_: o "r" {c} {fqn} ... k v 113 STACK_CHECK_START_REL(L_, 0); // L_: o "r" {c} {fqn} ... k v
114 114
115 // filter out uninteresting values 115 // filter out uninteresting values
116 auto const _valType{ luaG_type(L_, kIdxTop) }; 116 auto const _valType{ luaW_type(L_, kIdxTop) };
117 if (_valType == LuaType::NIL || _valType == LuaType::BOOLEAN || _valType == LuaType::LIGHTUSERDATA || _valType == LuaType::NUMBER || _valType == LuaType::STRING) { 117 if (_valType == LuaType::NIL || _valType == LuaType::BOOLEAN || _valType == LuaType::LIGHTUSERDATA || _valType == LuaType::NUMBER || _valType == LuaType::STRING) {
118 lua_pop(L_, 1); // L_: o "r" {c} {fqn} ... k 118 lua_pop(L_, 1); // L_: o "r" {c} {fqn} ... k
119 return _r; 119 return _r;
@@ -177,7 +177,7 @@ FqnLength DiscoverObjectNameRecur(lua_State* const L_, FqnLength const shortest_
177 177
178 UserValueIndex _uvi{ 0 }; 178 UserValueIndex _uvi{ 0 };
179 while (lua_getiuservalue(L_, kIdxTop, ++_uvi) != LUA_TNONE) { // L_: o "r" {c} {fqn} ... U uv 179 while (lua_getiuservalue(L_, kIdxTop, ++_uvi) != LUA_TNONE) { // L_: o "r" {c} {fqn} ... U uv
180 luaG_pushstring(L_, "<uv:%d>", _uvi); // L_: o "r" {c} {fqn} ... U uv name 180 luaW_pushstring(L_, "<uv:%d>", _uvi); // L_: o "r" {c} {fqn} ... U uv name
181 lua_insert(L_, -2); // L_: o "r" {c} {fqn} ... U name uv 181 lua_insert(L_, -2); // L_: o "r" {c} {fqn} ... U name uv
182 r_ = _processKeyValue(L_, r_); // L_: o "r" {c} {fqn} ... U name 182 r_ = _processKeyValue(L_, r_); // L_: o "r" {c} {fqn} ... U name
183 lua_pop(L_, 1); // L_: o "r" {c} {fqn} ... U 183 lua_pop(L_, 1); // L_: o "r" {c} {fqn} ... U
@@ -200,7 +200,7 @@ FqnLength DiscoverObjectNameRecur(lua_State* const L_, FqnLength const shortest_
200 _upname = "<C>"; 200 _upname = "<C>";
201 } 201 }
202 202
203 luaG_pushstring(L_, "upvalue:%s", _upname); // L_: o "r" {c} {fqn} ... F up name 203 luaW_pushstring(L_, "upvalue:%s", _upname); // L_: o "r" {c} {fqn} ... F up name
204 lua_insert(L_, -2); // L_: o "r" {c} {fqn} ... F name up 204 lua_insert(L_, -2); // L_: o "r" {c} {fqn} ... F name up
205 r_ = _processKeyValue(L_, r_); // L_: o "r" {c} {fqn} ... F name 205 r_ = _processKeyValue(L_, r_); // L_: o "r" {c} {fqn} ... F name
206 lua_pop(L_, 1); // L_: o "r" {c} {fqn} ... F 206 lua_pop(L_, 1); // L_: o "r" {c} {fqn} ... F
@@ -213,7 +213,7 @@ FqnLength DiscoverObjectNameRecur(lua_State* const L_, FqnLength const shortest_
213 STACK_GROW(L_, 2); 213 STACK_GROW(L_, 2);
214 STACK_CHECK_START_REL(L_, 0); 214 STACK_CHECK_START_REL(L_, 0);
215 // stack top contains the location to search in (table, function, userdata) 215 // stack top contains the location to search in (table, function, userdata)
216 [[maybe_unused]] auto const _typeWhere{ luaG_type(L_, kIdxTop) }; 216 [[maybe_unused]] auto const _typeWhere{ luaW_type(L_, kIdxTop) };
217 LUA_ASSERT(L_, _typeWhere == LuaType::TABLE || _typeWhere == LuaType::USERDATA || _typeWhere == LuaType::FUNCTION); 217 LUA_ASSERT(L_, _typeWhere == LuaType::TABLE || _typeWhere == LuaType::USERDATA || _typeWhere == LuaType::FUNCTION);
218 lua_pushvalue(L_, kIdxTop); // L_: o "r" {c} {fqn} ... <> <> 218 lua_pushvalue(L_, kIdxTop); // L_: o "r" {c} {fqn} ... <> <>
219 lua_rawget(L_, kCache); // L_: o "r" {c} {fqn} ... <> nil/N 219 lua_rawget(L_, kCache); // L_: o "r" {c} {fqn} ... <> nil/N
@@ -263,12 +263,12 @@ LUAG_FUNC(nameof)
263 263
264 // nil, boolean, light userdata, number and string aren't identifiable 264 // nil, boolean, light userdata, number and string aren't identifiable
265 static constexpr auto _isIdentifiable = [](lua_State* const L_) { 265 static constexpr auto _isIdentifiable = [](lua_State* const L_) {
266 auto const _valType{ luaG_type(L_, kIdxTop) }; 266 auto const _valType{ luaW_type(L_, kIdxTop) };
267 return _valType == LuaType::TABLE || _valType == LuaType::FUNCTION || _valType == LuaType::USERDATA || _valType == LuaType::THREAD; 267 return _valType == LuaType::TABLE || _valType == LuaType::FUNCTION || _valType == LuaType::USERDATA || _valType == LuaType::THREAD;
268 }; 268 };
269 269
270 if (!_isIdentifiable(L_)) { 270 if (!_isIdentifiable(L_)) {
271 luaG_pushstring(L_, luaG_typename(L_, kIdxTop)); // L_: o "type" 271 luaW_pushstring(L_, luaW_typename(L_, kIdxTop)); // L_: o "type"
272 lua_insert(L_, -2); // L_: "type" o 272 lua_insert(L_, -2); // L_: "type" o
273 return 2; 273 return 2;
274 } 274 }
@@ -282,15 +282,15 @@ LUAG_FUNC(nameof)
282 // push a table whose contents are strings that, when concatenated, produce unique name 282 // push a table whose contents are strings that, when concatenated, produce unique name
283 lua_newtable(L_); // L_: o nil {c} {fqn} 283 lua_newtable(L_); // L_: o nil {c} {fqn}
284 // {fqn}[1] = "_G" 284 // {fqn}[1] = "_G"
285 luaG_pushstring(L_, LUA_GNAME); // L_: o nil {c} {fqn} "_G" 285 luaW_pushstring(L_, LUA_GNAME); // L_: o nil {c} {fqn} "_G"
286 lua_rawseti(L_, -2, 1); // L_: o nil {c} {fqn} 286 lua_rawseti(L_, -2, 1); // L_: o nil {c} {fqn}
287 // this is where we start the search 287 // this is where we start the search
288 luaG_pushglobaltable(L_); // L_: o nil {c} {fqn} _G 288 luaW_pushglobaltable(L_); // L_: o nil {c} {fqn} _G
289 auto const _foundInG{ DiscoverObjectNameRecur(L_, FqnLength{ std::numeric_limits<FqnLength::type>::max() }) }; 289 auto const _foundInG{ DiscoverObjectNameRecur(L_, FqnLength{ std::numeric_limits<FqnLength::type>::max() }) };
290 if (lua_isnil(L_, 2)) { // try again with registry, just in case... 290 if (lua_isnil(L_, 2)) { // try again with registry, just in case...
291 LUA_ASSERT(L_, _foundInG == std::numeric_limits<FqnLength::type>::max()); 291 LUA_ASSERT(L_, _foundInG == std::numeric_limits<FqnLength::type>::max());
292 lua_pop(L_, 1); // L_: o nil {c} {fqn} 292 lua_pop(L_, 1); // L_: o nil {c} {fqn}
293 luaG_pushstring(L_, "_R"); // L_: o nil {c} {fqn} "_R" 293 luaW_pushstring(L_, "_R"); // L_: o nil {c} {fqn} "_R"
294 lua_rawseti(L_, -2, 1); // L_: o nil {c} {fqn} 294 lua_rawseti(L_, -2, 1); // L_: o nil {c} {fqn}
295 lua_pushvalue(L_, kIdxRegistry); // L_: o nil {c} {fqn} _R 295 lua_pushvalue(L_, kIdxRegistry); // L_: o nil {c} {fqn} _R
296 [[maybe_unused]] auto const _foundInR{ DiscoverObjectNameRecur(L_, FqnLength{ std::numeric_limits<FqnLength::type>::max() }) }; 296 [[maybe_unused]] auto const _foundInR{ DiscoverObjectNameRecur(L_, FqnLength{ std::numeric_limits<FqnLength::type>::max() }) };
diff --git a/src/state.cpp b/src/state.cpp
index fc7f5ef..2f64194 100644
--- a/src/state.cpp
+++ b/src/state.cpp
@@ -166,7 +166,7 @@ namespace state {
166 }; 166 };
167 167
168 if (_L == nullptr) { 168 if (_L == nullptr) {
169 raise_luaL_error(from_, "luaG_newstate() failed while creating state; out of memory"); 169 raise_luaL_error(from_, "luaW_newstate() failed while creating state; out of memory");
170 } 170 }
171 return _L; 171 return _L;
172 } 172 }
@@ -202,11 +202,11 @@ namespace state {
202 202
203 // neither libs (not even 'base') nor special init func: we are done 203 // neither libs (not even 'base') nor special init func: we are done
204 if (!libs_.has_value() && std::holds_alternative<std::nullptr_t>(U_->onStateCreateFunc)) { 204 if (!libs_.has_value() && std::holds_alternative<std::nullptr_t>(U_->onStateCreateFunc)) {
205 DEBUGSPEW_CODE(DebugSpew(U_) << "luaG_newstate(nullptr)" << std::endl); 205 DEBUGSPEW_CODE(DebugSpew(U_) << "luaW_newstate(nullptr)" << std::endl);
206 return _L; 206 return _L;
207 } 207 }
208 208
209 DEBUGSPEW_CODE(DebugSpew(U_) << "luaG_newstate()" << std::endl); 209 DEBUGSPEW_CODE(DebugSpew(U_) << "luaW_newstate()" << std::endl);
210 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ }); 210 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ U_ });
211 211
212 // copy settings (for example because it may contain a Lua on_state_create function) 212 // copy settings (for example because it may contain a Lua on_state_create function)
@@ -239,7 +239,7 @@ namespace state {
239 lua_pop(_L, 1); 239 lua_pop(_L, 1);
240 } else { 240 } else {
241 lua_pushcfunction(_L, luaopen_base); 241 lua_pushcfunction(_L, luaopen_base);
242 luaG_pushstring(_L, ""); 242 luaW_pushstring(_L, "");
243 lua_call(_L, 1, 0); 243 lua_call(_L, 1, 0);
244 } 244 }
245 } 245 }
@@ -274,7 +274,7 @@ namespace state {
274 274
275 STACK_CHECK(_L, 0); 275 STACK_CHECK(_L, 0);
276 // after all this, register everything we find in our name<->function database 276 // after all this, register everything we find in our name<->function database
277 luaG_pushglobaltable(_L); // L: _G 277 luaW_pushglobaltable(_L); // L: _G
278 tools::PopulateFuncLookupTable(_L, kIdxTop, {}); 278 tools::PopulateFuncLookupTable(_L, kIdxTop, {});
279 lua_pop(_L, 1); // L: 279 lua_pop(_L, 1); // L:
280 STACK_CHECK(_L, 0); 280 STACK_CHECK(_L, 0);
@@ -286,19 +286,19 @@ namespace state {
286 kLookupRegKey.pushValue(_L); // L: {} 286 kLookupRegKey.pushValue(_L); // L: {}
287 lua_pushnil(_L); // L: {} nil 287 lua_pushnil(_L); // L: {} nil
288 while (lua_next(_L, -2)) { // L: {} k v 288 while (lua_next(_L, -2)) { // L: {} k v
289 luaG_pushstring(_L, "["); // L: {} k v "[" 289 luaW_pushstring(_L, "["); // L: {} k v "["
290 290
291 lua_getglobal(_L, "tostring"); // L: {} k v "[" tostring 291 lua_getglobal(_L, "tostring"); // L: {} k v "[" tostring
292 lua_pushvalue(_L, -4); // L: {} k v "[" tostring k 292 lua_pushvalue(_L, -4); // L: {} k v "[" tostring k
293 lua_call(_L, 1, 1); // L: {} k v "[" 'k' 293 lua_call(_L, 1, 1); // L: {} k v "[" 'k'
294 294
295 luaG_pushstring(_L, "] = "); // L: {} k v "[" 'k' "] = " 295 luaW_pushstring(_L, "] = "); // L: {} k v "[" 'k' "] = "
296 296
297 lua_getglobal(_L, "tostring"); // L: {} k v "[" 'k' "] = " tostring 297 lua_getglobal(_L, "tostring"); // L: {} k v "[" 'k' "] = " tostring
298 lua_pushvalue(_L, -5); // L: {} k v "[" 'k' "] = " tostring v 298 lua_pushvalue(_L, -5); // L: {} k v "[" 'k' "] = " tostring v
299 lua_call(_L, 1, 1); // L: {} k v "[" 'k' "] = " 'v' 299 lua_call(_L, 1, 1); // L: {} k v "[" 'k' "] = " 'v'
300 lua_concat(_L, 4); // L: {} k v "[k] = v" 300 lua_concat(_L, 4); // L: {} k v "[k] = v"
301 DEBUGSPEW_CODE(DebugSpew(U_) << luaG_tostring(_L, kIdxTop) << std::endl); 301 DEBUGSPEW_CODE(DebugSpew(U_) << luaW_tostring(_L, kIdxTop) << std::endl);
302 lua_pop(_L, 2); // L: {} k 302 lua_pop(_L, 2); // L: {} k
303 } // lua_next() // L: {} 303 } // lua_next() // L: {}
304 lua_pop(_L, 1); // L: 304 lua_pop(_L, 1); // L:
@@ -317,7 +317,7 @@ namespace state {
317 lua_newtable(L_); // L_: out 317 lua_newtable(L_); // L_: out
318 for (luaL_Reg const& _entry : local::sLibs) { 318 for (luaL_Reg const& _entry : local::sLibs) {
319 lua_pushboolean(L_, 1); // L_: out true 319 lua_pushboolean(L_, 1); // L_: out true
320 luaG_setfield(L_, StackIndex{ -2 }, std::string_view{ _entry.name }); // out[name] = true // L_: out 320 luaW_setfield(L_, StackIndex{ -2 }, std::string_view{ _entry.name }); // out[name] = true // L_: out
321 } 321 }
322 STACK_CHECK(L_, 1); 322 STACK_CHECK(L_, 1);
323 return 1; 323 return 1;
diff --git a/src/threading.cpp b/src/threading.cpp
index 3435075..4b27bed 100644
--- a/src/threading.cpp
+++ b/src/threading.cpp
@@ -49,6 +49,7 @@ THE SOFTWARE.
49 49
50#endif // __linux__ 50#endif // __linux__
51 51
52#include "compat.hpp"
52#include "threading.hpp" 53#include "threading.hpp"
53 54
54#if !defined(PLATFORM_XBOX) && !defined(PLATFORM_WIN32) && !defined(PLATFORM_POCKETPC) 55#if !defined(PLATFORM_XBOX) && !defined(PLATFORM_WIN32) && !defined(PLATFORM_POCKETPC)
@@ -82,25 +83,42 @@ THE SOFTWARE.
82#pragma warning(disable : 4054) 83#pragma warning(disable : 4054)
83#endif 84#endif
84 85
86static constexpr std::string_view StripFuncName(std::string_view const& where_)
87{
88 std::string_view funcname_{ where_ };
89
90 auto _args_pos{ funcname_.find_first_of('(') };
91 funcname_ = funcname_.substr(0, _args_pos);
92 auto _name_pos{ funcname_.find_last_of(' ') };
93 funcname_.remove_prefix(_name_pos + 1);
94 return funcname_;
95}
96
85/* 97/*
86 * FAIL is for unexpected API return values - essentially programming 98 * FAIL is for unexpected API return values - essentially programming
87 * error in _this_ code. 99 * error in _this_ code.
88 */ 100 */
89#if HAVE_WIN32 101#if HAVE_WIN32
90static void FAIL(char const* funcname_, DWORD const rc_) 102
103template <typename F, typename... ARGS>
104void Win32Invoke(lua_State* const L_, std::string_view const& where_, F& f_, ARGS... args_)
91{ 105{
106 auto const _ret{ std::invoke(f_, std::forward<ARGS>(args_)...) };
107 if (!_ret) {
108 auto const _rc{ GetLastError() };
109 std::string_view const _funcname{ StripFuncName(where_) };
110
92#if defined(PLATFORM_XBOX) 111#if defined(PLATFORM_XBOX)
93 fprintf(stderr, "%s() failed! (%d)\n", funcname_, rc_); 112 luaW_pushstring(L_, "%s() failed with code %d", _funcname.data(), _rc);
94#else // PLATFORM_XBOX 113#else // PLATFORM_XBOX
95 char buf[256]; 114 char _buf[256];
96 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, rc_, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buf, 256, nullptr); 115 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, _rc, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), _buf, 256, nullptr);
97 fprintf(stderr, "%s() failed! [GetLastError() -> %lu] '%s'", funcname_, rc_, buf); 116 luaW_pushstring(L_, "%s() failed with code %d '%s'", _funcname.data(), _rc, _buf);
98#endif // PLATFORM_XBOX 117#endif // PLATFORM_XBOX
99#ifdef _MSC_VER 118 raise_lua_error(L_);
100 __debugbreak(); // give a chance to the debugger! 119 }
101#endif // _MSC_VER
102 abort();
103} 120}
121
104#endif // HAVE_WIN32 122#endif // HAVE_WIN32
105 123
106/*---=== Threading ===---*/ 124/*---=== Threading ===---*/
@@ -121,33 +139,35 @@ static int const gs_prio_remap[] = {
121 139
122// ################################################################################################# 140// #################################################################################################
123 141
124void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) 142std::pair<int, int> THREAD_NATIVE_PRIOS()
125{ 143{
126 // prio range [-3,+3] was checked by the caller 144 return std::make_pair(THREAD_PRIORITY_IDLE, THREAD_PRIORITY_TIME_CRITICAL);
127 if (!SetThreadPriority(GetCurrentThread(), gs_prio_remap[prio_ + 3])) {
128 FAIL("THREAD_SET_PRIORITY", GetLastError());
129 }
130} 145}
131 146
132// ################################################################################################# 147// #################################################################################################
133 148
134void THREAD_SET_PRIORITY(std::thread& thread_, int prio_, [[maybe_unused]] bool sudo_) 149[[nodiscard]]
150void THREAD_SET_PRIORITY(lua_State* const L_, int const prio_, NativePrioFlag const native_, [[maybe_unused]] SudoFlag const sudo_)
135{ 151{
136 // prio range [-3,+3] was checked by the caller 152 // mapped prio range [-3,+3] was checked by the caller
137 // for some reason when building for mingw, native_handle() is an unsigned long long, but HANDLE is a void* 153 return Win32Invoke(L_, std::source_location::current().function_name(), SetThreadPriority, GetCurrentThread(), native_ ? prio_ : gs_prio_remap[prio_ + 3]);
138 // -> need a strong cast to make g++ happy
139 if (!SetThreadPriority(thread_.native_handle(), gs_prio_remap[prio_ + 3])) {
140 FAIL("THREAD_SET_PRIORITY", GetLastError());
141 }
142} 154}
143 155
144// ################################################################################################# 156// #################################################################################################
145 157
146void THREAD_SET_AFFINITY(unsigned int aff_) 158[[nodiscard]]
159void THREAD_SET_PRIORITY(lua_State* const L_, std::thread& thread_, int const prio_, NativePrioFlag const native_, [[maybe_unused]] SudoFlag const sudo_)
147{ 160{
148 if (!SetThreadAffinityMask(GetCurrentThread(), aff_)) { 161 // mapped prio range [-3,+3] was checked by the caller
149 FAIL("THREAD_SET_AFFINITY", GetLastError()); 162 return Win32Invoke(L_, std::source_location::current().function_name(), SetThreadPriority, thread_.native_handle(), native_ ? prio_ : gs_prio_remap[prio_ + 3]);
150 } 163}
164
165// #################################################################################################
166
167[[nodiscard]]
168void THREAD_SET_AFFINITY(lua_State* const L_, unsigned int aff_)
169{
170 return Win32Invoke(L_, std::source_location::current().function_name(), SetThreadAffinityMask, GetCurrentThread(), aff_);
151} 171}
152 172
153// ################################################################################################# 173// #################################################################################################
@@ -215,24 +235,24 @@ static int pthread_attr_setschedpolicy(pthread_attr_t* attr, int policy)
215#endif // pthread_attr_setschedpolicy() 235#endif // pthread_attr_setschedpolicy()
216#endif // defined(__MINGW32__) || defined(__MINGW64__) 236#endif // defined(__MINGW32__) || defined(__MINGW64__)
217 237
218static void _PT_FAIL(int rc, const char* name, const char* file, int line) 238template <typename F, typename... ARGS>
239void PthreadInvoke(lua_State* const L_, std::string_view const& where_, F& f_, ARGS... args_)
219{ 240{
220 const char* why = (rc == EINVAL) ? "EINVAL" 241 auto const _rc{ std::invoke(f_, std::forward<ARGS>(args_)...) };
221 : (rc == EBUSY) ? "EBUSY" 242 if (_rc) {
222 : (rc == EPERM) ? "EPERM" 243 std::string_view const _funcname{ StripFuncName(where_) };
223 : (rc == ENOMEM) ? "ENOMEM" 244
224 : (rc == ESRCH) ? "ESRCH" 245 char const* _why = (_rc == EINVAL) ? "EINVAL"
225 : (rc == ENOTSUP) ? "ENOTSUP" 246 : (_rc == EBUSY) ? "EBUSY"
226 : "<UNKNOWN>"; 247 : (_rc == EPERM) ? "EPERM"
227 fprintf(stderr, "%s %d: %s failed, %d %s\n", file, line, name, rc, why); 248 : (_rc == ENOMEM) ? "ENOMEM"
228 abort(); 249 : (_rc == ESRCH) ? "ESRCH"
229} 250 : (_rc == ENOTSUP) ? "ENOTSUP"
230#define PT_CALL(call) \ 251 : "<UNKNOWN>";
231 { \ 252
232 int rc = call; \ 253 raise_luaL_error(L_, "%s() failed with code %s", _funcname.data(), _why);
233 if (rc != 0) \
234 _PT_FAIL(rc, #call, __FILE__, __LINE__); \
235 } 254 }
255}
236 256
237// array of 7 thread priority values, hand-tuned by platform so that we offer a uniform [-3,+3] public priority range 257// array of 7 thread priority values, hand-tuned by platform so that we offer a uniform [-3,+3] public priority range
238static int const gs_prio_remap[] = { 258static int const gs_prio_remap[] = {
@@ -336,8 +356,8 @@ static int const gs_prio_remap[] = {
336// 356//
337#define _PRIO_MODE SCHED_OTHER 357#define _PRIO_MODE SCHED_OTHER
338#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS 358#define _PRIO_SCOPE PTHREAD_SCOPE_PROCESS
339#define _PRIO_HI 31 359#define _PRIO_HI 15
340#define _PRIO_0 15 360#define _PRIO_0 7
341#define _PRIO_LO 1 361#define _PRIO_LO 1
342#else 362#else
343#error "Unknown OS: not implemented!" 363#error "Unknown OS: not implemented!"
@@ -357,7 +377,18 @@ static int const gs_prio_remap[] = {
357#endif // _PRIO_0 377#endif // _PRIO_0
358}; 378};
359 379
360void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) 380// #################################################################################################
381
382std::pair<int, int> THREAD_NATIVE_PRIOS()
383{
384 int const _prio_min{ sched_get_priority_min(_PRIO_MODE) };
385 int const _prio_max{ sched_get_priority_max(_PRIO_MODE) };
386 return std::make_pair(_prio_min, _prio_max);
387}
388
389// #################################################################################################
390
391void THREAD_SET_PRIORITY(lua_State* const L_, int const prio_, NativePrioFlag const native_, [[maybe_unused]] SudoFlag const sudo_)
361{ 392{
362#ifdef PLATFORM_LINUX 393#ifdef PLATFORM_LINUX
363 if (!sudo_) // only root-privileged process can change priorities 394 if (!sudo_) // only root-privileged process can change priorities
@@ -366,13 +397,13 @@ void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_)
366 397
367 struct sched_param sp; 398 struct sched_param sp;
368 // prio range [-3,+3] was checked by the caller 399 // prio range [-3,+3] was checked by the caller
369 sp.sched_priority = gs_prio_remap[prio_ + 3]; 400 sp.sched_priority = native_ ? prio_ : gs_prio_remap[prio_ + 3];
370 PT_CALL(pthread_setschedparam(pthread_self(), _PRIO_MODE, &sp)); 401 PthreadInvoke(L_, std::source_location::current().function_name(), pthread_setschedparam, pthread_self(), _PRIO_MODE, &sp);
371} 402}
372 403
373// ################################################################################################# 404// #################################################################################################
374 405
375void THREAD_SET_PRIORITY(std::thread& thread_, int prio_, [[maybe_unused]] bool sudo_) 406void THREAD_SET_PRIORITY(lua_State* const L_, std::thread& thread_, int const prio_, NativePrioFlag const native_, [[maybe_unused]] SudoFlag const sudo_)
376{ 407{
377#ifdef PLATFORM_LINUX 408#ifdef PLATFORM_LINUX
378 if (!sudo_) // only root-privileged process can change priorities 409 if (!sudo_) // only root-privileged process can change priorities
@@ -381,28 +412,26 @@ void THREAD_SET_PRIORITY(std::thread& thread_, int prio_, [[maybe_unused]] bool
381 412
382 struct sched_param sp; 413 struct sched_param sp;
383 // prio range [-3,+3] was checked by the caller 414 // prio range [-3,+3] was checked by the caller
384 sp.sched_priority = gs_prio_remap[prio_ + 3]; 415 sp.sched_priority = native_ ? prio_ : gs_prio_remap[prio_ + 3];
385 PT_CALL(pthread_setschedparam(thread_.native_handle(), _PRIO_MODE, &sp)); 416 PthreadInvoke(L_, std::source_location::current().function_name(), pthread_setschedparam, thread_.native_handle(), _PRIO_MODE, &sp);
386} 417}
387 418
388// ################################################################################################# 419// #################################################################################################
389 420
390#ifdef __PROSPERO__ 421#ifdef __PROSPERO__
391 422
392void THREAD_SET_AFFINITY(unsigned int aff_) 423void THREAD_SET_AFFINITY(lua_State* const L_, unsigned int aff_)
393{ 424{
394 scePthreadSetaffinity(scePthreadSelf(), aff_); 425 PthreadInvoke(L_, std::source_location::current().function_name(), scePthreadSetaffinity, scePthreadSelf(), aff_);
395} 426}
396 427
397#else // __PROSPERO__ 428#else // __PROSPERO__
398 429
399void THREAD_SET_AFFINITY(unsigned int aff_) 430void THREAD_SET_AFFINITY(lua_State* const L_, unsigned int aff_)
400{ 431{
401#if HAVE_WIN32 // "hybrid": Win32 API is available, and pthread too 432#if HAVE_WIN32 // "hybrid": Win32 API is available, and pthread too
402 // since pthread_setaffinity_np can be missing (for example mingw), use win32 api instead 433 // since pthread_setaffinity_np can be missing (for example mingw), use win32 api instead
403 if (!SetThreadAffinityMask(GetCurrentThread(), aff_)) { 434 Win32Invoke(L_, std::source_location::current().function_name(), SetThreadAffinityMask, GetCurrentThread(), aff_);
404 FAIL("THREAD_SET_AFFINITY", GetLastError());
405 }
406#else // pure pthread 435#else // pure pthread
407 int bit = 0; 436 int bit = 0;
408#ifdef __NetBSD__ 437#ifdef __NetBSD__
@@ -422,12 +451,13 @@ void THREAD_SET_AFFINITY(unsigned int aff_)
422 aff_ >>= 1; 451 aff_ >>= 1;
423 } 452 }
424#ifdef __ANDROID__ 453#ifdef __ANDROID__
425 PT_CALL(sched_setaffinity(pthread_self(), sizeof(cpu_set_t), &cpuset)); 454
455 PthreadInvoke(L_, std::source_location::current().function_name(), sched_setaffinity, pthread_self(), sizeof(cpu_set_t), &cpuset);
426#elif defined(__NetBSD__) 456#elif defined(__NetBSD__)
427 PT_CALL(pthread_setaffinity_np(pthread_self(), cpuset_size(cpuset), cpuset)); 457 PthreadInvoke(L_, std::source_location::current().function_name(), pthread_setaffinity_np, pthread_self(), cpuset_size(cpuset), cpuset);
428 cpuset_destroy(cpuset); 458 cpuset_destroy(cpuset);
429#else 459#else
430 PT_CALL(pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset)); 460 PthreadInvoke(L_, std::source_location::current().function_name(), pthread_setaffinity_np, pthread_self(), sizeof(cpu_set_t), &cpuset);
431#endif 461#endif
432#endif // PLATFORM_MINGW 462#endif // PLATFORM_MINGW
433} 463}
@@ -447,7 +477,7 @@ void THREAD_SETNAME(std::string_view const& name_)
447 477
448void THREAD_SETNAME(std::string_view const& name_) 478void THREAD_SETNAME(std::string_view const& name_)
449{ 479{
450 // exact API to set the thread name is platform-dependant 480 // exact API to set the thread name is platform-dependent
451 // if you need to fix the build, or if you know how to fill a hole, tell me (bnt.germain@gmail.com) so that I can submit the fix in github. 481 // if you need to fix the build, or if you know how to fill a hole, tell me (bnt.germain@gmail.com) so that I can submit the fix in github.
452#if defined PLATFORM_MINGW 482#if defined PLATFORM_MINGW
453 pthread_setname_np(pthread_self(), name_.data()); 483 pthread_setname_np(pthread_self(), name_.data());
diff --git a/src/threading.hpp b/src/threading.hpp
index 912c28f..07c1ab3 100644
--- a/src/threading.hpp
+++ b/src/threading.hpp
@@ -1,6 +1,7 @@
1#pragma once 1#pragma once
2 2
3#include "platform.h" 3#include "platform.h"
4#include "unique.hpp"
4 5
5#define THREADAPI_WINDOWS 1 6#define THREADAPI_WINDOWS 1
6#define THREADAPI_PTHREAD 2 7#define THREADAPI_PTHREAD 2
@@ -73,8 +74,15 @@ static constexpr int kThreadPrioMax{ +3 };
73// ################################################################################################# 74// #################################################################################################
74// ################################################################################################# 75// #################################################################################################
75 76
77DECLARE_UNIQUE_TYPE(SudoFlag, bool);
78DECLARE_UNIQUE_TYPE(NativePrioFlag, bool);
79
80std::pair<int, int> THREAD_NATIVE_PRIOS();
81
76void THREAD_SETNAME(std::string_view const& name_); 82void THREAD_SETNAME(std::string_view const& name_);
77void THREAD_SET_PRIORITY(int prio_, bool sudo_);
78void THREAD_SET_AFFINITY(unsigned int aff_);
79 83
80void THREAD_SET_PRIORITY(std::thread& thread_, int prio_, bool sudo_); 84void THREAD_SET_PRIORITY(lua_State* L_, int prio_, NativePrioFlag native_, SudoFlag sudo_);
85
86void THREAD_SET_AFFINITY(lua_State* L_, unsigned int aff_);
87
88void THREAD_SET_PRIORITY(lua_State* L_, std::thread& thread_, int prio_, NativePrioFlag native_, SudoFlag sudo_);
diff --git a/src/tools.cpp b/src/tools.cpp
index cbfefb0..cd1c593 100644
--- a/src/tools.cpp
+++ b/src/tools.cpp
@@ -45,13 +45,29 @@ static constexpr RegistryUniqueKey kLookupCacheRegKey{ 0x9BF75F84E54B691Bull };
45 45
46// ################################################################################################# 46// #################################################################################################
47 47
48static constexpr int kWriterReturnCode{ 666 }; 48namespace {
49[[nodiscard]] 49 namespace local {
50static int dummy_writer([[maybe_unused]] lua_State* const L_, [[maybe_unused]] void const* p_, [[maybe_unused]] size_t sz_, [[maybe_unused]] void* ud_) 50 static int buf_writer([[maybe_unused]] lua_State* const L_, void const* b_, size_t size_, void* ud_)
51{ 51 {
52 // always fail with this code 52 auto* const _B{ static_cast<luaL_Buffer*>(ud_) };
53 return kWriterReturnCode; 53 if (b_ && size_) {
54} 54 luaL_addlstring(_B, static_cast<char const*>(b_), size_);
55 }
56 return 0;
57 }
58
59 static constexpr int kWriterReturnCode{ 666 };
60 [[nodiscard]]
61 static int dummy_writer([[maybe_unused]] lua_State* const L_, [[maybe_unused]] void const* p_, [[maybe_unused]] size_t sz_, [[maybe_unused]] void* ud_)
62 {
63 // always fail with this code
64 return kWriterReturnCode;
65 }
66
67 } // namespace local
68} // namespace
69
70// #################################################################################################
55 71
56/* 72/*
57 * differentiation between C, bytecode and JIT-fast functions 73 * differentiation between C, bytecode and JIT-fast functions
@@ -59,30 +75,28 @@ static int dummy_writer([[maybe_unused]] lua_State* const L_, [[maybe_unused]] v
59 * +-------------------+------------+----------+ 75 * +-------------------+------------+----------+
60 * | bytecode | C function | JIT-fast | 76 * | bytecode | C function | JIT-fast |
61 * +-----------------+-------------------+------------+----------+ 77 * +-----------------+-------------------+------------+----------+
62 * | lua_topointer | | | | 78 * | lua_tocfunction | nullptr | <some p> | nullptr |
63 * +-----------------+-------------------+------------+----------+ 79 * +-----------------+-------------------+------------+----------+
64 * | lua_tocfunction | nullptr | | nullptr | 80 * | luaW_dump | kWriterReturnCode | 1 | 1 |
65 * +-----------------+-------------------+------------+----------+
66 * | luaG_dump | kWriterReturnCode | 1 | 1 |
67 * +-----------------+-------------------+------------+----------+ 81 * +-----------------+-------------------+------------+----------+
68 */ 82 */
69 83
70[[nodiscard]] 84[[nodiscard]]
71FuncSubType luaG_getfuncsubtype(lua_State* const L_, StackIndex const i_) 85FuncSubType luaW_getfuncsubtype(lua_State* const L_, StackIndex const i_)
72{ 86{
73 if (lua_tocfunction(L_, i_)) { // nullptr for LuaJIT-fast && bytecode functions 87 if (lua_tocfunction(L_, i_)) { // nullptr for LuaJIT-fast && bytecode functions
74 return FuncSubType::Native; 88 return FuncSubType::Native;
75 } 89 }
76 90
77 // luaG_dump expects the function at the top of the stack 91 // luaW_dump expects the function at the top of the stack
78 int const _popCount{ (luaG_absindex(L_, i_) == lua_gettop(L_)) ? 0 : (lua_pushvalue(L_, i_), 1) }; 92 int const _popCount{ (luaW_absindex(L_, i_) == lua_gettop(L_)) ? 0 : (lua_pushvalue(L_, i_), 1) };
79 // here we either have a Lua bytecode or a LuaJIT-compiled function 93 // here we either have a Lua bytecode or a LuaJIT-compiled function
80 int const _dumpres{ luaG_dump(L_, dummy_writer, nullptr, 0) }; 94 int const _dumpres{ luaW_dump(L_, local::dummy_writer, nullptr, 0) };
81 if (_popCount > 0) { 95 if (_popCount > 0) {
82 lua_pop(L_, _popCount); 96 lua_pop(L_, _popCount);
83 } 97 }
84 if (_dumpres == kWriterReturnCode) { 98 if (_dumpres == local::kWriterReturnCode) {
85 // anytime we get kWriterReturnCode, this means that luaG_dump() attempted a dump 99 // anytime we get kWriterReturnCode, this means that luaW_dump() attempted a dump
86 return FuncSubType::Bytecode; 100 return FuncSubType::Bytecode;
87 } 101 }
88 // we didn't try to dump, therefore this is a LuaJIT-fast function 102 // we didn't try to dump, therefore this is a LuaJIT-fast function
@@ -92,7 +106,6 @@ FuncSubType luaG_getfuncsubtype(lua_State* const L_, StackIndex const i_)
92// ################################################################################################# 106// #################################################################################################
93 107
94namespace tools { 108namespace tools {
95
96 // inspired from tconcat() in ltablib.c 109 // inspired from tconcat() in ltablib.c
97 [[nodiscard]] 110 [[nodiscard]]
98 std::string_view PushFQN(lua_State* const L_, StackIndex const t_) 111 std::string_view PushFQN(lua_State* const L_, StackIndex const t_)
@@ -115,9 +128,23 @@ namespace tools {
115 // &b is popped at that point (-> replaced by the result) 128 // &b is popped at that point (-> replaced by the result)
116 luaL_pushresult(&_b); // L_: ... {} ... "<result>" 129 luaL_pushresult(&_b); // L_: ... {} ... "<result>"
117 STACK_CHECK(L_, 1); 130 STACK_CHECK(L_, 1);
118 return luaG_tostring(L_, kIdxTop); 131 return luaW_tostring(L_, kIdxTop);
119 } 132 }
120 133
134 // #############################################################################################
135
136 void PushFunctionBytecode(SourceState const L1_, DestState const L2_, int const strip_)
137 {
138 luaL_Buffer B{};
139 STACK_CHECK_START_REL(L1_, 0);
140 STACK_CHECK_START_REL(L2_, 0);
141 STACK_GROW(L2_, 2);
142 luaL_buffinit(L2_, &B); // L1_: ... f L2_: ... <B stuff>
143 luaW_dump(L1_, local::buf_writer, &B, strip_);
144 luaL_pushresult(&B); // L2_: ... "<bytecode>"
145 STACK_CHECK(L2_, 1);
146 STACK_CHECK(L1_, 0);
147 }
121} // namespace tools 148} // namespace tools
122 149
123// ################################################################################################# 150// #################################################################################################
@@ -145,10 +172,10 @@ static void update_lookup_entry(lua_State* const L_, StackIndex const ctxBase_,
145 // first, raise an error if the function is already known 172 // first, raise an error if the function is already known
146 lua_pushvalue(L_, -1); // L_: ... {bfc} k o o 173 lua_pushvalue(L_, -1); // L_: ... {bfc} k o o
147 lua_rawget(L_, _dest); // L_: ... {bfc} k o name? 174 lua_rawget(L_, _dest); // L_: ... {bfc} k o name?
148 std::string_view const _prevName{ luaG_tostring(L_, kIdxTop) }; // nullptr if we got nil (first encounter of this object) 175 std::string_view const _prevName{ luaW_tostring(L_, kIdxTop) }; // nullptr if we got nil (first encounter of this object)
149 // push name in fqn stack (note that concatenation will crash if name is a not string or a number) 176 // push name in fqn stack (note that concatenation will crash if name is a not string or a number)
150 lua_pushvalue(L_, -3); // L_: ... {bfc} k o name? k 177 lua_pushvalue(L_, -3); // L_: ... {bfc} k o name? k
151 LUA_ASSERT(L_, luaG_type(L_, kIdxTop) == LuaType::NUMBER || luaG_type(L_, kIdxTop) == LuaType::STRING); 178 LUA_ASSERT(L_, luaW_type(L_, kIdxTop) == LuaType::NUMBER || luaW_type(L_, kIdxTop) == LuaType::STRING);
152 TableIndex const _deeper{ depth_ + 1 }; 179 TableIndex const _deeper{ depth_ + 1 };
153 lua_rawseti(L_, _fqn, _deeper); // L_: ... {bfc} k o name? 180 lua_rawseti(L_, _fqn, _deeper); // L_: ... {bfc} k o name?
154 // generate name 181 // generate name
@@ -161,7 +188,7 @@ static void update_lookup_entry(lua_State* const L_, StackIndex const ctxBase_,
161 // Therefore, when we encounter an object for which a name was previously registered, we need to select a single name 188 // Therefore, when we encounter an object for which a name was previously registered, we need to select a single name
162 // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded 189 // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded
163 if (!_prevName.empty() && ((_prevName.size() < _newName.size()) || (_prevName <= _newName))) { 190 if (!_prevName.empty() && ((_prevName.size() < _newName.size()) || (_prevName <= _newName))) {
164 DEBUGSPEW_CODE(DebugSpew(_U) << luaG_typename(L_, StackIndex{ -3 }) << " '" << _newName << "' remains named '" << _prevName << "'" << std::endl); 191 DEBUGSPEW_CODE(DebugSpew(_U) << luaW_typename(L_, StackIndex{ -3 }) << " '" << _newName << "' remains named '" << _prevName << "'" << std::endl);
165 // the previous name is 'smaller' than the one we just generated: keep it! 192 // the previous name is 'smaller' than the one we just generated: keep it!
166 lua_pop(L_, 3); // L_: ... {bfc} k 193 lua_pop(L_, 3); // L_: ... {bfc} k
167 } else { 194 } else {
@@ -175,7 +202,7 @@ static void update_lookup_entry(lua_State* const L_, StackIndex const ctxBase_,
175 } else { 202 } else {
176 lua_remove(L_, -2); // L_: ... {bfc} k o "f.q.n" 203 lua_remove(L_, -2); // L_: ... {bfc} k o "f.q.n"
177 } 204 }
178 DEBUGSPEW_CODE(DebugSpew(_U) << luaG_typename(L_, StackIndex{ -2 }) << " '" << _newName << "'" << std::endl); 205 DEBUGSPEW_CODE(DebugSpew(_U) << luaW_typename(L_, StackIndex{ -2 }) << " '" << _newName << "'" << std::endl);
179 // prepare the stack for database feed 206 // prepare the stack for database feed
180 lua_pushvalue(L_, -1); // L_: ... {bfc} k o "f.q.n" "f.q.n" 207 lua_pushvalue(L_, -1); // L_: ... {bfc} k o "f.q.n" "f.q.n"
181 lua_pushvalue(L_, -3); // L_: ... {bfc} k o "f.q.n" "f.q.n" o 208 lua_pushvalue(L_, -3); // L_: ... {bfc} k o "f.q.n" "f.q.n" o
@@ -210,7 +237,7 @@ static void populate_lookup_table_recur(lua_State* const L_, StackIndex const db
210 STACK_CHECK_START_REL(L_, 0); // L_: ... {i_} 237 STACK_CHECK_START_REL(L_, 0); // L_: ... {i_}
211 238
212 // if object is a userdata, replace it by its metatable 239 // if object is a userdata, replace it by its metatable
213 if (luaG_type(L_, i_) == LuaType::USERDATA) { 240 if (luaW_type(L_, i_) == LuaType::USERDATA) {
214 lua_getmetatable(L_, i_); // L_: ... {i_} mt 241 lua_getmetatable(L_, i_); // L_: ... {i_} mt
215 lua_replace(L_, i_); // L_: ... {i_} 242 lua_replace(L_, i_); // L_: ... {i_}
216 } 243 }
@@ -239,7 +266,7 @@ static void populate_lookup_table_recur(lua_State* const L_, StackIndex const db
239 lua_pushnil(L_); // L_: ... {i_} {bfc} nil 266 lua_pushnil(L_); // L_: ... {i_} {bfc} nil
240 while (lua_next(L_, i_) != 0) { // L_: ... {i_} {bfc} k v 267 while (lua_next(L_, i_) != 0) { // L_: ... {i_} {bfc} k v
241 // just for debug, not actually needed 268 // just for debug, not actually needed
242 // std::string_view const _key{ (luaG_type(L_, -2) == LuaType::STRING) ? luaG_tostring(L_, -2) : "not a string" }; 269 // std::string_view const _key{ (luaW_type(L_, -2) == LuaType::STRING) ? luaW_tostring(L_, -2) : "not a string" };
243 // subtable: process it recursively 270 // subtable: process it recursively
244 if (lua_istable(L_, kIdxTop)) { // L_: ... {i_} {bfc} k {} 271 if (lua_istable(L_, kIdxTop)) { // L_: ... {i_} {bfc} k {}
245 // increment visit count to make sure we will actually scan it at this recursive level 272 // increment visit count to make sure we will actually scan it at this recursive level
@@ -256,11 +283,11 @@ static void populate_lookup_table_recur(lua_State* const L_, StackIndex const db
256 lua_rawset(L_, _breadthFirstCache); // L_: ... {i_} {bfc} k {} 283 lua_rawset(L_, _breadthFirstCache); // L_: ... {i_} {bfc} k {}
257 // generate a name, and if we already had one name, keep whichever is the shorter 284 // generate a name, and if we already had one name, keep whichever is the shorter
258 update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k 285 update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k
259 } else if (lua_isfunction(L_, kIdxTop) && (luaG_getfuncsubtype(L_, kIdxTop) != FuncSubType::Bytecode)) { 286 } else if (lua_isfunction(L_, kIdxTop) && (luaW_getfuncsubtype(L_, kIdxTop) != FuncSubType::Bytecode)) {
260 // generate a name, and if we already had one name, keep whichever is the shorter 287 // generate a name, and if we already had one name, keep whichever is the shorter
261 // this pops the function from the stack 288 // this pops the function from the stack
262 update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k 289 update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k
263 } else if (luaG_type(L_, kIdxTop) == LuaType::USERDATA) { 290 } else if (luaW_type(L_, kIdxTop) == LuaType::USERDATA) {
264 // generate a name, and if we already had one name, keep whichever is the shorter 291 // generate a name, and if we already had one name, keep whichever is the shorter
265 // this pops the userdata from the stack 292 // this pops the userdata from the stack
266 update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k 293 update_lookup_entry(L_, dbIdx_, depth_); // L_: ... {i_} {bfc} k
@@ -273,13 +300,13 @@ static void populate_lookup_table_recur(lua_State* const L_, StackIndex const db
273 TableIndex const _deeper{ depth_ + 1 }; 300 TableIndex const _deeper{ depth_ + 1 };
274 lua_pushnil(L_); // L_: ... {i_} {bfc} nil 301 lua_pushnil(L_); // L_: ... {i_} {bfc} nil
275 while (lua_next(L_, _breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {} 302 while (lua_next(L_, _breadthFirstCache) != 0) { // L_: ... {i_} {bfc} k {}
276 DEBUGSPEW_CODE(std::string_view const _key{ (luaG_type(L_, StackIndex{ -2 }) == LuaType::STRING) ? luaG_tostring(L_, StackIndex{ -2 }) : std::string_view{ "<not a string>" } }); 303 DEBUGSPEW_CODE(std::string_view const _key{ (luaW_type(L_, StackIndex{ -2 }) == LuaType::STRING) ? luaW_tostring(L_, StackIndex{ -2 }) : std::string_view{ "<not a string>" } });
277 DEBUGSPEW_CODE(DebugSpew(_U) << "table '"<< _key <<"'" << std::endl); 304 DEBUGSPEW_CODE(DebugSpew(_U) << "table '"<< _key <<"'" << std::endl);
278 DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U }); 305 DEBUGSPEW_CODE(DebugSpewIndentScope _scope2{ _U });
279 // un-visit this table in case we do need to process it 306 // un-visit this table in case we do need to process it
280 lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} 307 lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {}
281 lua_rawget(L_, _cache); // L_: ... {i_} {bfc} k {} n 308 lua_rawget(L_, _cache); // L_: ... {i_} {bfc} k {} n
282 LUA_ASSERT(L_, luaG_type(L_, kIdxTop) == LuaType::NUMBER); 309 LUA_ASSERT(L_, luaW_type(L_, kIdxTop) == LuaType::NUMBER);
283 _visit_count = lua_tointeger(L_, -1) - 1; 310 _visit_count = lua_tointeger(L_, -1) - 1;
284 lua_pop(L_, 1); // L_: ... {i_} {bfc} k {} 311 lua_pop(L_, 1); // L_: ... {i_} {bfc} k {}
285 lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {} 312 lua_pushvalue(L_, -1); // L_: ... {i_} {bfc} k {} {}
@@ -312,7 +339,7 @@ namespace tools {
312 // create a "fully.qualified.name" <-> function equivalence database 339 // create a "fully.qualified.name" <-> function equivalence database
313 void PopulateFuncLookupTable(lua_State* const L_, StackIndex const i_, std::string_view const& name_) 340 void PopulateFuncLookupTable(lua_State* const L_, StackIndex const i_, std::string_view const& name_)
314 { 341 {
315 StackIndex const _in_base{ luaG_absindex(L_, i_) }; 342 StackIndex const _in_base{ luaW_absindex(L_, i_) };
316 DEBUGSPEW_CODE(Universe* _U = Universe::Get(L_)); 343 DEBUGSPEW_CODE(Universe* _U = Universe::Get(L_));
317 std::string_view _name{ name_.empty() ? std::string_view{} : name_ }; 344 std::string_view _name{ name_.empty() ? std::string_view{} : name_ };
318 DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": PopulateFuncLookupTable('" << _name << "')" << std::endl); 345 DEBUGSPEW_CODE(DebugSpew(_U) << L_ << ": PopulateFuncLookupTable('" << _name << "')" << std::endl);
@@ -323,24 +350,24 @@ namespace tools {
323 StackIndex const _dbIdx{ lua_gettop(L_) }; 350 StackIndex const _dbIdx{ lua_gettop(L_) };
324 STACK_CHECK(L_, 1); 351 STACK_CHECK(L_, 1);
325 LUA_ASSERT(L_, lua_istable(L_, -1)); 352 LUA_ASSERT(L_, lua_istable(L_, -1));
326 LuaType const _moduleType{ luaG_type(L_, _in_base) }; 353 LuaType const _moduleType{ luaW_type(L_, _in_base) };
327 if ((_moduleType == LuaType::FUNCTION) || (_moduleType == LuaType::USERDATA)) { // for example when a module is a simple function 354 if ((_moduleType == LuaType::FUNCTION) || (_moduleType == LuaType::USERDATA)) { // for example when a module is a simple function
328 if (_name.empty()) { 355 if (_name.empty()) {
329 _name = "nullptr"; 356 _name = "nullptr";
330 } 357 }
331 lua_pushvalue(L_, _in_base); // L_: {} f 358 lua_pushvalue(L_, _in_base); // L_: {} f
332 luaG_pushstring(L_, _name); // L_: {} f name_ 359 luaW_pushstring(L_, _name); // L_: {} f name_
333 lua_rawset(L_, -3); // L_: {} 360 lua_rawset(L_, -3); // L_: {}
334 luaG_pushstring(L_, _name); // L_: {} name_ 361 luaW_pushstring(L_, _name); // L_: {} name_
335 lua_pushvalue(L_, _in_base); // L_: {} name_ f 362 lua_pushvalue(L_, _in_base); // L_: {} name_ f
336 lua_rawset(L_, -3); // L_: {} 363 lua_rawset(L_, -3); // L_: {}
337 lua_pop(L_, 1); // L_: 364 lua_pop(L_, 1); // L_:
338 } else if (luaG_type(L_, _in_base) == LuaType::TABLE) { 365 } else if (luaW_type(L_, _in_base) == LuaType::TABLE) {
339 lua_newtable(L_); // L_: {} {fqn} 366 lua_newtable(L_); // L_: {} {fqn}
340 TableIndex _startDepth{ 0 }; 367 TableIndex _startDepth{ 0 };
341 if (!_name.empty()) { 368 if (!_name.empty()) {
342 STACK_CHECK(L_, 2); 369 STACK_CHECK(L_, 2);
343 luaG_pushstring(L_, _name); // L_: {} {fqn} "name" 370 luaW_pushstring(L_, _name); // L_: {} {fqn} "name"
344 // generate a name, and if we already had one name, keep whichever is the shorter 371 // generate a name, and if we already had one name, keep whichever is the shorter
345 lua_pushvalue(L_, _in_base); // L_: {} {fqn} "name" t 372 lua_pushvalue(L_, _in_base); // L_: {} {fqn} "name" t
346 update_lookup_entry(L_, _dbIdx, _startDepth); // L_: {} {fqn} "name" 373 update_lookup_entry(L_, _dbIdx, _startDepth); // L_: {} {fqn} "name"
@@ -355,7 +382,7 @@ namespace tools {
355 lua_pop(L_, 3); // L_: 382 lua_pop(L_, 3); // L_:
356 } else { 383 } else {
357 lua_pop(L_, 1); // L_: 384 lua_pop(L_, 1); // L_:
358 raise_luaL_error(L_, "unsupported module type %s", luaG_typename(L_, _in_base).data()); 385 raise_luaL_error(L_, "unsupported module type %s", luaW_typename(L_, _in_base).data());
359 } 386 }
360 STACK_CHECK(L_, 0); 387 STACK_CHECK(L_, 0);
361 } 388 }
@@ -373,7 +400,7 @@ namespace tools {
373 +[](lua_State* L_) 400 +[](lua_State* L_)
374 { 401 {
375 int const _args{ lua_gettop(L_) }; // L_: args... 402 int const _args{ lua_gettop(L_) }; // L_: args...
376 //[[maybe_unused]] std::string_view const _modname{ luaG_checkstring(L_, 1) }; 403 //[[maybe_unused]] std::string_view const _modname{ luaW_checkstring(L_, 1) };
377 404
378 STACK_GROW(L_, 1); 405 STACK_GROW(L_, 1);
379 406
diff --git a/src/tools.hpp b/src/tools.hpp
index 420b5f8..c555344 100644
--- a/src/tools.hpp
+++ b/src/tools.hpp
@@ -21,7 +21,7 @@ enum class [[nodiscard]] FuncSubType
21}; 21};
22 22
23[[nodiscard]] 23[[nodiscard]]
24FuncSubType luaG_getfuncsubtype(lua_State* L_, StackIndex i_); 24FuncSubType luaW_getfuncsubtype(lua_State* L_, StackIndex i_);
25 25
26// ################################################################################################# 26// #################################################################################################
27 27
@@ -37,5 +37,6 @@ namespace tools {
37 void PopulateFuncLookupTable(lua_State* L_, StackIndex i_, std::string_view const& name_); 37 void PopulateFuncLookupTable(lua_State* L_, StackIndex i_, std::string_view const& name_);
38 [[nodiscard]] 38 [[nodiscard]]
39 std::string_view PushFQN(lua_State* L_, StackIndex t_); 39 std::string_view PushFQN(lua_State* L_, StackIndex t_);
40 void PushFunctionBytecode(SourceState L1_, DestState L2_, int strip_);
40 void SerializeRequire(lua_State* L_); 41 void SerializeRequire(lua_State* L_);
41} // namespace tools 42} // namespace tools
diff --git a/src/tracker.cpp b/src/tracker.cpp
index 8b06522..34866dd 100644
--- a/src/tracker.cpp
+++ b/src/tracker.cpp
@@ -96,7 +96,7 @@ int LaneTracker::pushThreadsTable(lua_State* L_) const
96 while (_lane != TRACKING_END) { 96 while (_lane != TRACKING_END) {
97 // insert a { name='<name>', status='<status>' } tuple, so that several lanes with the same name can't clobber each other 97 // insert a { name='<name>', status='<status>' } tuple, so that several lanes with the same name can't clobber each other
98 lua_createtable(L_, 0, 2); // L_: {} {} 98 lua_createtable(L_, 0, 2); // L_: {} {}
99 luaG_pushstring(L_, _lane->getDebugName()); // L_: {} {} "name" 99 luaW_pushstring(L_, _lane->getDebugName()); // L_: {} {} "name"
100 lua_setfield(L_, -2, "name"); // L_: {} {} 100 lua_setfield(L_, -2, "name"); // L_: {} {}
101 _lane->pushStatusString(L_); // L_: {} {} "<status>" 101 _lane->pushStatusString(L_); // L_: {} {} "<status>"
102 lua_setfield(L_, -2, "status"); // L_: {} {} 102 lua_setfield(L_, -2, "status"); // L_: {} {}
diff --git a/src/uniquekey.hpp b/src/uniquekey.hpp
index 4c9eb58..ace21c4 100644
--- a/src/uniquekey.hpp
+++ b/src/uniquekey.hpp
@@ -80,7 +80,7 @@ class RegistryUniqueKey final
80 STACK_GROW(L_, 1); 80 STACK_GROW(L_, 1);
81 STACK_CHECK_START_REL(L_, 0); 81 STACK_CHECK_START_REL(L_, 0);
82 pushValue(L_); // L_: ... {}|nil 82 pushValue(L_); // L_: ... {}|nil
83 T* const value{ luaG_tolightuserdata<T>(L_, kIdxTop) }; 83 T* const value{ luaW_tolightuserdata<T>(L_, kIdxTop) };
84 lua_pop(L_, 1); // L_: ... 84 lua_pop(L_, 1); // L_: ...
85 STACK_CHECK(L_, 0); 85 STACK_CHECK(L_, 0);
86 return value; 86 return value;
@@ -125,8 +125,8 @@ class RegistryUniqueKey final
125 if (!mode_.empty()) { 125 if (!mode_.empty()) {
126 STACK_GROW(L_, 3); 126 STACK_GROW(L_, 3);
127 lua_createtable(L_, 0, 1); // L_: {} mt 127 lua_createtable(L_, 0, 1); // L_: {} mt
128 luaG_pushstring(L_, "__mode"); // L_: {} mt "__mode" 128 luaW_pushstring(L_, "__mode"); // L_: {} mt "__mode"
129 luaG_pushstring(L_, mode_); // L_: {} mt "__mode" mode 129 luaW_pushstring(L_, mode_); // L_: {} mt "__mode" mode
130 lua_rawset(L_, -3); // L_: {} mt 130 lua_rawset(L_, -3); // L_: {} mt
131 lua_setmetatable(L_, -2); // L_: {} 131 lua_setmetatable(L_, -2); // L_: {}
132 } 132 }
diff --git a/src/universe.cpp b/src/universe.cpp
index 335f056..4db036b 100644
--- a/src/universe.cpp
+++ b/src/universe.cpp
@@ -51,6 +51,16 @@ static constexpr RegistryUniqueKey kUniverseFullRegKey{ 0x1C2D76870DD9DD9Full };
51 51
52// ################################################################################################# 52// #################################################################################################
53 53
54[[nodiscard]]
55void* ProtectedAllocator::Protected_lua_Alloc(void* const ud_, void* const ptr_, size_t const osize_, size_t const nsize_)
56{
57 ProtectedAllocator* const _allocator{ static_cast<ProtectedAllocator*>(ud_) };
58 std::lock_guard<std::mutex> _guard{ _allocator->mutex };
59 return _allocator->alloc(ptr_, osize_, nsize_);
60}
61
62// #################################################################################################
63
54Universe::Universe() 64Universe::Universe()
55{ 65{
56 //--- 66 //---
@@ -101,18 +111,18 @@ void Universe::callOnStateCreate(lua_State* const L_, lua_State* const from_, Lo
101 } 111 }
102 kConfigRegKey.pushValue(L_); // L_: config 112 kConfigRegKey.pushValue(L_); // L_: config
103 STACK_CHECK(L_, 1); 113 STACK_CHECK(L_, 1);
104 LuaType const _funcType{ luaG_getfield(L_, kIdxTop, kOnStateCreate) }; // L_: config on_state_create() 114 LuaType const _funcType{ luaW_getfield(L_, kIdxTop, kOnStateCreate) }; // L_: config on_state_create()
105 if (_funcType != LuaType::FUNCTION) { 115 if (_funcType != LuaType::FUNCTION) {
106 raise_luaL_error(L_, "INTERNAL ERROR: %s is a %s, not a function", kOnStateCreate.data(), luaG_typename(L_, _funcType).data()); 116 raise_luaL_error(L_, "INTERNAL ERROR: %s is a %s, not a function", kOnStateCreate.data(), luaW_typename(L_, _funcType).data());
107 } 117 }
108 lua_remove(L_, -2); // L_: on_state_create() 118 lua_remove(L_, -2); // L_: on_state_create()
109 } 119 }
110 STACK_CHECK(L_, 1); 120 STACK_CHECK(L_, 1);
111 // capture error and raise it in caller state 121 // capture error and raise it in caller state
112 std::string_view const _stateType{ mode_ == LookupMode::LaneBody ? "lane" : "keeper" }; 122 std::string_view const _stateType{ mode_ == LookupMode::LaneBody ? "lane" : "keeper" };
113 luaG_pushstring(L_, _stateType); // L_: on_state_create() "<type>" 123 luaW_pushstring(L_, _stateType); // L_: on_state_create() "<type>"
114 if (lua_pcall(L_, 1, 0, 0) != LUA_OK) { 124 if (lua_pcall(L_, 1, 0, 0) != LUA_OK) {
115 raise_luaL_error(from_, "%s failed in %s: \"%s\"", kOnStateCreate.data(), _stateType.data(), lua_isstring(L_, -1) ? luaG_tostring(L_, kIdxTop).data() : luaG_typename(L_, kIdxTop).data()); 125 raise_luaL_error(from_, "%s failed in %s: \"%s\"", kOnStateCreate.data(), _stateType.data(), lua_isstring(L_, -1) ? luaW_tostring(L_, kIdxTop).data() : luaW_typename(L_, kIdxTop).data());
116 } 126 }
117 STACK_CHECK(L_, 0); 127 STACK_CHECK(L_, 0);
118} 128}
@@ -127,14 +137,14 @@ Universe* Universe::Create(lua_State* const L_)
127 static constexpr StackIndex kIdxSettings{ 1 }; 137 static constexpr StackIndex kIdxSettings{ 1 };
128 LUA_ASSERT(L_, lua_gettop(L_) == 1 && lua_istable(L_, 1)); 138 LUA_ASSERT(L_, lua_gettop(L_) == 1 && lua_istable(L_, 1));
129 STACK_CHECK_START_REL(L_, 0); // L_: settings 139 STACK_CHECK_START_REL(L_, 0); // L_: settings
130 std::ignore = luaG_getfield(L_, kIdxSettings, "nb_user_keepers"); // L_: settings nb_user_keepers 140 std::ignore = luaW_getfield(L_, kIdxSettings, "nb_user_keepers"); // L_: settings nb_user_keepers
131 int const _nbUserKeepers{ static_cast<int>(lua_tointeger(L_, -1)) + 1}; 141 int const _nbUserKeepers{ static_cast<int>(lua_tointeger(L_, -1)) + 1};
132 lua_pop(L_, 1); // L_: settings 142 lua_pop(L_, 1); // L_: settings
133 if (_nbUserKeepers < 1) { 143 if (_nbUserKeepers < 1) {
134 raise_luaL_error(L_, "Bad number of additional keepers (%d)", _nbUserKeepers); 144 raise_luaL_error(L_, "Bad number of additional keepers (%d)", _nbUserKeepers);
135 } 145 }
136 STACK_CHECK(L_, 0); 146 STACK_CHECK(L_, 0);
137 std::ignore = luaG_getfield(L_, kIdxSettings, "keepers_gc_threshold"); // L_: settings keepers_gc_threshold 147 std::ignore = luaW_getfield(L_, kIdxSettings, "keepers_gc_threshold"); // L_: settings keepers_gc_threshold
138 int const _keepers_gc_threshold{ static_cast<int>(lua_tointeger(L_, -1)) }; 148 int const _keepers_gc_threshold{ static_cast<int>(lua_tointeger(L_, -1)) };
139 lua_pop(L_, 1); // L_: settings 149 lua_pop(L_, 1); // L_: settings
140 STACK_CHECK(L_, 0); 150 STACK_CHECK(L_, 0);
@@ -147,30 +157,30 @@ Universe* Universe::Create(lua_State* const L_)
147 157
148 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U }); 158 DEBUGSPEW_CODE(DebugSpewIndentScope _scope{ _U });
149 lua_createtable(L_, 0, 1); // L_: settings universe {mt} 159 lua_createtable(L_, 0, 1); // L_: settings universe {mt}
150 std::ignore = luaG_getfield(L_, kIdxSettings, "shutdown_timeout"); // L_: settings universe {mt} shutdown_timeout 160 std::ignore = luaW_getfield(L_, kIdxSettings, "shutdown_timeout"); // L_: settings universe {mt} shutdown_timeout
151 lua_pushcclosure(L_, UniverseGC, 1); // L_: settings universe {mt} UniverseGC 161 lua_pushcclosure(L_, UniverseGC, 1); // L_: settings universe {mt} UniverseGC
152 lua_setfield(L_, -2, "__gc"); // L_: settings universe {mt} 162 lua_setfield(L_, -2, "__gc"); // L_: settings universe {mt}
153 lua_setmetatable(L_, -2); // L_: settings universe 163 lua_setmetatable(L_, -2); // L_: settings universe
154 lua_pop(L_, 1); // L_: settings 164 lua_pop(L_, 1); // L_: settings
155 165
156 std::ignore = luaG_getfield(L_, kIdxSettings, "linda_wake_period"); // L_: settings linda_wake_period 166 std::ignore = luaW_getfield(L_, kIdxSettings, "linda_wake_period"); // L_: settings linda_wake_period
157 if (luaG_type(L_, kIdxTop) == LuaType::NUMBER) { 167 if (luaW_type(L_, kIdxTop) == LuaType::NUMBER) {
158 _U->lindaWakePeriod = lua_Duration{ lua_tonumber(L_, kIdxTop) }; 168 _U->lindaWakePeriod = lua_Duration{ lua_tonumber(L_, kIdxTop) };
159 } else { 169 } else {
160 LUA_ASSERT(L_, luaG_tostring(L_, kIdxTop) == "never"); 170 LUA_ASSERT(L_, luaW_tostring(L_, kIdxTop) == "never");
161 } 171 }
162 lua_pop(L_, 1); // L_: settings 172 lua_pop(L_, 1); // L_: settings
163 173
164 std::ignore = luaG_getfield(L_, kIdxSettings, "strip_functions"); // L_: settings strip_functions 174 std::ignore = luaW_getfield(L_, kIdxSettings, "strip_functions"); // L_: settings strip_functions
165 _U->stripFunctions = lua_toboolean(L_, -1) ? true : false; 175 _U->stripFunctions = lua_toboolean(L_, -1) ? true : false;
166 lua_pop(L_, 1); // L_: settings 176 lua_pop(L_, 1); // L_: settings
167 177
168 std::ignore = luaG_getfield(L_, kIdxSettings, "verbose_errors"); // L_: settings verbose_errors 178 std::ignore = luaW_getfield(L_, kIdxSettings, "verbose_errors"); // L_: settings verbose_errors
169 _U->verboseErrors = lua_toboolean(L_, -1) ? true : false; 179 _U->verboseErrors = lua_toboolean(L_, -1) ? true : false;
170 lua_pop(L_, 1); // L_: settings 180 lua_pop(L_, 1); // L_: settings
171 181
172 // tracking 182 // tracking
173 std::ignore = luaG_getfield(L_, kIdxSettings, "track_lanes"); // L_: settings track_lanes 183 std::ignore = luaW_getfield(L_, kIdxSettings, "track_lanes"); // L_: settings track_lanes
174 if (lua_toboolean(L_, -1)) { 184 if (lua_toboolean(L_, -1)) {
175 _U->tracker.activate(); 185 _U->tracker.activate();
176 } 186 }
@@ -178,8 +188,8 @@ Universe* Universe::Create(lua_State* const L_)
178 188
179 // Linked chains handling 189 // Linked chains handling
180 _U->selfdestructFirst = SELFDESTRUCT_END; 190 _U->selfdestructFirst = SELFDESTRUCT_END;
181 _U->initializeAllocatorFunction(L_); 191 _U->initializeAllocatorFunction(L_); // this can raise an error
182 _U->initializeOnStateCreate(L_); 192 _U->initializeOnStateCreate(L_); // this can raise an error
183 _U->keepers.initialize(*_U, L_, static_cast<size_t>(_nbUserKeepers), _keepers_gc_threshold); 193 _U->keepers.initialize(*_U, L_, static_cast<size_t>(_nbUserKeepers), _keepers_gc_threshold);
184 STACK_CHECK(L_, 0); 194 STACK_CHECK(L_, 0);
185 195
@@ -207,7 +217,7 @@ static void* libc_lua_Alloc([[maybe_unused]] void* const ud_, [[maybe_unused]] v
207// ################################################################################################# 217// #################################################################################################
208 218
209[[nodiscard]] 219[[nodiscard]]
210static int luaG_provide_protected_allocator(lua_State* const L_) 220static int luaW_provide_protected_allocator(lua_State* const L_)
211{ 221{
212 Universe* const _U{ Universe::Get(L_) }; 222 Universe* const _U{ Universe::Get(L_) };
213 // push a new full userdata on the stack, giving access to the universe's protected allocator 223 // push a new full userdata on the stack, giving access to the universe's protected allocator
@@ -217,9 +227,9 @@ static int luaG_provide_protected_allocator(lua_State* const L_)
217 227
218// ################################################################################################# 228// #################################################################################################
219 229
230// already called under protection of selfdestructMutex
220void Universe::flagDanglingLanes() const 231void Universe::flagDanglingLanes() const
221{ 232{
222 std::lock_guard<std::mutex> _guard{ selfdestructMutex };
223 Lane* _lane{ selfdestructFirst }; 233 Lane* _lane{ selfdestructFirst };
224 while (_lane != SELFDESTRUCT_END) { 234 while (_lane != SELFDESTRUCT_END) {
225 _lane->flaggedAfterUniverseGC.store(true, std::memory_order_relaxed); 235 _lane->flaggedAfterUniverseGC.store(true, std::memory_order_relaxed);
@@ -235,17 +245,17 @@ void Universe::initializeAllocatorFunction(lua_State* const L_)
235 // start by just grabbing whatever allocator was provided to the master state 245 // start by just grabbing whatever allocator was provided to the master state
236 protectedAllocator.initFrom(L_); 246 protectedAllocator.initFrom(L_);
237 STACK_CHECK_START_REL(L_, 1); // L_: settings 247 STACK_CHECK_START_REL(L_, 1); // L_: settings
238 switch (luaG_getfield(L_, kIdxTop, "allocator")) { // L_: settings allocator|nil|"protected" 248 switch (luaW_getfield(L_, kIdxTop, "allocator")) { // L_: settings allocator|nil|"protected"
239 case LuaType::NIL: 249 case LuaType::NIL:
240 // nothing else to do 250 // nothing else to do
241 break; 251 break;
242 252
243 case LuaType::STRING: 253 case LuaType::STRING:
244 LUA_ASSERT(L_, luaG_tostring(L_, kIdxTop) == "protected"); 254 LUA_ASSERT(L_, luaW_tostring(L_, kIdxTop) == "protected");
245 // set the original allocator to call from inside protection by the mutex 255 // set the original allocator to call from inside protection by the mutex
246 protectedAllocator.installIn(L_); 256 protectedAllocator.installIn(L_);
247 // before a state is created, this function will be called to obtain the allocator 257 // before a state is created, this function will be called to obtain the allocator
248 provideAllocator = luaG_provide_protected_allocator; 258 provideAllocator = luaW_provide_protected_allocator;
249 break; 259 break;
250 260
251 case LuaType::FUNCTION: 261 case LuaType::FUNCTION:
@@ -266,14 +276,14 @@ void Universe::initializeAllocatorFunction(lua_State* const L_)
266 break; 276 break;
267 277
268 default: // should be filtered out in lanes.lua 278 default: // should be filtered out in lanes.lua
269 raise_luaL_error(L_, "Bad config.allocator type %s", luaG_typename(L_, kIdxTop).data()); 279 raise_luaL_error(L_, "Bad config.allocator type %s", luaW_typename(L_, kIdxTop).data());
270 } 280 }
271 lua_pop(L_, 1); // L_: settings 281 lua_pop(L_, 1); // L_: settings
272 STACK_CHECK(L_, 1); 282 STACK_CHECK(L_, 1);
273 283
274 std::ignore = luaG_getfield(L_, kIdxTop, "internal_allocator"); // L_: settings "libc"|"allocator" 284 std::ignore = luaW_getfield(L_, kIdxTop, "internal_allocator"); // L_: settings "libc"|"allocator"
275 LUA_ASSERT(L_, lua_isstring(L_, kIdxTop)); // should be the case due to lanes.lua parameter validation 285 LUA_ASSERT(L_, lua_isstring(L_, kIdxTop)); // should be the case due to lanes.lua parameter validation
276 std::string_view const _allocator{ luaG_tostring(L_, kIdxTop) }; 286 std::string_view const _allocator{ luaW_tostring(L_, kIdxTop) };
277 // use whatever the provider provides. This performs validation of what provideAllocator is giving 287 // use whatever the provider provides. This performs validation of what provideAllocator is giving
278 // we do this even if _allocator == "libc", to have the validation part 288 // we do this even if _allocator == "libc", to have the validation part
279 internalAllocator = resolveAndValidateAllocator(L_, "internal"); 289 internalAllocator = resolveAndValidateAllocator(L_, "internal");
@@ -295,7 +305,7 @@ int Universe::InitializeFinalizer(lua_State* const L_)
295 305
296 // make sure we are only called from the Master Lua State! 306 // make sure we are only called from the Master Lua State!
297 kUniverseFullRegKey.pushValue(L_); // L_: f U 307 kUniverseFullRegKey.pushValue(L_); // L_: f U
298 if (luaG_type(L_, kIdxTop) != LuaType::USERDATA) { 308 if (luaW_type(L_, kIdxTop) != LuaType::USERDATA) {
299 raise_luaL_error(L_, "lanes.%s called from inside a lane", kFinally); 309 raise_luaL_error(L_, "lanes.%s called from inside a lane", kFinally);
300 } 310 }
301 lua_pop(L_, 1); // L_: f 311 lua_pop(L_, 1); // L_: f
@@ -311,8 +321,8 @@ int Universe::InitializeFinalizer(lua_State* const L_)
311void Universe::initializeOnStateCreate(lua_State* const L_) 321void Universe::initializeOnStateCreate(lua_State* const L_)
312{ 322{
313 STACK_CHECK_START_REL(L_, 0); // L_: settings 323 STACK_CHECK_START_REL(L_, 0); // L_: settings
314 if (luaG_getfield(L_, kIdxTop, kOnStateCreate) != LuaType::NIL) { // L_: settings on_state_create|nil 324 if (luaW_getfield(L_, kIdxTop, kOnStateCreate) != LuaType::NIL) { // L_: settings on_state_create|nil
315 LUA_ASSERT(L_, luaG_type(L_, kIdxTop) == LuaType::FUNCTION); // ensured by lanes.lua parameter validation 325 LUA_ASSERT(L_, luaW_type(L_, kIdxTop) == LuaType::FUNCTION); // ensured by lanes.lua parameter validation
316 // store C function pointer in an internal variable 326 // store C function pointer in an internal variable
317 lua_CFunction const _func{ lua_tocfunction(L_, -1) }; // L_: settings on_state_create 327 lua_CFunction const _func{ lua_tocfunction(L_, -1) }; // L_: settings on_state_create
318 if (_func) { 328 if (_func) {
@@ -325,7 +335,7 @@ void Universe::initializeOnStateCreate(lua_State* const L_)
325 // remove this C function from the config table so that it doesn't cause problems 335 // remove this C function from the config table so that it doesn't cause problems
326 // when we transfer the config table in newly created Lua states 336 // when we transfer the config table in newly created Lua states
327 lua_pushnil(L_); // L_: settings on_state_create nil 337 lua_pushnil(L_); // L_: settings on_state_create nil
328 luaG_setfield(L_, StackIndex{ -3 }, kOnStateCreate); // L_: settings on_state_create 338 luaW_setfield(L_, StackIndex{ -3 }, kOnStateCreate); // L_: settings on_state_create
329 } else { 339 } else {
330 // the function is still in the config table. we indicate this with the uintptr_t alternative (actual value is irrelevant) 340 // the function is still in the config table. we indicate this with the uintptr_t alternative (actual value is irrelevant)
331 onStateCreateFunc.emplace<uintptr_t>(std::bit_cast<uintptr_t>(kOnStateCreate.data())); 341 onStateCreateFunc.emplace<uintptr_t>(std::bit_cast<uintptr_t>(kOnStateCreate.data()));
@@ -348,7 +358,7 @@ lanes::AllocatorDefinition Universe::resolveAndValidateAllocator(lua_State* cons
348 358
349 STACK_CHECK_START_REL(L_, 0); // here, we have a function we can call to obtain an allocator 359 STACK_CHECK_START_REL(L_, 0); // here, we have a function we can call to obtain an allocator
350 lua_pushcclosure(L_, provideAllocator, 0); // L_: provideAllocator() 360 lua_pushcclosure(L_, provideAllocator, 0); // L_: provideAllocator()
351 luaG_pushstring(L_, hint_); // L_: provideAllocator() "<hint>" 361 luaW_pushstring(L_, hint_); // L_: provideAllocator() "<hint>"
352 lua_call(L_, 1, 1); // L_: result 362 lua_call(L_, 1, 1); // L_: result
353 // make sure we have a valid AllocatorDefinition on the stack (an error is raised instead if it is not the case) 363 // make sure we have a valid AllocatorDefinition on the stack (an error is raised instead if it is not the case)
354 _ret = lanes::AllocatorDefinition::Validated(L_, kIdxTop); 364 _ret = lanes::AllocatorDefinition::Validated(L_, kIdxTop);
@@ -423,7 +433,7 @@ int Universe::UniverseGC(lua_State* const L_)
423{ 433{
424 lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; 434 lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) };
425 STACK_CHECK_START_ABS(L_, 1); 435 STACK_CHECK_START_ABS(L_, 1);
426 Universe* const _U{ luaG_tofulluserdata<Universe>(L_, StackIndex{ 1 }) }; // L_: U 436 Universe* const _U{ luaW_tofulluserdata<Universe>(L_, StackIndex{ 1 }) }; // L_: U
427 437
428 // attempt to terminate all lanes with increasingly stronger cancel methods 438 // attempt to terminate all lanes with increasingly stronger cancel methods
429 bool const _allLanesTerminated{ 439 bool const _allLanesTerminated{
@@ -437,7 +447,7 @@ int Universe::UniverseGC(lua_State* const L_)
437 if (!lua_isnil(L_, -1)) { 447 if (!lua_isnil(L_, -1)) {
438 lua_pushboolean(L_, _allLanesTerminated); // L_: U finalizer bool 448 lua_pushboolean(L_, _allLanesTerminated); // L_: U finalizer bool
439 // no protection. Lua rules for errors in finalizers apply normally: 449 // no protection. Lua rules for errors in finalizers apply normally:
440 // Lua 5.4: error is propagated in the warn system 450 // Lua 5.4+: error is propagated in the warn system
441 // older: error is swallowed 451 // older: error is swallowed
442 lua_call(L_, 1, 1); // L_: U msg? 452 lua_call(L_, 1, 1); // L_: U msg?
443 // phew, no error in finalizer, since we reached that point 453 // phew, no error in finalizer, since we reached that point
@@ -446,24 +456,31 @@ int Universe::UniverseGC(lua_State* const L_)
446 if (lua_isnil(L_, kIdxTop)) { 456 if (lua_isnil(L_, kIdxTop)) {
447 lua_pop(L_, 1); // L_: U 457 lua_pop(L_, 1); // L_: U
448 // no finalizer, or it returned no value: push some default message on the stack, in case it is necessary 458 // no finalizer, or it returned no value: push some default message on the stack, in case it is necessary
449 luaG_pushstring(L_, "uncooperative lanes detected at shutdown"); // L_: U "msg" 459 luaW_pushstring(L_, "uncooperative lanes detected at shutdown"); // L_: U "msg"
450 } 460 }
451 STACK_CHECK(L_, 2); 461 STACK_CHECK(L_, 2);
452 462
453 // now, all remaining lanes are flagged. if they crash because we remove keepers and the Universe from under them, it is their fault 463 {
454 bool const _detectedUncooperativeLanes{ _U->selfdestructFirst != SELFDESTRUCT_END }; 464 std::lock_guard<std::mutex> _guard{ _U->selfdestructMutex };
455 if (_detectedUncooperativeLanes) { 465 // now, all remaining lanes are flagged. if they crash because we remove keepers and the Universe from under them, it is their fault
456 _U->flagDanglingLanes(); 466 bool const _detectedUncooperativeLanes{ _U->selfdestructFirst != SELFDESTRUCT_END };
457 if (luaG_tostring(L_, kIdxTop) == "freeze") { 467 if (_detectedUncooperativeLanes) {
458 std::this_thread::sleep_until(std::chrono::time_point<std::chrono::steady_clock>::max()); 468 _U->flagDanglingLanes();
469 if (luaW_tostring(L_, kIdxTop) == "freeze") {
470 std::this_thread::sleep_until(std::chrono::time_point<std::chrono::steady_clock>::max());
471 } else {
472 // take the value returned by the finalizer (or our default message) and throw it as an error
473 // since we are inside Lua's GCTM, it will be propagated through the warning system (Lua 5.4) or swallowed silently
474 // IMPORTANT: lua_error() is used here instead of the wrapper raise_lua_error() to circumvent what looks like a MSVC compiler bug
475 // that manifests as a crash inside ntdll!longjmp() function, in optimized builds only
476 lua_error(L_);
477 }
459 } else { 478 } else {
460 // take the value returned by the finalizer (or our default message) and throw it as an error 479 // we didn't use the error message, let's keep a clean stack
461 // since we are inside Lua's GCTM, it will be propagated through the warning system (Lua 5.4) or swallowed silently 480 lua_pop(L_, 1); // L_: U
462 // IMPORTANT: lua_error() is used here instead of the wrapper raise_lua_error() to circumvent what looks like a MSVC compiler bug
463 // that manifests as a crash inside ntdll!longjmp() function, in optimized builds only
464 lua_error(L_);
465 } 481 }
466 } 482 }
483 STACK_CHECK(L_, 1);
467 484
468 // --------------------------------------------------------- 485 // ---------------------------------------------------------
469 // we don't reach that point if some lanes are still running 486 // we don't reach that point if some lanes are still running
@@ -472,7 +489,9 @@ int Universe::UniverseGC(lua_State* const L_)
472 // no need to mutex-protect this as all lanes in the universe are gone at that point 489 // no need to mutex-protect this as all lanes in the universe are gone at that point
473 Linda::DeleteTimerLinda(L_, std::exchange(_U->timerLinda, nullptr), PK); 490 Linda::DeleteTimerLinda(L_, std::exchange(_U->timerLinda, nullptr), PK);
474 491
475 _U->keepers.close(); 492 if (!_U->keepers.close()) {
493 raise_luaL_error(L_, "INTERNAL ERROR: Keepers closed more than once");
494 }
476 495
477 // remove the protected allocator, if any 496 // remove the protected allocator, if any
478 _U->protectedAllocator.removeFrom(L_); 497 _U->protectedAllocator.removeFrom(L_);
diff --git a/src/universe.hpp b/src/universe.hpp
index 0c5e659..f781e92 100644
--- a/src/universe.hpp
+++ b/src/universe.hpp
@@ -4,6 +4,7 @@
4#include "cancel.hpp" 4#include "cancel.hpp"
5#include "keeper.hpp" 5#include "keeper.hpp"
6#include "lanesconf.h" 6#include "lanesconf.h"
7#include "threading.hpp"
7#include "tracker.hpp" 8#include "tracker.hpp"
8#include "uniquekey.hpp" 9#include "uniquekey.hpp"
9 10
@@ -27,12 +28,7 @@ class ProtectedAllocator final
27 std::mutex mutex; 28 std::mutex mutex;
28 29
29 [[nodiscard]] 30 [[nodiscard]]
30 static void* protected_lua_Alloc(void* const ud_, void* const ptr_, size_t const osize_, size_t const nsize_) 31 static void* Protected_lua_Alloc(void* const ud_, void* const ptr_, size_t const osize_, size_t const nsize_);
31 {
32 ProtectedAllocator* const allocator{ static_cast<ProtectedAllocator*>(ud_) };
33 std::lock_guard<std::mutex> guard{ allocator->mutex };
34 return allocator->alloc(ptr_, osize_, nsize_);
35 }
36 32
37 public: 33 public:
38 // we are not like our base class: we can't be created inside a full userdata (or we would have to install a metatable and __gc handler to destroy ourselves properly) 34 // we are not like our base class: we can't be created inside a full userdata (or we would have to install a metatable and __gc handler to destroy ourselves properly)
@@ -42,13 +38,13 @@ class ProtectedAllocator final
42 38
43 AllocatorDefinition makeDefinition() 39 AllocatorDefinition makeDefinition()
44 { 40 {
45 return AllocatorDefinition{ protected_lua_Alloc, this }; 41 return AllocatorDefinition{ Protected_lua_Alloc, this };
46 } 42 }
47 43
48 void installIn(lua_State* const L_) const 44 void installIn(lua_State* const L_) const
49 { 45 {
50 // install our replacement allocator function (this is a C function, we need to deconst ourselves) 46 // install our replacement allocator function (this is a C function, we need to deconst ourselves)
51 lua_setallocf(L_, protected_lua_Alloc, static_cast<void*>(const_cast<ProtectedAllocator*>(this))); 47 lua_setallocf(L_, Protected_lua_Alloc, static_cast<void*>(const_cast<ProtectedAllocator*>(this)));
52 } 48 }
53 49
54 void removeFrom(lua_State* const L_) const 50 void removeFrom(lua_State* const L_) const
@@ -75,9 +71,9 @@ class Universe final
75 71
76#ifdef PLATFORM_LINUX 72#ifdef PLATFORM_LINUX
77 // Linux needs to check, whether it's been run as root 73 // Linux needs to check, whether it's been run as root
78 bool const sudo{ geteuid() == 0 }; 74 SudoFlag const sudo{ geteuid() == 0 };
79#else 75#else
80 bool const sudo{ false }; 76 SudoFlag const sudo{ false };
81#endif // PLATFORM_LINUX 77#endif // PLATFORM_LINUX
82 78
83 // for verbose errors 79 // for verbose errors
@@ -132,7 +128,7 @@ class Universe final
132 128
133 public: 129 public:
134 [[nodiscard]] 130 [[nodiscard]]
135 static void* operator new([[maybe_unused]] size_t const size_, lua_State* const L_) noexcept { return luaG_newuserdatauv<Universe>(L_, UserValueCount{ 0 }); }; 131 static void* operator new([[maybe_unused]] size_t const size_, lua_State* const L_) noexcept { return luaW_newuserdatauv<Universe>(L_, UserValueCount{ 0 }); };
136 // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception 132 // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception
137 static void operator delete([[maybe_unused]] void* const p_, [[maybe_unused]] lua_State* const L_) {} // nothing to do, as nothing is allocated independently 133 static void operator delete([[maybe_unused]] void* const p_, [[maybe_unused]] lua_State* const L_) {} // nothing to do, as nothing is allocated independently
138 134
diff --git a/tests/appendud.lua b/tests/appendud.lua
index f6f99c1..2a8c8ce 100644
--- a/tests/appendud.lua
+++ b/tests/appendud.lua
@@ -49,7 +49,7 @@ assert(not err)
49-- test 49-- test
50-- print("t:join()") 50-- print("t:join()")
51a,b,c = t[1],t[2],t[3] -- Need to explicitly wait for the thread, since 'ipairs()' does not 51a,b,c = t[1],t[2],t[3] -- Need to explicitly wait for the thread, since 'ipairs()' does not
52--a,b,c = t:join() -- Need to explicitly wait for the thread, since 'ipairs()' does not 52--r,a,b,c = t:join() -- Need to explicitly wait for the thread, since 'ipairs()' does not
53 -- value the '__index' metamethod (wouldn't it be cool if it did..?) 53 -- value the '__index' metamethod (wouldn't it be cool if it did..?)
54 54
55print(a,b,c) 55print(a,b,c)
diff --git a/tests/basic.lua b/tests/basic.lua
index 9aaad97..f393175 100644
--- a/tests/basic.lua
+++ b/tests/basic.lua
@@ -507,19 +507,20 @@ local S = lanes.gen("table", { name = 'auto', gc_cb = gc_cb },
507 return (unpack or table.unpack)(aux) 507 return (unpack or table.unpack)(aux)
508end) 508end)
509 509
510h= S { 12, 13, 14 } -- execution starts, h[1..3] will get the return values 510h = S { 12, 13, 14 } -- execution starts, h[1..3] will get the return values
511-- wait a bit so that the lane has a chance to set its debug name 511-- wait a bit so that the lane has a chance to set its debug name
512SLEEP(0.5) 512SLEEP(0.5)
513print("joining with '" .. h:get_threadname() .. "'") 513print("joining with '" .. h:get_threadname() .. "'")
514local a,b,c,d= h:join() 514local r,a,b,c,d= h:join()
515if h.status == "error" then 515if h.status == "error" then
516 print(h:get_threadname(), "error: " , a, b, c, d) 516 print(h:get_threadname(), "error: " , r, a, b, c, d)
517else 517else
518 print(h:get_threadname(), a,b,c,d) 518 print(h:get_threadname(), r,a,b,c,d)
519 assert(a==14) 519 assert(r == true)
520 assert(b==13) 520 assert(a == 14)
521 assert(c==12) 521 assert(b == 13)
522 assert(d==nil) 522 assert(c == 12)
523 assert(d == nil)
523end 524end
524 525
525local nameof_type, nameof_name = lanes.nameof(print) 526local nameof_type, nameof_name = lanes.nameof(print)
diff --git a/tests/error.lua b/tests/error.lua
index 28cfff1..76ceea4 100644
--- a/tests/error.lua
+++ b/tests/error.lua
@@ -173,8 +173,7 @@ local do_error_catching_test = function(error_reporting_mode_, error_value_, fin
173 local h = start_lane(error_reporting_mode_, error_value_, finalizer_, finalizer_error_value_) 173 local h = start_lane(error_reporting_mode_, error_value_, finalizer_, finalizer_error_value_)
174 local ret,err,stack= h:join() -- wait for the lane (no automatic error propagation) 174 local ret,err,stack= h:join() -- wait for the lane (no automatic error propagation)
175 WR("Processing results for {", error_reporting_mode_, error_value_, finalizer_, finalizer_error_value_, "}") 175 WR("Processing results for {", error_reporting_mode_, error_value_, finalizer_, finalizer_error_value_, "}")
176 if err then 176 if ret == nil then
177 assert(ret == nil)
178 assert(error_reporting_mode_ == "minimal" or type(stack)=="table") -- only true if lane was configured with error_trace_level ~= "minimal" 177 assert(error_reporting_mode_ == "minimal" or type(stack)=="table") -- only true if lane was configured with error_trace_level ~= "minimal"
179 if err == error_value_ then 178 if err == error_value_ then
180 WR("Lane regular error: ", err) 179 WR("Lane regular error: ", err)
@@ -198,8 +197,8 @@ local do_error_catching_test = function(error_reporting_mode_, error_value_, fin
198 end 197 end
199 end 198 end
200 else -- no error 199 else -- no error
201 assert(ret == "success") 200 assert(ret == true and err == "success")
202 WR("No error in lane: ", ret) 201 WR("No error in lane: ", err, ret)
203 end 202 end
204 WR "TEST OK" 203 WR "TEST OK"
205end 204end
diff --git a/tests/finalizer.lua b/tests/finalizer.lua
index ac5ce8b..9fa12dc 100644
--- a/tests/finalizer.lua
+++ b/tests/finalizer.lua
@@ -77,8 +77,8 @@ local do_test = function(error_)
77 77
78 local h = lgen(error_) 78 local h = lgen(error_)
79 79
80 local _,err,stack = h:join() -- wait for the lane (no automatic error propagation) 80 local r,err,stack = h:join() -- wait for the lane (no automatic error propagation)
81 if err then 81 if not r then
82 assert(stack, "no stack trace on error, check 'error_trace_level'") 82 assert(stack, "no stack trace on error, check 'error_trace_level'")
83 io.stderr:write( "Lane error: "..tostring(err).."\n" ) 83 io.stderr:write( "Lane error: "..tostring(err).."\n" )
84 io.stderr:write( "\t", table.concat(stack,"\t\n"), "\n" ) 84 io.stderr:write( "\t", table.concat(stack,"\t\n"), "\n" )
diff --git a/tests/func_is_string.lua b/tests/func_is_string.lua
index 5de4c60..3c91603 100644
--- a/tests/func_is_string.lua
+++ b/tests/func_is_string.lua
@@ -21,16 +21,17 @@ end
21 21
22local options = {globals = { b = 666 }} 22local options = {globals = { b = 666 }}
23 23
24local gen1 = lanes.gen("*", { name = 'auto' }, "return true, dofile('fibonacci.lua')") 24local gen1 = lanes.gen("*", { name = 'auto' }, "return true, error('bob')")
25local gen2 = lanes.gen(options, { name = 'auto' }, "return b")
26 25
27fibLane = gen1() 26fibLane = gen1()
28lanes.sleep(0.1) 27lanes.sleep(0.1)
29print(fibLane, fibLane.status) 28print(fibLane, fibLane.status)
30local _status, _err = fibLane:join() 29local _r, _err, _stk = fibLane:join()
31print(_status, _err) 30assert(_r == nil, "got " .. tostring(_r) .. " " .. tostring(_err) .. " " .. tostring(_stk))
32 31
33retLane1, retLane2 = gen2(), gen2() 32local gen2 = lanes.gen(options, { name = 'auto' }, "return b")
33local retLane1, retLane2 = gen2(), gen2()
34 34
35print( retLane1[1], retLane2[1]) 35print( retLane1[1], retLane2[1])
36print "TEST OK" \ No newline at end of file 36assert(retLane1[1] == 666 and retLane2[1] == 666)
37print "TEST OK"
diff --git a/tests/irayo_closure.lua b/tests/irayo_closure.lua
index 705b85e..40c586d 100644
--- a/tests/irayo_closure.lua
+++ b/tests/irayo_closure.lua
@@ -5,7 +5,7 @@
5"Another issue I've noticed is trying to pass a table with a function 5"Another issue I've noticed is trying to pass a table with a function
6that uses closures in it as a global variable into a new lane. This 6that uses closures in it as a global variable into a new lane. This
7causes a segmentation fault and it appears to be related to the 7causes a segmentation fault and it appears to be related to the
8luaG_inter_move function near line 835-836 or so in lanes.c, but I 8luaW_inter_move function near line 835-836 or so in lanes.c, but I
9haven't investigated further. 9haven't investigated further.
10e.g. { globals = { data = 1, func = function() useclosurehere() end } }" 10e.g. { globals = { data = 1, func = function() useclosurehere() end } }"
11]] 11]]
diff --git a/tests/launchtest.lua b/tests/launchtest.lua
index 57411e1..cdd6ffc 100644
--- a/tests/launchtest.lua
+++ b/tests/launchtest.lua
@@ -69,8 +69,8 @@ else
69 io.stderr:write( N.." lanes launched.\n" ) 69 io.stderr:write( N.." lanes launched.\n" )
70 70
71 for i=1,N do 71 for i=1,N do
72 local rc= t[i]:join() 72 local r,rc = t[i]:join()
73 assert( rc==i ) 73 assert( r == true and rc == i )
74 end 74 end
75 75
76 io.stderr:write( N.." lanes finished.\n" ) 76 io.stderr:write( N.." lanes finished.\n" )
diff --git a/tests/linda_perf.lua b/tests/linda_perf.lua
index 83b8921..e68d552 100644
--- a/tests/linda_perf.lua
+++ b/tests/linda_perf.lua
@@ -56,7 +56,7 @@ local eater = function( l, loop)
56 -- print "loop is over" 56 -- print "loop is over"
57 key, val = l:receive( "done") 57 key, val = l:receive( "done")
58 print("eater: done ("..val..")") 58 print("eater: done ("..val..")")
59 return true 59 return "ate everything"
60end 60end
61 61
62-- ################################################################################################# 62-- #################################################################################################
@@ -74,7 +74,7 @@ local gobbler = function( l, loop, batch)
74 print "loop is over" 74 print "loop is over"
75 key, val = l:receive( "done") 75 key, val = l:receive( "done")
76 print("gobbler: done ("..val..")") 76 print("gobbler: done ("..val..")")
77 return true 77 return "gobbled everything"
78end 78end
79 79
80-- ################################################################################################# 80-- #################################################################################################
@@ -123,7 +123,8 @@ local function ziva1( preloop, loop, batch)
123 end 123 end
124 end 124 end
125 l:send( "done" ,"are you happy?") 125 l:send( "done" ,"are you happy?")
126 lane:join() 126 local r, ret = lane:join()
127 assert(r == true and type(ret) == "string", "got " .. tostring(r) .. " " .. tostring(ret))
127 return lanes.now_secs() - t1 128 return lanes.now_secs() - t1
128end 129end
129 130
diff --git a/tests/perftest.lua b/tests/perftest.lua
index fe43cca..35e164d 100644
--- a/tests/perftest.lua
+++ b/tests/perftest.lua
@@ -175,9 +175,9 @@ else
175 -- Make sure all lanes finished 175 -- Make sure all lanes finished
176 -- 176 --
177 for i=1,N do 177 for i=1,N do
178 local tmp= t[i]:join() 178 local r, tmp = t[i]:join()
179 -- this assert will trigger if you change M to values below 1000 in order to solve C stack overflow 179 -- this assert will trigger if you change M to values below 1000 in order to solve C stack overflow
180 assert( type(tmp)=="table" and tmp[1]==2 and tmp[168]==997 ) 180 assert( r == true and type(tmp) == "table" and tmp[1] == 2 and tmp[168] == 997 )
181 end 181 end
182end 182end
183 183
diff --git a/tests/pingpong.lua b/tests/pingpong.lua
index 06c0903..1ed5b9a 100644
--- a/tests/pingpong.lua
+++ b/tests/pingpong.lua
@@ -21,13 +21,15 @@ local pingpong = function(name, qr, qs, start)
21 q:send(qs, val) 21 q:send(qs, val)
22 count = count + 1 22 count = count + 1
23 end 23 end
24 return true 24 return "ping!"
25end 25end
26 26
27-- pingpong("L1", '0', '1', true) 27-- pingpong("L1", '0', '1', true)
28local t1, err1 = lanes.gen("*", { name = 'auto' }, pingpong)("L1", 'a', 'b', true) 28local t1, err1 = lanes.gen("*", { name = 'auto' }, pingpong)("L1", 'a', 'b', true)
29local t2, err2 = lanes.gen("*", { name = 'auto' }, pingpong)("L2", 'b', 'a', false) 29local t2, err2 = lanes.gen("*", { name = 'auto' }, pingpong)("L2", 'b', 'a', false)
30 30
31t1:join() 31local r1, ret1 = t1:join()
32t2:join() 32assert(r1 == true and ret1 == "ping!")
33local r2, ret2 = t2:join()
34assert(r2 == true and ret2 == "ping!")
33print "TEST OK" 35print "TEST OK"
diff --git a/tests/rupval.lua b/tests/rupval.lua
index ad5ad9d..c6743b3 100644
--- a/tests/rupval.lua
+++ b/tests/rupval.lua
@@ -26,17 +26,17 @@ end
26local g = lanes.gen( "base", { name = 'auto' }, a) 26local g = lanes.gen( "base", { name = 'auto' }, a)
27 27
28local l = g(7) 28local l = g(7)
29local r = l:join() 29local _, r = l:join()
30assert(r == y) 30assert(r == y)
31print(r) 31print(r)
32 32
33local l = g(8) 33local l = g(8)
34local r = l:join() 34local _, r = l:join()
35assert(r == z) 35assert(r == z)
36print(r) 36print(r)
37 37
38local l = g(9) 38local l = g(9)
39local r = l:join() 39local _, r = l:join()
40assert(r == x) 40assert(r == x)
41print(r) 41print(r)
42 42
diff --git a/tests/tobeclosed.lua b/tests/tobeclosed.lua
index 447b936..fd157e2 100644
--- a/tests/tobeclosed.lua
+++ b/tests/tobeclosed.lua
@@ -106,7 +106,7 @@ do
106 local _count, l_out <close> = l:get("trip") 106 local _count, l_out <close> = l:get("trip")
107 -- linda from arguments 107 -- linda from arguments
108 local l_arg <close> = l_arg_ 108 local l_arg <close> = l_arg_
109 return true 109 return "done"
110 end 110 end
111 111
112 local close_handler_f = function(linda_, err_) 112 local close_handler_f = function(linda_, err_)
@@ -118,7 +118,8 @@ do
118 l:set("trip", l_in) 118 l:set("trip", l_in)
119 119
120 do 120 do
121 lanes.gen("*", { name = 'auto' }, lane_body)(l_in):join() 121 local r, ret = lanes.gen("*", { name = 'auto' }, lane_body)(l_in):join()
122 assert(r == true and ret == "done")
122 end 123 end
123 local _count, _closed = l_in:get("closed") 124 local _count, _closed = l_in:get("closed")
124 assert(_count == 1 and _closed == 2) 125 assert(_count == 1 and _closed == 2)
diff --git a/unit_tests/UnitTests.vcxproj b/unit_tests/UnitTests.vcxproj
index 8c22653..2093063 100644
--- a/unit_tests/UnitTests.vcxproj
+++ b/unit_tests/UnitTests.vcxproj
@@ -45,6 +45,30 @@
45 <Configuration>Debug 5.4</Configuration> 45 <Configuration>Debug 5.4</Configuration>
46 <Platform>Win32</Platform> 46 <Platform>Win32</Platform>
47 </ProjectConfiguration> 47 </ProjectConfiguration>
48 <ProjectConfiguration Include="Debug 5.5|Prospero">
49 <Configuration>Debug 5.5</Configuration>
50 <Platform>Prospero</Platform>
51 </ProjectConfiguration>
52 <ProjectConfiguration Include="Debug 5.5|Win32">
53 <Configuration>Debug 5.5</Configuration>
54 <Platform>Win32</Platform>
55 </ProjectConfiguration>
56 <ProjectConfiguration Include="Debug 5.5|x64">
57 <Configuration>Debug 5.5</Configuration>
58 <Platform>x64</Platform>
59 </ProjectConfiguration>
60 <ProjectConfiguration Include="Release 5.5|Prospero">
61 <Configuration>Release 5.5</Configuration>
62 <Platform>Prospero</Platform>
63 </ProjectConfiguration>
64 <ProjectConfiguration Include="Release 5.5|Win32">
65 <Configuration>Release 5.5</Configuration>
66 <Platform>Win32</Platform>
67 </ProjectConfiguration>
68 <ProjectConfiguration Include="Release 5.5|x64">
69 <Configuration>Release 5.5</Configuration>
70 <Platform>x64</Platform>
71 </ProjectConfiguration>
48 <ProjectConfiguration Include="Release LuaJIT|Prospero"> 72 <ProjectConfiguration Include="Release LuaJIT|Prospero">
49 <Configuration>Release LuaJIT</Configuration> 73 <Configuration>Release LuaJIT</Configuration>
50 <Platform>Prospero</Platform> 74 <Platform>Prospero</Platform>
@@ -125,7 +149,7 @@
125 <PropertyGroup Label="Globals"> 149 <PropertyGroup Label="Globals">
126 <ProjectGuid>{aed7f42f-139a-46ba-80fe-16e062ea1345}</ProjectGuid> 150 <ProjectGuid>{aed7f42f-139a-46ba-80fe-16e062ea1345}</ProjectGuid>
127 <Keyword>Win32Proj</Keyword> 151 <Keyword>Win32Proj</Keyword>
128 <WindowsTargetPlatformVersion>10.0.22621.0</WindowsTargetPlatformVersion> 152 <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
129 <ConfigurationType>Application</ConfigurationType> 153 <ConfigurationType>Application</ConfigurationType>
130 <PlatformToolset>v143</PlatformToolset> 154 <PlatformToolset>v143</PlatformToolset>
131 <CharacterSet>Unicode</CharacterSet> 155 <CharacterSet>Unicode</CharacterSet>
@@ -143,6 +167,9 @@
143 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'"> 167 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">
144 <UseDebugLibraries>true</UseDebugLibraries> 168 <UseDebugLibraries>true</UseDebugLibraries>
145 </PropertyGroup> 169 </PropertyGroup>
170 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'" Label="Configuration">
171 <UseDebugLibraries>true</UseDebugLibraries>
172 </PropertyGroup>
146 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'"> 173 <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'">
147 <UseDebugLibraries>true</UseDebugLibraries> 174 <UseDebugLibraries>true</UseDebugLibraries>
148 </PropertyGroup> 175 </PropertyGroup>
@@ -159,6 +186,11 @@
159 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 186 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
160 <LinkIncremental>false</LinkIncremental> 187 <LinkIncremental>false</LinkIncremental>
161 </PropertyGroup> 188 </PropertyGroup>
189 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">
190 <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir>
191 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
192 <LinkIncremental>false</LinkIncremental>
193 </PropertyGroup>
162 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'"> 194 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">
163 <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> 195 <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir>
164 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 196 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
@@ -204,11 +236,21 @@
204 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 236 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
205 <LinkIncremental>false</LinkIncremental> 237 <LinkIncremental>false</LinkIncremental>
206 </PropertyGroup> 238 </PropertyGroup>
239 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">
240 <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir>
241 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
242 <LinkIncremental>false</LinkIncremental>
243 </PropertyGroup>
207 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'"> 244 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">
208 <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> 245 <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir>
209 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 246 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
210 <LinkIncremental>false</LinkIncremental> 247 <LinkIncremental>false</LinkIncremental>
211 </PropertyGroup> 248 </PropertyGroup>
249 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">
250 <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir>
251 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
252 <LinkIncremental>false</LinkIncremental>
253 </PropertyGroup>
212 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'" /> 254 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'" />
213 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'"> 255 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">
214 <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> 256 <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir>
@@ -255,13 +297,37 @@
255 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> 297 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
256 <LinkIncremental>false</LinkIncremental> 298 <LinkIncremental>false</LinkIncremental>
257 </PropertyGroup> 299 </PropertyGroup>
300 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">
301 <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir>
302 <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir>
303 <LinkIncremental>false</LinkIncremental>
304 </PropertyGroup>
258 <ItemDefinitionGroup /> 305 <ItemDefinitionGroup />
259 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'"> 306 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">
260 <ClCompile> 307 <ClCompile>
261 <PrecompiledHeader>Use</PrecompiledHeader> 308 <PrecompiledHeader>Use</PrecompiledHeader>
262 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 309 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
263 <Optimization>Disabled</Optimization> 310 <Optimization>Disabled</Optimization>
264 <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 311 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
312 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
313 <WarningLevel>Level3</WarningLevel>
314 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
315 <LanguageStandard>stdcpp20</LanguageStandard>
316 <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
317 </ClCompile>
318 <Link>
319 <GenerateDebugInformation>true</GenerateDebugInformation>
320 <SubSystem>Console</SubSystem>
321 <AdditionalDependencies>lua54.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
322 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
323 </Link>
324 </ItemDefinitionGroup>
325 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">
326 <ClCompile>
327 <PrecompiledHeader>Use</PrecompiledHeader>
328 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
329 <Optimization>Disabled</Optimization>
330 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
265 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 331 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
266 <WarningLevel>Level3</WarningLevel> 332 <WarningLevel>Level3</WarningLevel>
267 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 333 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -280,7 +346,7 @@
280 <PrecompiledHeader>Use</PrecompiledHeader> 346 <PrecompiledHeader>Use</PrecompiledHeader>
281 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 347 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
282 <Optimization>Disabled</Optimization> 348 <Optimization>Disabled</Optimization>
283 <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 349 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
284 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 350 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
285 <WarningLevel>Level3</WarningLevel> 351 <WarningLevel>Level3</WarningLevel>
286 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 352 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -299,7 +365,7 @@
299 <PrecompiledHeader>Use</PrecompiledHeader> 365 <PrecompiledHeader>Use</PrecompiledHeader>
300 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 366 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
301 <Optimization>Disabled</Optimization> 367 <Optimization>Disabled</Optimization>
302 <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 368 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
303 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 369 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
304 <WarningLevel>Level3</WarningLevel> 370 <WarningLevel>Level3</WarningLevel>
305 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 371 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -318,7 +384,7 @@
318 <PrecompiledHeader>Use</PrecompiledHeader> 384 <PrecompiledHeader>Use</PrecompiledHeader>
319 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 385 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
320 <Optimization>Disabled</Optimization> 386 <Optimization>Disabled</Optimization>
321 <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 387 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
322 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 388 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
323 <WarningLevel>Level3</WarningLevel> 389 <WarningLevel>Level3</WarningLevel>
324 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 390 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -337,7 +403,7 @@
337 <PrecompiledHeader>Use</PrecompiledHeader> 403 <PrecompiledHeader>Use</PrecompiledHeader>
338 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 404 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
339 <Optimization>Disabled</Optimization> 405 <Optimization>Disabled</Optimization>
340 <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 406 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
341 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 407 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
342 <WarningLevel>Level3</WarningLevel> 408 <WarningLevel>Level3</WarningLevel>
343 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 409 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -356,7 +422,7 @@
356 <PrecompiledHeader>Use</PrecompiledHeader> 422 <PrecompiledHeader>Use</PrecompiledHeader>
357 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 423 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
358 <Optimization>Disabled</Optimization> 424 <Optimization>Disabled</Optimization>
359 <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 425 <PreprocessorDefinitions>LANES_DEBUG;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
360 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 426 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
361 <WarningLevel>Level3</WarningLevel> 427 <WarningLevel>Level3</WarningLevel>
362 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 428 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -375,7 +441,7 @@
375 <PrecompiledHeader>Use</PrecompiledHeader> 441 <PrecompiledHeader>Use</PrecompiledHeader>
376 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 442 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
377 <Optimization>Disabled</Optimization> 443 <Optimization>Disabled</Optimization>
378 <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 444 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
379 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 445 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
380 <WarningLevel>Level3</WarningLevel> 446 <WarningLevel>Level3</WarningLevel>
381 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 447 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -394,7 +460,7 @@
394 <PrecompiledHeader>Use</PrecompiledHeader> 460 <PrecompiledHeader>Use</PrecompiledHeader>
395 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 461 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
396 <Optimization>Disabled</Optimization> 462 <Optimization>Disabled</Optimization>
397 <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 463 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
398 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 464 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
399 <WarningLevel>Level3</WarningLevel> 465 <WarningLevel>Level3</WarningLevel>
400 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 466 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -413,7 +479,7 @@
413 <PrecompiledHeader>Use</PrecompiledHeader> 479 <PrecompiledHeader>Use</PrecompiledHeader>
414 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 480 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
415 <Optimization>Disabled</Optimization> 481 <Optimization>Disabled</Optimization>
416 <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 482 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
417 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 483 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
418 <WarningLevel>Level3</WarningLevel> 484 <WarningLevel>Level3</WarningLevel>
419 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 485 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -432,7 +498,7 @@
432 <PrecompiledHeader>Use</PrecompiledHeader> 498 <PrecompiledHeader>Use</PrecompiledHeader>
433 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 499 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
434 <Optimization>Disabled</Optimization> 500 <Optimization>Disabled</Optimization>
435 <PreprocessorDefinitions>X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 501 <PreprocessorDefinitions>LANES_DEBUG;X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
436 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 502 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
437 <WarningLevel>Level3</WarningLevel> 503 <WarningLevel>Level3</WarningLevel>
438 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 504 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -448,6 +514,27 @@
448 </IgnoreSpecificDefaultLibraries> 514 </IgnoreSpecificDefaultLibraries>
449 </Link> 515 </Link>
450 </ItemDefinitionGroup> 516 </ItemDefinitionGroup>
517 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">
518 <ClCompile>
519 <PrecompiledHeader>Use</PrecompiledHeader>
520 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
521 <Optimization>Disabled</Optimization>
522 <PreprocessorDefinitions>LANES_DEBUG;X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
523 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
524 <WarningLevel>Level3</WarningLevel>
525 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
526 <LanguageStandard>stdcpp20</LanguageStandard>
527 <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
528 </ClCompile>
529 <Link>
530 <GenerateDebugInformation>true</GenerateDebugInformation>
531 <SubSystem>Console</SubSystem>
532 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
533 <AdditionalDependencies>lua55.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
534 <IgnoreSpecificDefaultLibraries>
535 </IgnoreSpecificDefaultLibraries>
536 </Link>
537 </ItemDefinitionGroup>
451 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'"> 538 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'">
452 <ClCompile> 539 <ClCompile>
453 <PrecompiledHeader>Use</PrecompiledHeader> 540 <PrecompiledHeader>Use</PrecompiledHeader>
@@ -469,7 +556,7 @@
469 </IgnoreSpecificDefaultLibraries> 556 </IgnoreSpecificDefaultLibraries>
470 </Link> 557 </Link>
471 </ItemDefinitionGroup> 558 </ItemDefinitionGroup>
472 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'"> 559 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Prospero'">
473 <ClCompile> 560 <ClCompile>
474 <PrecompiledHeader>Use</PrecompiledHeader> 561 <PrecompiledHeader>Use</PrecompiledHeader>
475 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 562 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
@@ -477,6 +564,27 @@
477 <PreprocessorDefinitions>X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 564 <PreprocessorDefinitions>X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
478 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 565 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
479 <WarningLevel>Level3</WarningLevel> 566 <WarningLevel>Level3</WarningLevel>
567 <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\Lua54\include;$(SolutionDir)..</AdditionalIncludeDirectories>
568 <LanguageStandard>stdcpp20</LanguageStandard>
569 <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
570 </ClCompile>
571 <Link>
572 <GenerateDebugInformation>true</GenerateDebugInformation>
573 <SubSystem>Console</SubSystem>
574 <AdditionalLibraryDirectories>$(SolutionDir)..\..\..\Lua54\bin\$(Platform)\Debug;$(SolutionDir)..\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1.7\lib\native\v140\windesktop\msvcstl\static\rt-dyn\x64\Debug</AdditionalLibraryDirectories>
575 <AdditionalDependencies>lua54.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
576 <IgnoreSpecificDefaultLibraries>
577 </IgnoreSpecificDefaultLibraries>
578 </Link>
579 </ItemDefinitionGroup>
580 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">
581 <ClCompile>
582 <PrecompiledHeader>Use</PrecompiledHeader>
583 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
584 <Optimization>Disabled</Optimization>
585 <PreprocessorDefinitions>LANES_DEBUG;X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
586 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
587 <WarningLevel>Level3</WarningLevel>
480 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 588 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
481 <LanguageStandard>stdcpp20</LanguageStandard> 589 <LanguageStandard>stdcpp20</LanguageStandard>
482 <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> 590 <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
@@ -494,7 +602,7 @@
494 <ClCompile> 602 <ClCompile>
495 <PrecompiledHeader>Use</PrecompiledHeader> 603 <PrecompiledHeader>Use</PrecompiledHeader>
496 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 604 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
497 <PreprocessorDefinitions>X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 605 <PreprocessorDefinitions>LANES_DEBUG;X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
498 <WarningLevel>Level3</WarningLevel> 606 <WarningLevel>Level3</WarningLevel>
499 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 607 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
500 <LanguageStandard>stdcpp20</LanguageStandard> 608 <LanguageStandard>stdcpp20</LanguageStandard>
@@ -555,7 +663,7 @@
555 <PrecompiledHeader>Use</PrecompiledHeader> 663 <PrecompiledHeader>Use</PrecompiledHeader>
556 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 664 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
557 <Optimization>Disabled</Optimization> 665 <Optimization>Disabled</Optimization>
558 <PreprocessorDefinitions>X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 666 <PreprocessorDefinitions>LANES_DEBUG;X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
559 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 667 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
560 <WarningLevel>Level3</WarningLevel> 668 <WarningLevel>Level3</WarningLevel>
561 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 669 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -575,7 +683,7 @@
575 <ClCompile> 683 <ClCompile>
576 <PrecompiledHeader>Use</PrecompiledHeader> 684 <PrecompiledHeader>Use</PrecompiledHeader>
577 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 685 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
578 <PreprocessorDefinitions>X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 686 <PreprocessorDefinitions>LANES_DEBUG;X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
579 <WarningLevel>Level3</WarningLevel> 687 <WarningLevel>Level3</WarningLevel>
580 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 688 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
581 <LanguageStandard>stdcpp20</LanguageStandard> 689 <LanguageStandard>stdcpp20</LanguageStandard>
@@ -636,7 +744,7 @@
636 <PrecompiledHeader>Use</PrecompiledHeader> 744 <PrecompiledHeader>Use</PrecompiledHeader>
637 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 745 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
638 <Optimization>Disabled</Optimization> 746 <Optimization>Disabled</Optimization>
639 <PreprocessorDefinitions>X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 747 <PreprocessorDefinitions>LANES_DEBUG;X64;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
640 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 748 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
641 <WarningLevel>Level3</WarningLevel> 749 <WarningLevel>Level3</WarningLevel>
642 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 750 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -656,7 +764,7 @@
656 <ClCompile> 764 <ClCompile>
657 <PrecompiledHeader>Use</PrecompiledHeader> 765 <PrecompiledHeader>Use</PrecompiledHeader>
658 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 766 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
659 <PreprocessorDefinitions>X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 767 <PreprocessorDefinitions>LANES_DEBUG;X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
660 <WarningLevel>Level3</WarningLevel> 768 <WarningLevel>Level3</WarningLevel>
661 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 769 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
662 <LanguageStandard>stdcpp20</LanguageStandard> 770 <LanguageStandard>stdcpp20</LanguageStandard>
@@ -717,7 +825,7 @@
717 <PrecompiledHeader>Use</PrecompiledHeader> 825 <PrecompiledHeader>Use</PrecompiledHeader>
718 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 826 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
719 <Optimization>Disabled</Optimization> 827 <Optimization>Disabled</Optimization>
720 <PreprocessorDefinitions>X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 828 <PreprocessorDefinitions>LANES_DEBUG;X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
721 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 829 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
722 <WarningLevel>Level3</WarningLevel> 830 <WarningLevel>Level3</WarningLevel>
723 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 831 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -738,7 +846,7 @@
738 <PrecompiledHeader>Use</PrecompiledHeader> 846 <PrecompiledHeader>Use</PrecompiledHeader>
739 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 847 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
740 <Optimization>Disabled</Optimization> 848 <Optimization>Disabled</Optimization>
741 <PreprocessorDefinitions>X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 849 <PreprocessorDefinitions>LANES_DEBUG;X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
742 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> 850 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
743 <WarningLevel>Level3</WarningLevel> 851 <WarningLevel>Level3</WarningLevel>
744 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 852 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -800,7 +908,26 @@
800 <ClCompile> 908 <ClCompile>
801 <PrecompiledHeader>Use</PrecompiledHeader> 909 <PrecompiledHeader>Use</PrecompiledHeader>
802 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 910 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
803 <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 911 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
912 <WarningLevel>Level3</WarningLevel>
913 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
914 <LanguageStandard>stdcpp20</LanguageStandard>
915 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
916 </ClCompile>
917 <Link>
918 <GenerateDebugInformation>true</GenerateDebugInformation>
919 <SubSystem>Console</SubSystem>
920 <OptimizeReferences>true</OptimizeReferences>
921 <EnableCOMDATFolding>true</EnableCOMDATFolding>
922 <AdditionalDependencies>lua54.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
923 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
924 </Link>
925 </ItemDefinitionGroup>
926 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">
927 <ClCompile>
928 <PrecompiledHeader>Use</PrecompiledHeader>
929 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
930 <PreprocessorDefinitions>LANES_DEBUG;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
804 <WarningLevel>Level3</WarningLevel> 931 <WarningLevel>Level3</WarningLevel>
805 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> 932 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
806 <LanguageStandard>stdcpp20</LanguageStandard> 933 <LanguageStandard>stdcpp20</LanguageStandard>
@@ -819,7 +946,7 @@
819 <ClCompile> 946 <ClCompile>
820 <PrecompiledHeader>Use</PrecompiledHeader> 947 <PrecompiledHeader>Use</PrecompiledHeader>
821 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile> 948 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
822 <PreprocessorDefinitions>X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions> 949 <PreprocessorDefinitions>LANES_DEBUG;X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
823 <WarningLevel>Level3</WarningLevel> 950 <WarningLevel>Level3</WarningLevel>
824 <LanguageStandard>stdcpp20</LanguageStandard> 951 <LanguageStandard>stdcpp20</LanguageStandard>
825 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories> 952 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
@@ -833,6 +960,24 @@
833 <AdditionalDependencies>lua54.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies> 960 <AdditionalDependencies>lua54.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
834 </Link> 961 </Link>
835 </ItemDefinitionGroup> 962 </ItemDefinitionGroup>
963 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">
964 <ClCompile>
965 <PrecompiledHeader>Use</PrecompiledHeader>
966 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
967 <PreprocessorDefinitions>LANES_DEBUG;X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
968 <WarningLevel>Level3</WarningLevel>
969 <LanguageStandard>stdcpp20</LanguageStandard>
970 <AdditionalIncludeDirectories>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)/include;$(SolutionDir)..</AdditionalIncludeDirectories>
971 </ClCompile>
972 <Link>
973 <GenerateDebugInformation>true</GenerateDebugInformation>
974 <SubSystem>Console</SubSystem>
975 <OptimizeReferences>true</OptimizeReferences>
976 <EnableCOMDATFolding>true</EnableCOMDATFolding>
977 <AdditionalLibraryDirectories>$(SolutionDir)_LuaVersions\$(PlatformName)\$(ConfigurationName)</AdditionalLibraryDirectories>
978 <AdditionalDependencies>lua55.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
979 </Link>
980 </ItemDefinitionGroup>
836 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'"> 981 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'">
837 <ClCompile> 982 <ClCompile>
838 <PrecompiledHeader>Use</PrecompiledHeader> 983 <PrecompiledHeader>Use</PrecompiledHeader>
@@ -852,6 +997,25 @@
852 <AdditionalDependencies>lua54.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies> 997 <AdditionalDependencies>lua54.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
853 </Link> 998 </Link>
854 </ItemDefinitionGroup> 999 </ItemDefinitionGroup>
1000 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Prospero'">
1001 <ClCompile>
1002 <PrecompiledHeader>Use</PrecompiledHeader>
1003 <PrecompiledHeaderFile>_pch.hpp</PrecompiledHeaderFile>
1004 <PreprocessorDefinitions>X64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
1005 <WarningLevel>Level3</WarningLevel>
1006 <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
1007 <LanguageStandard>stdcpp20</LanguageStandard>
1008 <AdditionalIncludeDirectories>$(SolutionDir)..\..\..\Lua54\include;$(SolutionDir)..</AdditionalIncludeDirectories>
1009 </ClCompile>
1010 <Link>
1011 <GenerateDebugInformation>true</GenerateDebugInformation>
1012 <SubSystem>Console</SubSystem>
1013 <OptimizeReferences>true</OptimizeReferences>
1014 <EnableCOMDATFolding>true</EnableCOMDATFolding>
1015 <AdditionalLibraryDirectories>$(SolutionDir)..\..\..\Lua54\bin\$(Platform)\Release;$(SolutionDir)..\Microsoft.googletest.v140.windesktop.msvcstl.static.rt-dyn.1.8.1.7\lib\native\v140\windesktop\msvcstl\static\rt-dyn\x64\Release</AdditionalLibraryDirectories>
1016 <AdditionalDependencies>lua54.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
1017 </Link>
1018 </ItemDefinitionGroup>
855 <ItemGroup> 1019 <ItemGroup>
856 <ClInclude Include="..\src\compat.hpp" /> 1020 <ClInclude Include="..\src\compat.hpp" />
857 <ClInclude Include="..\src\deep.hpp" /> 1021 <ClInclude Include="..\src\deep.hpp" />
@@ -864,11 +1028,13 @@
864 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">NotUsing</PrecompiledHeader> 1028 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">NotUsing</PrecompiledHeader>
865 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">NotUsing</PrecompiledHeader> 1029 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">NotUsing</PrecompiledHeader>
866 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">NotUsing</PrecompiledHeader> 1030 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">NotUsing</PrecompiledHeader>
1031 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">NotUsing</PrecompiledHeader>
867 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">NotUsing</PrecompiledHeader> 1032 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">NotUsing</PrecompiledHeader>
868 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'">NotUsing</PrecompiledHeader> 1033 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'">NotUsing</PrecompiledHeader>
869 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">NotUsing</PrecompiledHeader> 1034 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">NotUsing</PrecompiledHeader>
870 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">NotUsing</PrecompiledHeader> 1035 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">NotUsing</PrecompiledHeader>
871 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">NotUsing</PrecompiledHeader> 1036 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">NotUsing</PrecompiledHeader>
1037 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">NotUsing</PrecompiledHeader>
872 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">NotUsing</PrecompiledHeader> 1038 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">NotUsing</PrecompiledHeader>
873 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Win32'">NotUsing</PrecompiledHeader> 1039 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Win32'">NotUsing</PrecompiledHeader>
874 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">NotUsing</PrecompiledHeader> 1040 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">NotUsing</PrecompiledHeader>
@@ -876,7 +1042,9 @@
876 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'">NotUsing</PrecompiledHeader> 1042 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'">NotUsing</PrecompiledHeader>
877 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Prospero'">NotUsing</PrecompiledHeader> 1043 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Prospero'">NotUsing</PrecompiledHeader>
878 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">NotUsing</PrecompiledHeader> 1044 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">NotUsing</PrecompiledHeader>
1045 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">NotUsing</PrecompiledHeader>
879 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'">NotUsing</PrecompiledHeader> 1046 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'">NotUsing</PrecompiledHeader>
1047 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Prospero'">NotUsing</PrecompiledHeader>
880 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">NotUsing</PrecompiledHeader> 1048 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">NotUsing</PrecompiledHeader>
881 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|x64'">NotUsing</PrecompiledHeader> 1049 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|x64'">NotUsing</PrecompiledHeader>
882 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Prospero'">NotUsing</PrecompiledHeader> 1050 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Prospero'">NotUsing</PrecompiledHeader>
@@ -886,7 +1054,9 @@
886 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'">NotUsing</PrecompiledHeader> 1054 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'">NotUsing</PrecompiledHeader>
887 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Prospero'">NotUsing</PrecompiledHeader> 1055 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Prospero'">NotUsing</PrecompiledHeader>
888 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">NotUsing</PrecompiledHeader> 1056 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">NotUsing</PrecompiledHeader>
1057 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">NotUsing</PrecompiledHeader>
889 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'">NotUsing</PrecompiledHeader> 1058 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'">NotUsing</PrecompiledHeader>
1059 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Prospero'">NotUsing</PrecompiledHeader>
890 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">NotUsing</PrecompiledHeader> 1060 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">NotUsing</PrecompiledHeader>
891 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|x64'">NotUsing</PrecompiledHeader> 1061 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|x64'">NotUsing</PrecompiledHeader>
892 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Prospero'">NotUsing</PrecompiledHeader> 1062 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Prospero'">NotUsing</PrecompiledHeader>
@@ -897,11 +1067,13 @@
897 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">NotUsing</PrecompiledHeader> 1067 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">NotUsing</PrecompiledHeader>
898 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">NotUsing</PrecompiledHeader> 1068 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">NotUsing</PrecompiledHeader>
899 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">NotUsing</PrecompiledHeader> 1069 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">NotUsing</PrecompiledHeader>
1070 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">NotUsing</PrecompiledHeader>
900 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">NotUsing</PrecompiledHeader> 1071 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'">NotUsing</PrecompiledHeader>
901 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'">NotUsing</PrecompiledHeader> 1072 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'">NotUsing</PrecompiledHeader>
902 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">NotUsing</PrecompiledHeader> 1073 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">NotUsing</PrecompiledHeader>
903 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">NotUsing</PrecompiledHeader> 1074 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">NotUsing</PrecompiledHeader>
904 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">NotUsing</PrecompiledHeader> 1075 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">NotUsing</PrecompiledHeader>
1076 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">NotUsing</PrecompiledHeader>
905 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">NotUsing</PrecompiledHeader> 1077 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">NotUsing</PrecompiledHeader>
906 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Win32'">NotUsing</PrecompiledHeader> 1078 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Win32'">NotUsing</PrecompiledHeader>
907 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">NotUsing</PrecompiledHeader> 1079 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">NotUsing</PrecompiledHeader>
@@ -909,7 +1081,9 @@
909 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'">NotUsing</PrecompiledHeader> 1081 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'">NotUsing</PrecompiledHeader>
910 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Prospero'">NotUsing</PrecompiledHeader> 1082 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Prospero'">NotUsing</PrecompiledHeader>
911 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">NotUsing</PrecompiledHeader> 1083 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">NotUsing</PrecompiledHeader>
1084 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">NotUsing</PrecompiledHeader>
912 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'">NotUsing</PrecompiledHeader> 1085 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'">NotUsing</PrecompiledHeader>
1086 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Prospero'">NotUsing</PrecompiledHeader>
913 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">NotUsing</PrecompiledHeader> 1087 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'">NotUsing</PrecompiledHeader>
914 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|x64'">NotUsing</PrecompiledHeader> 1088 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.1|x64'">NotUsing</PrecompiledHeader>
915 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Prospero'">NotUsing</PrecompiledHeader> 1089 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Prospero'">NotUsing</PrecompiledHeader>
@@ -919,7 +1093,9 @@
919 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'">NotUsing</PrecompiledHeader> 1093 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'">NotUsing</PrecompiledHeader>
920 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Prospero'">NotUsing</PrecompiledHeader> 1094 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Prospero'">NotUsing</PrecompiledHeader>
921 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">NotUsing</PrecompiledHeader> 1095 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">NotUsing</PrecompiledHeader>
1096 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">NotUsing</PrecompiledHeader>
922 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'">NotUsing</PrecompiledHeader> 1097 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'">NotUsing</PrecompiledHeader>
1098 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Prospero'">NotUsing</PrecompiledHeader>
923 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">NotUsing</PrecompiledHeader> 1099 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'">NotUsing</PrecompiledHeader>
924 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|x64'">NotUsing</PrecompiledHeader> 1100 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.2|x64'">NotUsing</PrecompiledHeader>
925 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Prospero'">NotUsing</PrecompiledHeader> 1101 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Prospero'">NotUsing</PrecompiledHeader>
@@ -934,6 +1110,7 @@
934 <ClCompile Include="init_and_shutdown.cpp" /> 1110 <ClCompile Include="init_and_shutdown.cpp" />
935 <ClCompile Include="_pch.cpp"> 1111 <ClCompile Include="_pch.cpp">
936 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">Create</PrecompiledHeader> 1112 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'">Create</PrecompiledHeader>
1113 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'">Create</PrecompiledHeader>
937 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">Create</PrecompiledHeader> 1114 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'">Create</PrecompiledHeader>
938 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">Create</PrecompiledHeader> 1115 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'">Create</PrecompiledHeader>
939 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">Create</PrecompiledHeader> 1116 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'">Create</PrecompiledHeader>
@@ -943,8 +1120,11 @@
943 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">Create</PrecompiledHeader> 1120 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'">Create</PrecompiledHeader>
944 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">Create</PrecompiledHeader> 1121 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'">Create</PrecompiledHeader>
945 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">Create</PrecompiledHeader> 1122 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'">Create</PrecompiledHeader>
1123 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'">Create</PrecompiledHeader>
946 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">Create</PrecompiledHeader> 1124 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'">Create</PrecompiledHeader>
1125 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'">Create</PrecompiledHeader>
947 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'">Create</PrecompiledHeader> 1126 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Prospero'">Create</PrecompiledHeader>
1127 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Prospero'">Create</PrecompiledHeader>
948 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">Create</PrecompiledHeader> 1128 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|x64'">Create</PrecompiledHeader>
949 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">Create</PrecompiledHeader> 1129 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'">Create</PrecompiledHeader>
950 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'">Create</PrecompiledHeader> 1130 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Prospero'">Create</PrecompiledHeader>
@@ -962,15 +1142,28 @@
962 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'">Create</PrecompiledHeader> 1142 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Prospero'">Create</PrecompiledHeader>
963 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Prospero'">Create</PrecompiledHeader> 1143 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Prospero'">Create</PrecompiledHeader>
964 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">Create</PrecompiledHeader> 1144 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'">Create</PrecompiledHeader>
1145 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'">Create</PrecompiledHeader>
965 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'">Create</PrecompiledHeader> 1146 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Prospero'">Create</PrecompiledHeader>
1147 <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Prospero'">Create</PrecompiledHeader>
966 </ClCompile> 1148 </ClCompile>
967 </ItemGroup> 1149 </ItemGroup>
968 <ItemGroup> 1150 <ItemGroup>
969 <None Include="..\.runsettings" /> 1151 <None Include="..\.runsettings" />
1152 <None Include="scripts\coro\cancelling_suspended.lua" />
1153 <None Include="scripts\coro\collect_yielded_lane.lua" />
1154 <None Include="scripts\coro\join_suspended.lua" />
1155 <None Include="scripts\coro\linda_in_close_handler.lua" />
1156 <None Include="scripts\coro\regular_function.lua" />
1157 <None Include="scripts\coro\resume_basics.lua" />
1158 <None Include="scripts\coro\yielding_in_non_coro_errors.lua" />
1159 <None Include="scripts\lane\body_is_a_c_function.lua" />
970 <None Include="scripts\lane\tasking_cancelling_with_hook.lua" /> 1160 <None Include="scripts\lane\tasking_cancelling_with_hook.lua" />
1161 <None Include="scripts\linda\send_receive_func_and_string.lua" />
971 <None Include="scripts\linda\wake_period.lua" /> 1162 <None Include="scripts\linda\wake_period.lua" />
1163 <None Include="scripts\misc\deeptest.lua" />
1164 <None Include="scripts\_utils54.lua" />
972 <None Include="UnitTests.makefile" /> 1165 <None Include="UnitTests.makefile" />
973 <None Include="scripts\coro\basics.lua" /> 1166 <None Include="scripts\coro\index_suspended.lua" />
974 <None Include="scripts\coro\error_handling.lua" /> 1167 <None Include="scripts\coro\error_handling.lua" />
975 <None Include="scripts\lane\cooperative_shutdown.lua" /> 1168 <None Include="scripts\lane\cooperative_shutdown.lua" />
976 <None Include="scripts\lane\stdlib_naming.lua" /> 1169 <None Include="scripts\lane\stdlib_naming.lua" />
diff --git a/unit_tests/UnitTests.vcxproj.filters b/unit_tests/UnitTests.vcxproj.filters
index ce8cb58..df82447 100644
--- a/unit_tests/UnitTests.vcxproj.filters
+++ b/unit_tests/UnitTests.vcxproj.filters
@@ -54,6 +54,9 @@
54 <Filter Include="Make"> 54 <Filter Include="Make">
55 <UniqueIdentifier>{c62af5d9-9161-4ca1-9b58-6837e2907e35}</UniqueIdentifier> 55 <UniqueIdentifier>{c62af5d9-9161-4ca1-9b58-6837e2907e35}</UniqueIdentifier>
56 </Filter> 56 </Filter>
57 <Filter Include="Scripts\misc">
58 <UniqueIdentifier>{1fbb1341-2f93-4eaa-924c-1df79e083704}</UniqueIdentifier>
59 </Filter>
57 </ItemGroup> 60 </ItemGroup>
58 <ItemGroup> 61 <ItemGroup>
59 <None Include="scripts\linda\send_receive.lua"> 62 <None Include="scripts\linda\send_receive.lua">
@@ -95,7 +98,7 @@
95 <None Include="scripts\lane\tasking_join_test.lua"> 98 <None Include="scripts\lane\tasking_join_test.lua">
96 <Filter>Scripts\lane</Filter> 99 <Filter>Scripts\lane</Filter>
97 </None> 100 </None>
98 <None Include="scripts\coro\basics.lua"> 101 <None Include="scripts\coro\index_suspended.lua">
99 <Filter>Scripts\coro</Filter> 102 <Filter>Scripts\coro</Filter>
100 </None> 103 </None>
101 <None Include="scripts\coro\error_handling.lua"> 104 <None Include="scripts\coro\error_handling.lua">
@@ -119,5 +122,38 @@
119 <None Include="scripts\linda\wake_period.lua"> 122 <None Include="scripts\linda\wake_period.lua">
120 <Filter>Scripts\linda</Filter> 123 <Filter>Scripts\linda</Filter>
121 </None> 124 </None>
125 <None Include="scripts\coro\collect_yielded_lane.lua">
126 <Filter>Scripts\coro</Filter>
127 </None>
128 <None Include="scripts\lane\body_is_a_c_function.lua">
129 <Filter>Scripts\lane</Filter>
130 </None>
131 <None Include="scripts\coro\regular_function.lua">
132 <Filter>Scripts\coro</Filter>
133 </None>
134 <None Include="scripts\coro\yielding_in_non_coro_errors.lua">
135 <Filter>Scripts\coro</Filter>
136 </None>
137 <None Include="scripts\coro\resume_basics.lua">
138 <Filter>Scripts\coro</Filter>
139 </None>
140 <None Include="scripts\coro\join_suspended.lua">
141 <Filter>Scripts\coro</Filter>
142 </None>
143 <None Include="scripts\_utils54.lua">
144 <Filter>Scripts</Filter>
145 </None>
146 <None Include="scripts\coro\linda_in_close_handler.lua">
147 <Filter>Scripts\coro</Filter>
148 </None>
149 <None Include="scripts\coro\cancelling_suspended.lua">
150 <Filter>Scripts\coro</Filter>
151 </None>
152 <None Include="scripts\linda\send_receive_func_and_string.lua">
153 <Filter>Scripts\linda</Filter>
154 </None>
155 <None Include="scripts\misc\deeptest.lua">
156 <Filter>Scripts\misc</Filter>
157 </None>
122 </ItemGroup> 158 </ItemGroup>
123</Project> \ No newline at end of file 159</Project> \ No newline at end of file
diff --git a/unit_tests/deep_tests.cpp b/unit_tests/deep_tests.cpp
index e21072c..f18ff81 100644
--- a/unit_tests/deep_tests.cpp
+++ b/unit_tests/deep_tests.cpp
@@ -92,4 +92,13 @@ TEST_CASE("misc.deep_userdata.example")
92 " assert(due.get_deep_count() == 0)" 92 " assert(due.get_deep_count() == 0)"
93 ); 93 );
94 } 94 }
95} \ No newline at end of file 95}
96
97#define MAKE_TEST_CASE(DIR, FILE, CONDITION) \
98 TEST_CASE("scripted_tests." #DIR "." #FILE) \
99 { \
100 FileRunner _runner(R"(.\unit_tests\scripts)"); \
101 _runner.performTest(FileRunnerParam{ #DIR "/" #FILE, TestType::CONDITION }); \
102 }
103
104MAKE_TEST_CASE(misc, deeptest, AssertNoLuaError)
diff --git a/unit_tests/embedded_tests.cpp b/unit_tests/embedded_tests.cpp
index 04a8f87..388548d 100644
--- a/unit_tests/embedded_tests.cpp
+++ b/unit_tests/embedded_tests.cpp
@@ -139,13 +139,13 @@ namespace
139 139
140// ################################################################################################# 140// #################################################################################################
141 141
142TEST_CASE("lanes.embedding.with default allocator") 142TEST_CASE("lanes.embedding.with_default_allocator")
143{ 143{
144 local::EmbeddedLuaState S; 144 local::EmbeddedLuaState S;
145 145
146 // --------------------------------------------------------------------------------------------- 146 // ---------------------------------------------------------------------------------------------
147 147
148 SECTION("single state") 148 SECTION("single_state")
149 { 149 {
150 // this sends data in a linda. current contents: 150 // this sends data in a linda. current contents:
151 // key: short string 151 // key: short string
@@ -172,7 +172,7 @@ TEST_CASE("lanes.embedding.with default allocator")
172 172
173 // --------------------------------------------------------------------------------------------- 173 // ---------------------------------------------------------------------------------------------
174 174
175 SECTION("manual registration") 175 SECTION("manual_registration")
176 { 176 {
177 S.requireSuccess("require 'lanes'.configure{with_timers = false}"); 177 S.requireSuccess("require 'lanes'.configure{with_timers = false}");
178 178
@@ -192,7 +192,7 @@ TEST_CASE("lanes.embedding.with default allocator")
192 192
193 // try again after manual registration 193 // try again after manual registration
194 lua_pushcfunction(S, S.get_lanes_register()); // S: lanes_register 194 lua_pushcfunction(S, S.get_lanes_register()); // S: lanes_register
195 luaG_pushstring(S, LUA_IOLIBNAME); // S: lanes_register "io" 195 luaW_pushstring(S, LUA_IOLIBNAME); // S: lanes_register "io"
196 luaL_requiref(S, LUA_IOLIBNAME, luaopen_io, 1); // S: lanes_register "io" io 196 luaL_requiref(S, LUA_IOLIBNAME, luaopen_io, 1); // S: lanes_register "io" io
197 lua_call(S, 2, 0); // S: 197 lua_call(S, 2, 0); // S:
198 S.stackCheck(0); 198 S.stackCheck(0);
@@ -204,7 +204,7 @@ TEST_CASE("lanes.embedding.with default allocator")
204 204
205// this is not really a test yet, just something sitting here until it is converted properly 205// this is not really a test yet, just something sitting here until it is converted properly
206// currently it crashes with moonjit (but maybe I just need a more recent moonjit version) 206// currently it crashes with moonjit (but maybe I just need a more recent moonjit version)
207TEST_CASE("lanes.embedding.with custom allocator") 207TEST_CASE("lanes.embedding.with_custom_allocator")
208{ 208{
209 static constexpr auto logPrint = +[](lua_State* L) { 209 static constexpr auto logPrint = +[](lua_State* L) {
210 lua_getglobal(L, "ID"); // ID 210 lua_getglobal(L, "ID"); // ID
@@ -220,7 +220,7 @@ TEST_CASE("lanes.embedding.with custom allocator")
220 220
221 static constexpr auto launch_lane = +[](lua_CFunction on_state_create_, int id_, int n_) { 221 static constexpr auto launch_lane = +[](lua_CFunction on_state_create_, int id_, int n_) {
222 char script[500]; 222 char script[500];
223 lua_State* L = lua_newstate(local::allocf, nullptr); 223 lua_State* L = luaW_newstate(local::allocf, nullptr, luaL_makeseed(nullptr));
224 // _G.ID = id_ 224 // _G.ID = id_
225 luaL_openlibs(L); 225 luaL_openlibs(L);
226 luaL_dostring(L, "lanes = require 'lanes'"); 226 luaL_dostring(L, "lanes = require 'lanes'");
diff --git a/unit_tests/init_and_shutdown.cpp b/unit_tests/init_and_shutdown.cpp
index bd72157..69e4f1b 100644
--- a/unit_tests/init_and_shutdown.cpp
+++ b/unit_tests/init_and_shutdown.cpp
@@ -3,7 +3,7 @@
3 3
4// ################################################################################################# 4// #################################################################################################
5 5
6TEST_CASE("lanes.require 'lanes'") 6TEST_CASE("Lua.require_lanes")
7{ 7{
8 LuaState L{ LuaState::WithBaseLibs{ false }, LuaState::WithFixture{ false } }; 8 LuaState L{ LuaState::WithBaseLibs{ false }, LuaState::WithFixture{ false } };
9 9
@@ -58,7 +58,7 @@ TEST_CASE("lanes.require 'lanes'")
58// ################################################################################################# 58// #################################################################################################
59 59
60// allocator should be "protected", a C function returning a suitable userdata, or nil 60// allocator should be "protected", a C function returning a suitable userdata, or nil
61TEST_CASE("lanes.configure.allocator") 61TEST_CASE("lanes.configure.allocator/bool_number_table_string")
62{ 62{
63 LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; 63 LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
64 64
@@ -90,49 +90,33 @@ TEST_CASE("lanes.configure.allocator")
90 90
91 // --------------------------------------------------------------------------------------------- 91 // ---------------------------------------------------------------------------------------------
92 92
93 SECTION("allocator = <Lua function>")
94 {
95 L.requireFailure("require 'lanes'.configure{allocator = function() return {}, 12, 'yoy' end}");
96 }
97
98 // ---------------------------------------------------------------------------------------------
99
100 SECTION("allocator = <bad C function>")
101 {
102 // a C function that doesn't return what we expect should cause an error too
103 // TODO: for some reason, we use os.getenv here because using 'print' as the culprit, the tests deadlock in Release builds
104 L.requireFailure("return type(require 'lanes'.configure{allocator = os.getenv})");
105 }
106
107 // ---------------------------------------------------------------------------------------------
108
109 SECTION("allocator = <string with a typo>") 93 SECTION("allocator = <string with a typo>")
110 { 94 {
111 // oops, a typo 95 // oops, a typo
112 L.requireFailure("require 'lanes'.configure{allocator = 'Protected'}"); 96 L.requireFailure("require 'lanes'.configure{allocator = 'Protected'}");
113 } 97 }
98}
99
100// #################################################################################################
101
102TEST_CASE("lanes.configure.allocator/bad_functions")
103{
104 LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
114 105
115 // --------------------------------------------------------------------------------------------- 106 // ---------------------------------------------------------------------------------------------
116 107
117 SECTION("allocator = 'protected'") 108 SECTION("allocator = <Lua function>")
118 { 109 {
119 // no typo, should work 110 L.requireFailure("require 'lanes'.configure{allocator = function() return {}, 12, 'yoy' end}");
120 L.requireSuccess("require 'lanes'.configure{allocator = 'protected'}");
121 } 111 }
122 112
123 // --------------------------------------------------------------------------------------------- 113 // ---------------------------------------------------------------------------------------------
124 114
125 SECTION("allocator = <good custom C allocator>") 115 SECTION("allocator = <bad C function>")
126 { 116 {
127 // a function that provides what we expect is fine 117 // a C function that doesn't return what we expect should cause an error too
128 static constexpr lua_CFunction _provideAllocator = +[](lua_State* const L_) { 118 // TODO: for some reason, we use os.getenv here because using 'print' as the culprit, the tests deadlock in Release builds
129 lanes::AllocatorDefinition* const _def{ new (L_) lanes::AllocatorDefinition{} }; 119 L.requireFailure("return type(require 'lanes'.configure{allocator = os.getenv})");
130 _def->initFrom(L_);
131 return 1;
132 };
133 lua_pushcfunction(L, _provideAllocator);
134 lua_setglobal(L, "ProvideAllocator");
135 L.requireSuccess("require 'lanes'.configure{allocator = ProvideAllocator}");
136 } 120 }
137 121
138 // --------------------------------------------------------------------------------------------- 122 // ---------------------------------------------------------------------------------------------
@@ -191,6 +175,39 @@ TEST_CASE("lanes.configure.allocator")
191 175
192// ################################################################################################# 176// #################################################################################################
193 177
178TEST_CASE("lanes.configure.allocator/good_function")
179{
180 LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
181
182 SECTION("allocator = <good custom C allocator>")
183 {
184 // a function that provides what we expect is fine
185 static constexpr lua_CFunction _provideAllocator = +[](lua_State* const L_) {
186 lanes::AllocatorDefinition* const _def{ new (L_) lanes::AllocatorDefinition{} };
187 _def->initFrom(L_);
188 return 1;
189 };
190 lua_pushcfunction(L, _provideAllocator);
191 lua_setglobal(L, "ProvideAllocator");
192 L.requireSuccess("require 'lanes'.configure{allocator = ProvideAllocator}");
193 }
194}
195
196// #################################################################################################
197
198// TODO: investigate why this test crashes under AppVerifier on lanes_core.dll unload when running against Lua 5.1, 5.2 and 5.4 RELEASE ONLY!
199// apparently, the mutex of ProtectedAllocator is deemed still in use. Crash goes away if I don't use it in protected_lua_Alloc
200TEST_CASE(("lanes.configure.allocator/protected"))
201{
202 LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
203
204 // no typo, should work
205 L.requireSuccess("require 'lanes'.configure{allocator = 'protected'}");
206}
207
208
209// #################################################################################################
210
194TEST_CASE("lanes.configure.internal_allocator") 211TEST_CASE("lanes.configure.internal_allocator")
195{ 212{
196 LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; 213 LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
@@ -401,7 +418,7 @@ TEST_CASE("lanes.configure.nb_user_keepers")
401 418
402// ################################################################################################# 419// #################################################################################################
403 420
404TEST_CASE("lanes.configure.on_state_create") 421TEST_CASE("lanes.configure.on_state_create/configuration")
405{ 422{
406 LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; 423 LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
407 424
@@ -758,7 +775,7 @@ TEST_CASE("lanes.configure.unknown_setting")
758 775
759#if LUAJIT_FLAVOR() == 0 776#if LUAJIT_FLAVOR() == 0
760// TODO: this test crashes inside S.close() against LuaJIT. to be investigated 777// TODO: this test crashes inside S.close() against LuaJIT. to be investigated
761TEST_CASE("lanes.finally.no fixture") 778TEST_CASE("lanes.finally.no_fixture")
762{ 779{
763 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; 780 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
764 // we need Lanes to be up. Since we run several 'scripts', we store it as a global 781 // we need Lanes to be up. Since we run several 'scripts', we store it as a global
@@ -779,7 +796,7 @@ TEST_CASE("lanes.finally.no fixture")
779 796
780// ################################################################################################# 797// #################################################################################################
781 798
782TEST_CASE("lanes.finally.with fixture") 799TEST_CASE("lanes.finally.with_fixture")
783{ 800{
784 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; 801 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } };
785 802
@@ -797,7 +814,7 @@ TEST_CASE("lanes.finally.with fixture")
797 814
798// ################################################################################################# 815// #################################################################################################
799 816
800TEST_CASE("lanes.finally.shutdown with an uncooperative lane") 817TEST_CASE("lanes.finally.shutdown_with_an_uncooperative_lane")
801{ 818{
802 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; 819 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } };
803 S.requireSuccess("lanes = require 'lanes'.configure()"); 820 S.requireSuccess("lanes = require 'lanes'.configure()");
@@ -846,7 +863,7 @@ namespace
846 863
847// ################################################################################################# 864// #################################################################################################
848 865
849TEST_CASE("lanes.on_state_create setting") 866TEST_CASE("lanes.configure.on_state_create/details")
850{ 867{
851 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; 868 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
852 869
diff --git a/unit_tests/lane_tests.cpp b/unit_tests/lane_tests.cpp
index 1367ae5..b6fb188 100644
--- a/unit_tests/lane_tests.cpp
+++ b/unit_tests/lane_tests.cpp
@@ -1,5 +1,7 @@
1#include "_pch.hpp" 1#include "_pch.hpp"
2
2#include "shared.h" 3#include "shared.h"
4#include "lanes/src/threading.hpp"
3 5
4// ################################################################################################# 6// #################################################################################################
5// ################################################################################################# 7// #################################################################################################
@@ -33,7 +35,77 @@ TEST_CASE("lanes.nameof")
33// ################################################################################################# 35// #################################################################################################
34// ################################################################################################# 36// #################################################################################################
35 37
36TEST_CASE("lanes.sleep.argument validation") 38TEST_CASE("lanes.thread_priority_range")
39{
40 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
41 S.requireSuccess("lanes = require 'lanes'.configure()");
42
43 S.requireSuccess("a, b = lanes.thread_priority_range(); print(a, b)");
44 S.requireSuccess("assert(type(a) == 'number' and type(b) == 'number' and b > a)");
45 S.requireSuccess("c, d = lanes.thread_priority_range('native'); print(c, d)");
46 S.requireSuccess("assert(type(c) == 'number' and type(d) == 'number' and d > c)");
47
48 // can't really test the range of values from pthread as they are platform-dependent
49 if constexpr (THREADAPI == THREADAPI_WINDOWS) {
50 // windows constants THREAD_PRIORITY_IDLE and THREAD_PRIORITY_TIME_CRITICAL
51 S.requireSuccess("assert(c == -15 and d == 15)");
52 }
53}
54
55// #################################################################################################
56// #################################################################################################
57
58TEST_CASE("lanes.set_thread_priority")
59{
60 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
61 S.requireSuccess("lanes = require 'lanes'.configure()");
62
63 SECTION("mapped priorities")
64 {
65 std::string_view const _script{
66 " min_prio, max_prio = lanes.thread_priority_range()"
67 " for prio = min_prio, max_prio do"
68 " lanes.set_thread_priority(prio)"
69 " end"
70 };
71 S.requireSuccess(_script);
72
73 S.requireFailure("lanes.set_thread_priority(min_prio - 1)");
74 S.requireFailure("lanes.set_thread_priority(max_prio + 1)");
75 }
76
77 SECTION("native priorities")
78 {
79 S.requireSuccess("min_prio, max_prio = lanes.thread_priority_range('native')");
80 if constexpr (THREADAPI == THREADAPI_WINDOWS) {
81 // Win32 range is -15 to 15, but only some values are accepted
82 S.requireSuccess("lanes.set_thread_priority(-15, 'native')"); // THREAD_PRIORITY_IDLE
83 S.requireFailure("lanes.set_thread_priority(-3, 'native')");
84 S.requireSuccess("lanes.set_thread_priority(-2, 'native')"); // THREAD_PRIORITY_LOWEST
85 S.requireSuccess("lanes.set_thread_priority(-1, 'native')"); // THREAD_PRIORITY_BELOW_NORMAL
86 S.requireSuccess("lanes.set_thread_priority(0, 'native')"); // THREAD_PRIORITY_NORMAL
87 S.requireSuccess("lanes.set_thread_priority(1, 'native')"); // THREAD_PRIORITY_ABOVE_NORMAL
88 S.requireSuccess("lanes.set_thread_priority(2, 'native')"); // THREAD_PRIORITY_HIGHEST
89 S.requireFailure("lanes.set_thread_priority(3, 'native')");
90 S.requireSuccess("lanes.set_thread_priority(-15, 'native')"); // THREAD_PRIORITY_TIME_CRITICAL
91 } else {
92 // until proven otherwise, the full set of values is supported by pthread
93 std::string_view const _script{
94 " for prio = min_prio, max_prio do"
95 " lanes.set_thread_priority(prio, 'native')"
96 " end"
97 };
98 S.requireSuccess(_script);
99 }
100 S.requireFailure("lanes.set_thread_priority(min_prio - 1)");
101 S.requireFailure("lanes.set_thread_priority(max_prio + 1)");
102 }
103}
104
105// #################################################################################################
106// #################################################################################################
107
108TEST_CASE("lanes.sleep.argument_validation/not_numbers")
37{ 109{
38 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; 110 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
39 S.requireSuccess("lanes = require 'lanes'.configure()"); 111 S.requireSuccess("lanes = require 'lanes'.configure()");
@@ -44,6 +116,14 @@ TEST_CASE("lanes.sleep.argument validation")
44 S.requireFailure("lanes.sleep('a string')"); 116 S.requireFailure("lanes.sleep('a string')");
45 S.requireFailure("lanes.sleep(lanes.null)"); 117 S.requireFailure("lanes.sleep(lanes.null)");
46 S.requireFailure("lanes.sleep(print)"); 118 S.requireFailure("lanes.sleep(print)");
119}
120
121// #################################################################################################
122
123TEST_CASE("lanes.sleep.argument_validation/numbers")
124{
125 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
126 S.requireSuccess("lanes = require 'lanes'.configure()");
47 127
48 // negative durations are not supported 128 // negative durations are not supported
49 S.requireFailure("lanes.sleep(-1)"); 129 S.requireFailure("lanes.sleep(-1)");
@@ -97,88 +177,109 @@ TEST_CASE("lanes.sleep.interactions with timers")
97// ################################################################################################# 177// #################################################################################################
98// ################################################################################################# 178// #################################################################################################
99 179
100TEST_CASE("lanes.gen") 180TEST_CASE("lanes.gen.argument_checks")
101{ 181{
102 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; 182 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
103 S.requireSuccess("lanes = require 'lanes'.configure()"); 183 S.requireSuccess("lanes = require 'lanes'.configure()");
104 184
105 // --------------------------------------------------------------------------------------------- 185 // ---------------------------------------------------------------------------------------------
106 186
107 SECTION("argument checks") 187 // no argument is bad
108 { 188 S.requireFailure("lanes.gen()");
109 // no parameter is bad 189
110 S.requireFailure("lanes.gen()"); 190 // minimal generator needs a function
111 191 S.requireSuccess("lanes.gen(function() end)");
112 // minimal generator needs a function 192
113 S.requireSuccess("lanes.gen(function() end)"); 193 // acceptable arguments for the generator are strings, tables, nil, followed by the function body
114 194 S.requireSuccess("lanes.gen(nil, function() end)");
115 // acceptable parameters for the generator are strings, tables, nil, followed by the function body 195 S.requireSuccess("lanes.gen('', function() end)");
116 S.requireSuccess("lanes.gen(nil, function() end)"); 196 S.requireSuccess("lanes.gen({}, function() end)");
117 S.requireSuccess("lanes.gen('', function() end)"); 197 S.requireSuccess("lanes.gen('', {}, function() end)");
118 S.requireSuccess("lanes.gen({}, function() end)"); 198 S.requireSuccess("lanes.gen({}, '', function() end)");
119 S.requireSuccess("lanes.gen('', {}, function() end)"); 199 S.requireSuccess("lanes.gen('', '', function() end)");
120 S.requireSuccess("lanes.gen({}, '', function() end)"); 200 S.requireSuccess("lanes.gen({}, {}, function() end)");
121 S.requireSuccess("lanes.gen('', '', function() end)"); 201
122 S.requireSuccess("lanes.gen({}, {}, function() end)"); 202 // anything different should fail: booleans, numbers, any userdata
123 203 S.requireFailure("lanes.gen(false, function() end)");
124 // anything different should fail: booleans, numbers, any userdata 204 S.requireFailure("lanes.gen(true, function() end)");
125 S.requireFailure("lanes.gen(false, function() end)"); 205 S.requireFailure("lanes.gen(42, function() end)");
126 S.requireFailure("lanes.gen(true, function() end)"); 206 S.requireFailure("lanes.gen(io.stdin, function() end)");
127 S.requireFailure("lanes.gen(42, function() end)"); 207 S.requireFailure("lanes.gen(lanes.linda(), function() end)");
128 S.requireFailure("lanes.gen(io.stdin, function() end)"); 208 S.requireFailure("lanes.gen(lanes.linda():deep(), function() end)");
129 S.requireFailure("lanes.gen(lanes.linda(), function() end)"); 209
130 S.requireFailure("lanes.gen(lanes.linda():deep(), function() end)"); 210 // even if argument types are correct, the function must come last
131 211 S.requireFailure("lanes.gen(function() end, '')");
132 // even if parameter types are correct, the function must come last 212
133 S.requireFailure("lanes.gen(function() end, '')"); 213 // the strings should only list "known base libraries", in any order, or "*"
134 214 // if the particular Lua flavor we build for doesn't support them, they raise an error unless postfixed by '?'
135 // the strings should only list "known base libraries", in any order, or "*" 215 S.requireSuccess("lanes.gen('base', function() end)");
136 // if the particular Lua flavor we build for doesn't support them, they raise an error unless postfixed by '?' 216
137 S.requireSuccess("lanes.gen('base', function() end)"); 217 // bit, ffi, jit are LuaJIT-specific
138
139 // bit, ffi, jit are LuaJIT-specific
140#if LUAJIT_FLAVOR() == 0 218#if LUAJIT_FLAVOR() == 0
141 S.requireFailure("lanes.gen('bit,ffi,jit', function() end)"); 219 S.requireFailure("lanes.gen('bit,ffi,jit', function() end)");
142 S.requireSuccess("lanes.gen('bit?,ffi?,jit?', function() end)"); 220 S.requireSuccess("lanes.gen('bit?,ffi?,jit?', function() end)");
143#endif // LUAJIT_FLAVOR() 221#endif // LUAJIT_FLAVOR()
144 222
145 // bit32 library existed only in Lua 5.2, there is still a loader that will raise an error in Lua 5.3 223 // bit32 library existed only in Lua 5.2, there is still a loader that will raise an error in Lua 5.3
146#if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 224#if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
147 S.requireSuccess("lanes.gen('bit32', function() end)"); 225 S.requireSuccess("lanes.gen('bit32', function() end)");
148#else // LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 226#else // LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
149 S.requireFailure("lanes.gen('bit32', function() end)"); 227 S.requireFailure("lanes.gen('bit32', function() end)");
150 S.requireSuccess("lanes.gen('bit32?', function() end)"); 228 S.requireSuccess("lanes.gen('bit32?', function() end)");
151#endif // LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 229#endif // LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503
152 230
153 // coroutine library appeared with Lua 5.2 231 // coroutine library appeared with Lua 5.2
154#if LUA_VERSION_NUM == 501 232#if LUA_VERSION_NUM == 501
155 S.requireFailure("lanes.gen('coroutine', function() end)"); 233 S.requireFailure("lanes.gen('coroutine', function() end)");
156 S.requireSuccess("lanes.gen('coroutine?', function() end)"); 234 S.requireSuccess("lanes.gen('coroutine?', function() end)");
157#endif // LUA_VERSION_NUM == 501 235#endif // LUA_VERSION_NUM == 501
158 236
159 S.requireSuccess("lanes.gen('debug', function() end)"); 237 S.requireSuccess("lanes.gen('debug', function() end)");
160 S.requireSuccess("lanes.gen('io', function() end)"); 238 S.requireSuccess("lanes.gen('io', function() end)");
161 S.requireSuccess("lanes.gen('math', function() end)"); 239 S.requireSuccess("lanes.gen('math', function() end)");
162 S.requireSuccess("lanes.gen('os', function() end)"); 240 S.requireSuccess("lanes.gen('os', function() end)");
163 S.requireSuccess("lanes.gen('package', function() end)"); 241 S.requireSuccess("lanes.gen('package', function() end)");
164 S.requireSuccess("lanes.gen('string', function() end)"); 242 S.requireSuccess("lanes.gen('string', function() end)");
165 S.requireSuccess("lanes.gen('table', function() end)"); 243 S.requireSuccess("lanes.gen('table', function() end)");
166 244
167 // utf8 library appeared with Lua 5.3 245 // utf8 library appeared with Lua 5.3
168#if LUA_VERSION_NUM < 503 246#if LUA_VERSION_NUM < 503
169 S.requireFailure("lanes.gen('utf8', function() end)"); 247 S.requireFailure("lanes.gen('utf8', function() end)");
170 S.requireSuccess("lanes.gen('utf8?', function() end)"); 248 S.requireSuccess("lanes.gen('utf8?', function() end)");
171#endif // LUA_VERSION_NUM < 503 249#endif // LUA_VERSION_NUM < 503
172 250
173 S.requireSuccess("lanes.gen('lanes_core', function() end)"); 251 S.requireSuccess("lanes.gen('lanes_core', function() end)");
174 // "*" repeated or combined with anything else is forbidden 252 // "*" repeated or combined with anything else is forbidden
175 S.requireFailure("lanes.gen('*', '*', function() end)"); 253 S.requireFailure("lanes.gen('*', '*', function() end)");
176 S.requireFailure("lanes.gen('base', '*', function() end)"); 254 S.requireFailure("lanes.gen('base', '*', function() end)");
177 // unknown names are forbidden 255 // unknown names are forbidden
178 S.requireFailure("lanes.gen('Base', function() end)"); 256 S.requireFailure("lanes.gen('Base', function() end)");
179 // repeating the same library more than once is forbidden 257 // repeating the same library more than once is forbidden
180 S.requireFailure("lanes.gen('base,base', function() end)"); 258 S.requireFailure("lanes.gen('base,base', function() end)");
181 } 259}
260
261// #################################################################################################
262// #################################################################################################
263
264TEST_CASE("lanes.gen.priority")
265{
266 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
267 S.requireSuccess("lanes = require 'lanes'.configure()");
268
269 S.requireSuccess("lanes.gen({priority=1}, function() end)");
270 // AFAICT, 1 is accepted by all pthread flavors and win32 API
271 S.requireSuccess("lanes.gen({native_priority=1}, function() end)");
272 // shouldn't be able to provide 2 priority settings
273 S.requireFailure("lanes.gen({priority=1, native_priority=1}, function() end)");
274}
275
276// #################################################################################################
277// #################################################################################################
278
279TEST_CASE("lanes.gen.thread_naming")
280{
281 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
282 S.requireSuccess("lanes = require 'lanes'.configure()");
182 283
183 // --------------------------------------------------------------------------------------------- 284 // ---------------------------------------------------------------------------------------------
184 285
@@ -319,18 +420,22 @@ TEST_CASE("lane.cancel")
319// unfortunately, VS Test adapter does not list individual sections, 420// unfortunately, VS Test adapter does not list individual sections,
320// so let's create a separate test case for each file with an ugly macro... 421// so let's create a separate test case for each file with an ugly macro...
321 422
322#define MAKE_TEST_CASE(DIR, FILE, CONDITION)\ 423#define MAKE_TEST_CASE(DIR, FILE, CONDITION) \
323TEST_CASE("scripted_tests." #DIR "." #FILE) \ 424TEST_CASE("scripted_tests." #DIR "." #FILE) \
324{ \ 425{ \
325 FileRunner _runner(R"(.\unit_tests\scripts)"); \ 426 FileRunner _runner(R"(.\unit_tests\scripts)"); \
326 _runner.performTest(FileRunnerParam{ #DIR "/" #FILE, TestType::CONDITION }); \ 427 _runner.performTest(FileRunnerParam{ #DIR "/" #FILE, TestType::CONDITION }); \
327} 428}
328 429
329MAKE_TEST_CASE(lane, cooperative_shutdown, AssertNoLuaError) 430#if LUA_VERSION_NUM >= 504 // this makes use of to-be-closed variables, a Lua 5.4 feature
330#if LUA_VERSION_NUM >= 504 // // warnings are a Lua 5.4 feature 431#define MAKE_TEST_CASE_54(DIR, FILE, CONDITION) MAKE_TEST_CASE(DIR, FILE, CONDITION)
331// NOTE: when this test ends, there are resource leaks and a dangling thread 432#else // LUA_VERSION_NUM
332MAKE_TEST_CASE(lane, uncooperative_shutdown, AssertWarns) 433#define MAKE_TEST_CASE_54(DIR, FILE, CONDITION)
333#endif // LUA_VERSION_NUM 434#endif // LUA_VERSION_NUM
435
436MAKE_TEST_CASE(lane, body_is_a_c_function, AssertNoLuaError)
437MAKE_TEST_CASE(lane, cooperative_shutdown, AssertNoLuaError)
438MAKE_TEST_CASE_54(lane, uncooperative_shutdown, AssertWarns) // NOTE: when this test ends, there are resource leaks and a dangling thread
334MAKE_TEST_CASE(lane, tasking_basic, AssertNoLuaError) 439MAKE_TEST_CASE(lane, tasking_basic, AssertNoLuaError)
335MAKE_TEST_CASE(lane, tasking_cancelling_with_hook, AssertNoLuaError) 440MAKE_TEST_CASE(lane, tasking_cancelling_with_hook, AssertNoLuaError)
336MAKE_TEST_CASE(lane, tasking_cancelling, AssertNoLuaError) 441MAKE_TEST_CASE(lane, tasking_cancelling, AssertNoLuaError)
@@ -340,11 +445,18 @@ MAKE_TEST_CASE(lane, tasking_error, AssertNoLuaError)
340MAKE_TEST_CASE(lane, tasking_join_test, AssertNoLuaError) 445MAKE_TEST_CASE(lane, tasking_join_test, AssertNoLuaError)
341MAKE_TEST_CASE(lane, tasking_send_receive_code, AssertNoLuaError) 446MAKE_TEST_CASE(lane, tasking_send_receive_code, AssertNoLuaError)
342MAKE_TEST_CASE(lane, stdlib_naming, AssertNoLuaError) 447MAKE_TEST_CASE(lane, stdlib_naming, AssertNoLuaError)
343MAKE_TEST_CASE(coro, basics, AssertNoLuaError) 448MAKE_TEST_CASE(coro, cancelling_suspended, AssertNoLuaError)
449MAKE_TEST_CASE_54(coro, collect_yielded_lane, AssertNoLuaError)
344#if LUAJIT_FLAVOR() == 0 450#if LUAJIT_FLAVOR() == 0
345// TODO: for some reason, the test fails with LuaJIT. To be investigated 451// TODO: for some reason, the test fails with LuaJIT. To be investigated
346MAKE_TEST_CASE(coro, error_handling, AssertNoLuaError) 452MAKE_TEST_CASE(coro, error_handling, AssertNoLuaError)
347#endif // LUAJIT_FLAVOR() 453#endif // LUAJIT_FLAVOR()
454MAKE_TEST_CASE(coro, index_suspended, AssertNoLuaError)
455MAKE_TEST_CASE(coro, join_suspended, AssertNoLuaError)
456MAKE_TEST_CASE_54(coro, linda_in_close_handler, AssertNoLuaError)
457MAKE_TEST_CASE(coro, regular_function, AssertNoLuaError)
458MAKE_TEST_CASE(coro, resume_basics, AssertNoLuaError)
459MAKE_TEST_CASE(coro, yielding_in_non_coro_errors, AssertNoLuaError)
348 460
349/* 461/*
350TEST_CASE("lanes.scripted_tests") 462TEST_CASE("lanes.scripted_tests")
diff --git a/unit_tests/linda_tests.cpp b/unit_tests/linda_tests.cpp
index d956ae2..90630a7 100644
--- a/unit_tests/linda_tests.cpp
+++ b/unit_tests/linda_tests.cpp
@@ -35,7 +35,7 @@ TEST_CASE("linda.single_keeper.creation/close_handler")
35 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; 35 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } };
36 S.requireSuccess("lanes = require 'lanes'"); 36 S.requireSuccess("lanes = require 'lanes'");
37 37
38 if constexpr (LUA_VERSION_NUM == 504) { 38 if constexpr (LUA_VERSION_NUM >= 504) {
39 // a function is acceptable as a __close handler 39 // a function is acceptable as a __close handler
40 S.requireSuccess("local l <close> = lanes.linda{close_handler = function() end}"); 40 S.requireSuccess("local l <close> = lanes.linda{close_handler = function() end}");
41 // a callable table too (a callable full userdata as well, but I have none here) 41 // a callable table too (a callable full userdata as well, but I have none here)
@@ -109,103 +109,110 @@ TEST_CASE("linda.single_keeper.creation/wake_period")
109 109
110// ################################################################################################# 110// #################################################################################################
111 111
112TEST_CASE("linda.single_keeper.the_rest") 112TEST_CASE("linda.single_keeper.indexing")
113{ 113{
114 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; 114 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } };
115 S.requireSuccess("lanes = require 'lanes'"); 115 S.requireSuccess("lanes = require 'lanes'.configure()");
116
117 // indexing the linda with an unknown string key should fail
118 S.requireFailure("return lanes.linda().gouikra");
119 // indexing the linda with an unsupported key type should fail
120 S.requireFailure("return lanes.linda()[5]");
121 S.requireFailure("return lanes.linda()[false]");
122 S.requireFailure("return lanes.linda()[{}]");
123 S.requireFailure("return lanes.linda()[function() end]");
124}
116 125
117 // --------------------------------------------------------------------------------------------- 126// #################################################################################################
118 127
119 SECTION("error in close handler is propagated") 128TEST_CASE("linda.single_keeper.send()")
129{
130 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } };
131 S.requireSuccess("lanes = require 'lanes'.configure()");
132
133 SECTION("timeout")
120 { 134 {
121 // if the function raises an error, we should get it 135 // timeout checks
122 S.requireFailure("local l <close> = lanes.linda{close_handler = function() error 'gluh' end}"); 136 // linda:send() should fail if the timeout is bad
137 S.requireFailure("lanes.linda():send(-1, 'k', 'v')");
138 // any positive value is ok
139 S.requireSuccess("lanes.linda():send(0, 'k', 'v')");
140 S.requireSuccess("lanes.linda():send(1e20, 'k', 'v')");
141 // nil too (same as 'forever')
142 S.requireSuccess("lanes.linda():send(nil, 'k', 'v')");
123 } 143 }
124 144
125 // --------------------------------------------------------------------------------------------- 145 // -----------------------------------------------------------------------------------------
126 146
127 SECTION("Linda indexing") 147 SECTION("fails on bad keys")
128 { 148 {
129 // indexing the linda with an unknown string key should fail 149 // key checks
130 S.requireFailure("return lanes.linda().gouikra"); 150 // linda:send() should fail if the key is unsupported (nil, table, function, full userdata, reserved light userdata)
131 // indexing the linda with an unsupported key type should fail 151 S.requireFailure("lanes.linda():send(0, nil, 'v')");
132 S.requireFailure("return lanes.linda()[5]"); 152 S.requireFailure("lanes.linda():send(0, {}, 'v')");
133 S.requireFailure("return lanes.linda()[false]"); 153 S.requireFailure("lanes.linda():send(0, function() end, 'v')");
134 S.requireFailure("return lanes.linda()[{}]"); 154 S.requireFailure("lanes.linda():send(0, io.stdin, 'v')");
135 S.requireFailure("return lanes.linda()[function() end]"); 155 S.requireFailure("lanes.linda():send(0, lanes.null, 'v')");
156 S.requireFailure("lanes.linda():send(0, lanes.cancel_error, 'v')");
136 } 157 }
137 158
138 // --------------------------------------------------------------------------------------------- 159 // -----------------------------------------------------------------------------------------
139 SECTION("linda:send()") 160
161 SECTION("succeeds on supported keys")
140 { 162 {
141 SECTION("timeout") 163 // supported keys are ok: boolean, number, string, light userdata, deep userdata
142 { 164 S.requireSuccess("lanes.linda():send(0, true, 'v')");
143 // timeout checks 165 S.requireSuccess("lanes.linda():send(0, false, 'v')");
144 // linda:send() should fail if the timeout is bad 166 S.requireSuccess("lanes.linda():send(0, 99, 'v')");
145 S.requireFailure("lanes.linda():send(-1, 'k', 'v')"); 167 S.requireSuccess("local l = lanes.linda(); l:send(0, l:deep(), 'v')");
146 // any positive value is ok 168 }
147 S.requireSuccess("lanes.linda():send(0, 'k', 'v')");
148 S.requireSuccess("lanes.linda():send(1e20, 'k', 'v')");
149 // nil too (same as 'forever')
150 S.requireSuccess("lanes.linda():send(nil, 'k', 'v')");
151 }
152 169
153 // ----------------------------------------------------------------------------------------- 170 // -----------------------------------------------------------------------------------------
154 171
155 SECTION("fails on bad keys") 172 SECTION("succeeds on deep userdata key")
156 { 173 {
157 // key checks 174 S.requireSuccess("local l = lanes.linda(); l:send(0, l, 'v')");
158 // linda:send() should fail if the key is unsupported (nil, table, function, full userdata, reserved light userdata) 175 }
159 S.requireFailure("lanes.linda():send(0, nil, 'v')");
160 S.requireFailure("lanes.linda():send(0, {}, 'v')");
161 S.requireFailure("lanes.linda():send(0, function() end, 'v')");
162 S.requireFailure("lanes.linda():send(0, io.stdin, 'v')");
163 S.requireFailure("lanes.linda():send(0, lanes.null, 'v')");
164 S.requireFailure("lanes.linda():send(0, lanes.cancel_error, 'v')");
165 }
166 176
167 // ----------------------------------------------------------------------------------------- 177 // -----------------------------------------------------------------------------------------
168 178
169 SECTION("succeeds on supported keys") 179 SECTION(". fails")
170 { 180 {
171 // supported keys are ok: boolean, number, string, light userdata, deep userdata 181 // misuse checks, . instead of :
172 S.requireSuccess("lanes.linda():send(0, true, 'v')"); 182 S.requireFailure("lanes.linda().send(nil, 'k', 'v')");
173 S.requireSuccess("lanes.linda():send(0, false, 'v')"); 183 }
174 S.requireSuccess("lanes.linda():send(0, 99, 'v')");
175 S.requireSuccess("local l = lanes.linda(); l:send(0, l:deep(), 'v')");
176 }
177 184
178 // ----------------------------------------------------------------------------------------- 185 // -----------------------------------------------------------------------------------------
179 186
180 SECTION("succeeds on deep userdata key") 187 SECTION("unsupported values fail")
181 { 188 {
182 S.requireSuccess("local l = lanes.linda(); l:send(0, l, 'v')"); 189 // value checks
183 } 190 // linda:send() should fail if we don't send anything
191 S.requireFailure("lanes.linda():send()");
192 S.requireFailure("lanes.linda():send(0)");
193 S.requireFailure("lanes.linda():send(0, 'k')");
194 // or non-deep userdata
195 S.requireFailure("lanes.linda():send(0, 'k', fixture.newuserdata())");
196 // or something with a converter that raises an error (maybe that should go to a dedicated __lanesconvert test!)
197 S.requireFailure("lanes.linda():send(0, 'k', setmetatable({}, {__lanesconvert = function(where_) error (where_ .. ': should not send me' end}))");
198 // but a registered non-deep userdata should work
199 S.requireSuccess("lanes.linda():send(0, 'k', io.stdin)");
200 }
201}
184 202
185 // ----------------------------------------------------------------------------------------- 203// #################################################################################################
186 204
187 SECTION(". fails") 205TEST_CASE("linda.single_keeper.the_rest")
188 { 206{
189 // misuse checks, . instead of : 207 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } };
190 S.requireFailure("lanes.linda().send(nil, 'k', 'v')"); 208 S.requireSuccess("lanes = require 'lanes'");
191 }
192 209
193 // ----------------------------------------------------------------------------------------- 210 // ---------------------------------------------------------------------------------------------
194 211
195 SECTION("unsupported values fail") 212 SECTION("error in close handler is propagated")
196 { 213 {
197 // value checks 214 // if the function raises an error, we should get it
198 // linda:send() should fail if we don't send anything 215 S.requireFailure("local l <close> = lanes.linda{close_handler = function() error 'gluh' end}");
199 S.requireFailure("lanes.linda():send()");
200 S.requireFailure("lanes.linda():send(0)");
201 S.requireFailure("lanes.linda():send(0, 'k')");
202 // or non-deep userdata
203 S.requireFailure("lanes.linda():send(0, 'k', fixture.newuserdata())");
204 // or something with a converter that raises an error (maybe that should go to a dedicated __lanesconvert test!)
205 S.requireFailure("lanes.linda():send(0, 'k', setmetatable({}, {__lanesconvert = function(where_) error (where_ .. ': should not send me' end}))");
206 // but a registered non-deep userdata should work
207 S.requireSuccess("lanes.linda():send(0, 'k', io.stdin)");
208 }
209 } 216 }
210 217
211 // --------------------------------------------------------------------------------------------- 218 // ---------------------------------------------------------------------------------------------
@@ -390,6 +397,7 @@ TEST_CASE("scripted_tests." #DIR "." #FILE) \
390 397
391MAKE_TEST_CASE(linda, multiple_keepers) 398MAKE_TEST_CASE(linda, multiple_keepers)
392MAKE_TEST_CASE(linda, send_receive) 399MAKE_TEST_CASE(linda, send_receive)
400MAKE_TEST_CASE(linda, send_receive_func_and_string)
393MAKE_TEST_CASE(linda, send_registered_userdata) 401MAKE_TEST_CASE(linda, send_registered_userdata)
394MAKE_TEST_CASE(linda, wake_period) 402MAKE_TEST_CASE(linda, wake_period)
395 403
diff --git a/unit_tests/scripts/_utils.lua b/unit_tests/scripts/_utils.lua
index d710702..9f46237 100644
--- a/unit_tests/scripts/_utils.lua
+++ b/unit_tests/scripts/_utils.lua
@@ -68,8 +68,26 @@ local function dump_error_stack(error_reporting_mode_, stack)
68 end 68 end
69end 69end
70 70
71-- a function that yields back what got in, one element at a time
72local yield_one_by_one = function(...)
73 local PRINT = MAKE_PRINT()
74 PRINT "In lane"
75 for _i = 1, select('#', ...) do
76 local _val = select(_i, ...)
77 PRINT("yielding #", _i, _val)
78 local _ack = coroutine.yield(_val)
79 if cancel_test and cancel_test() then -- cancel_test does not exist when run immediately (not in a Lane)
80 return "cancelled!"
81 end
82 -- of course, if we are cancelled, we were not resumed, and yield() didn't return what we expect
83 assert(_ack == _i)
84 end
85 return "bye!"
86end
87
71return { 88return {
72 MAKE_PRINT = MAKE_PRINT, 89 MAKE_PRINT = MAKE_PRINT,
73 tables_match = tables_match, 90 tables_match = tables_match,
74 dump_error_stack = dump_error_stack 91 dump_error_stack = dump_error_stack,
92 yield_one_by_one = yield_one_by_one
75} 93}
diff --git a/unit_tests/scripts/_utils54.lua b/unit_tests/scripts/_utils54.lua
new file mode 100644
index 0000000..a511563
--- /dev/null
+++ b/unit_tests/scripts/_utils54.lua
@@ -0,0 +1,30 @@
1local utils = require "_utils"
2
3-- expand _utils module with Lua5.4 specific stuff
4
5-- a lane body that yields stuff
6utils.yielder_with_to_be_closed = function(out_linda_, wait_)
7 local fixture = assert(require "fixture")
8 -- here is a to-be-closed variable that, when closed, sends "Closed!" in the "out" slot of the provided linda
9 local t <close> = setmetatable(
10 { text = "Closed!" }, {
11 __close = function(self, err)
12 if wait_ then
13 fixture.block_for(wait_)
14 end
15 out_linda_:send("out", self.text)
16 end
17 }
18 )
19 -- yield forever, but be cancel-friendly
20 local n = 1
21 while true do
22 coroutine.yield("I yield!", n)
23 if cancel_test and cancel_test() then -- cancel_test does not exist when run immediately (not in a Lane)
24 return "I am cancelled"
25 end
26 n = n + 1
27 end
28end
29
30return utils
diff --git a/unit_tests/scripts/coro/basics.lua b/unit_tests/scripts/coro/basics.lua
deleted file mode 100644
index cd2f410..0000000
--- a/unit_tests/scripts/coro/basics.lua
+++ /dev/null
@@ -1,97 +0,0 @@
1local lanes = require "lanes"
2
3local fixture = require "fixture"
4lanes.finally(fixture.throwing_finalizer)
5
6local utils = lanes.require "_utils"
7local PRINT = utils.MAKE_PRINT()
8
9if true then
10 -- a lane body that just returns some value
11 local lane = function(msg_)
12 local utils = lanes.require "_utils"
13 local PRINT = utils.MAKE_PRINT()
14 PRINT "In lane"
15 assert(msg_ == "hi")
16 return "bye"
17 end
18
19 -- the generator
20 local g1 = lanes.coro("*", {name = "auto"}, lane)
21
22 -- launch lane
23 local h1 = g1("hi")
24
25 local r = h1[1]
26 assert(r == "bye")
27end
28
29-- a lane coroutine that yields back what got in, one element at a time
30local yielder = function(...)
31 local utils = lanes.require "_utils"
32 local PRINT = utils.MAKE_PRINT()
33 PRINT "In lane"
34 for _i = 1, select('#', ...) do
35 local _val = select(_i, ...)
36 PRINT("yielding #", _i, _val)
37 local _ack = coroutine.yield(_val)
38 assert(_ack == _i)
39 end
40 return "done!"
41end
42
43if true then
44 -- if we start a non-coroutine lane with a yielding function, we should get an error, right?
45 local fun_g = lanes.gen("*", { name = 'auto' }, yielder)
46 local h = fun_g("hello", "world", "!")
47 local err, status, stack = h:join()
48 PRINT(err, status, stack)
49 -- the actual error message is not the same for Lua 5.1
50 -- of course, it also has to be different for LuaJIT as well
51 -- also, LuaJIT prepends a file:line to the actual error message, which Lua5.1 does not.
52 local msgs = {
53 ["Lua 5.1"] = jit and "attempt to yield across C-call boundary" or "attempt to yield across metamethod/C-call boundary",
54 ["Lua 5.2"] = "attempt to yield from outside a coroutine",
55 ["Lua 5.3"] = "attempt to yield from outside a coroutine",
56 ["Lua 5.4"] = "attempt to yield from outside a coroutine"
57 }
58 local expected_msg = msgs[_VERSION]
59 PRINT("expected_msg = " .. expected_msg)
60 assert(err == nil and string.find(status, expected_msg, 1, true) and stack == nil, "status = " .. status)
61end
62
63-- the generator
64local coro_g = lanes.coro("*", {name = "auto"}, yielder)
65
66if true then
67 -- launch coroutine lane
68 local h2 = coro_g("hello", "world", "!")
69 -- read the yielded values, sending back the expected index
70 assert(h2:resume(1) == "hello")
71 assert(h2:resume(2) == "world")
72 assert(h2:resume(3) == "!")
73 -- the lane return value is available as usual
74 local r = h2[1]
75 assert(r == "done!")
76end
77
78if true then
79 -- another coroutine lane
80 local h3 = coro_g("hello", "world", "!")
81
82 -- yielded values are available as regular return values
83 assert(h3[1] == "hello" and h3.status == "suspended")
84 -- since we consumed the returned values, they should not be here when we resume
85 assert(h3:resume(1) == nil)
86
87 -- similarly, we can get them with join()
88 assert(h3:join() == "world" and h3.status == "suspended")
89 -- since we consumed the returned values, they should not be here when we resume
90 assert(h3:resume(2) == nil)
91
92 -- the rest should work as usual
93 assert(h3:resume(3) == "!")
94
95 -- the final return value of the lane body remains to be read
96 assert(h3:join() == "done!" and h3.status == "done")
97end
diff --git a/unit_tests/scripts/coro/cancelling_suspended.lua b/unit_tests/scripts/coro/cancelling_suspended.lua
new file mode 100644
index 0000000..3a29e55
--- /dev/null
+++ b/unit_tests/scripts/coro/cancelling_suspended.lua
@@ -0,0 +1,31 @@
1local fixture = require "fixture"
2local lanes = require "lanes".configure{on_state_create = fixture.on_state_create}
3
4local fixture = require "fixture"
5lanes.finally(fixture.throwing_finalizer)
6
7local utils = lanes.require "_utils"
8local PRINT = utils.MAKE_PRINT()
9
10--------------------------------------------------
11-- TEST: cancelling a suspended Lane should end it
12--------------------------------------------------
13if true then
14 -- the generator
15 local coro_g = lanes.coro("*", utils.yield_one_by_one)
16
17 -- start the lane
18 local h = coro_g("hello", "world", "!")
19 repeat until h.status == "suspended"
20
21 -- first cancellation attempt: don't wake the lane
22 local b, r = h:cancel("soft", 0.5)
23 -- the lane is still blocked in its suspended state
24 assert(b == false and r == "timeout" and h.status == "suspended", "got " .. tostring(b) .. " " .. tostring(r) .. " " .. h.status)
25
26 -- cancel the Lane again, this time waking it. it will resume, and yielder()'s will break out of its infinite loop
27 h:cancel("soft", nil, true)
28
29 -- lane should be done, because it returned cooperatively when detecting a soft cancel
30 assert(h.status == "done", "got " .. h.status)
31end
diff --git a/unit_tests/scripts/coro/collect_yielded_lane.lua b/unit_tests/scripts/coro/collect_yielded_lane.lua
new file mode 100644
index 0000000..2ee58f8
--- /dev/null
+++ b/unit_tests/scripts/coro/collect_yielded_lane.lua
@@ -0,0 +1,64 @@
1local fixture = require "fixture"
2local lanes = require "lanes".configure{on_state_create = fixture.on_state_create}
3
4local fixture = require "fixture"
5lanes.finally(fixture.throwing_finalizer)
6
7-- this test is only for Lua 5.4+
8local utils = lanes.require "_utils54"
9local PRINT = utils.MAKE_PRINT()
10
11local out_linda = lanes.linda()
12
13------------------------------------------------------------------------------
14-- TEST: to-be-closed variables are properly closed when the lane is collected
15------------------------------------------------------------------------------
16if true then
17 -- the generator
18 local coro_g = lanes.coro("*", utils.yielder_with_to_be_closed)
19
20 -- start the lane
21 local h = coro_g(out_linda)
22
23 -- join the lane. it should be done and give back the values resulting of the first yield point
24 local r, v1, v2 = h:join()
25 assert(r == true and v1 == "I yield!" and v2 == 1, "got " .. tostring(r) .. " " .. tostring(v1) .. " " .. tostring(v2))
26 assert(h.status == "done", "got " .. h.status)
27
28 -- force collection of the lane
29 h = nil
30 collectgarbage()
31
32 -- I want the to-be-closed variable of the coroutine linda to be properly closed
33 local s, r = out_linda:receive(0, "out")
34 assert(s == "out" and r == "Closed!", "coro got " .. tostring(s) .. " " .. tostring(r)) -- THIS TEST FAILS
35end
36
37---------------------------------------------------------------------------------------------------
38-- TEST: if a to-be-closed handler takes longer than the join timeout, everything works as expected
39---------------------------------------------------------------------------------------------------
40if true then
41 -- the generator
42 local coro_g = lanes.coro("*", utils.yielder_with_to_be_closed)
43
44 -- start the lane. The to-be-closed handler will sleep for 1 second
45 local h = coro_g(out_linda, 1)
46
47 -- first join attempt should timeout
48 local r, v = h:join(0.6)
49 assert(r == nil and v == "timeout", "got " .. tostring(r) .. " " .. tostring(v))
50 assert(h.status == "running", "got " .. h.status)
51
52 -- join the lane again. it should be done and give back the values resulting of the first yield point
53 local r, v1, v2 = h:join(0.6)
54 assert(r == true and v1 == "I yield!" and v2 == 1, "got " .. tostring(r) .. " " .. tostring(v1) .. " " .. tostring(v2))
55 assert(h.status == "done", "got " .. h.status)
56
57 -- force collection of the lane
58 h = nil
59 collectgarbage()
60
61 -- I want the to-be-closed variable of the coroutine linda to be properly closed
62 local s, r = out_linda:receive(0, "out")
63 assert(s == "out" and r == "Closed!", "coro got " .. tostring(s) .. " " .. tostring(r)) -- THIS TEST FAILS
64end
diff --git a/unit_tests/scripts/coro/error_handling.lua b/unit_tests/scripts/coro/error_handling.lua
index ba6cff6..1cfb8c8 100644
--- a/unit_tests/scripts/coro/error_handling.lua
+++ b/unit_tests/scripts/coro/error_handling.lua
@@ -38,15 +38,15 @@ local force_error_test = function(error_trace_level_)
38 utils.dump_error_stack(error_trace_level_, c) 38 utils.dump_error_stack(error_trace_level_, c)
39end 39end
40 40
41if false then 41if true then
42 force_error_test("minimal") 42 force_error_test("minimal")
43end 43end
44 44
45if false then 45if true then
46 force_error_test("basic") 46 force_error_test("basic")
47end 47end
48 48
49if false then 49if true then
50 force_error_test("extended") 50 force_error_test("extended")
51end 51end
52 52
diff --git a/unit_tests/scripts/coro/index_suspended.lua b/unit_tests/scripts/coro/index_suspended.lua
new file mode 100644
index 0000000..2cd8c28
--- /dev/null
+++ b/unit_tests/scripts/coro/index_suspended.lua
@@ -0,0 +1,28 @@
1local lanes = require "lanes"
2
3local fixture = require "fixture"
4lanes.finally(fixture.throwing_finalizer)
5
6local utils = lanes.require "_utils"
7local PRINT = utils.MAKE_PRINT()
8
9-- the coroutine generator
10local coro_g = lanes.coro("*", {name = "auto"}, utils.yield_one_by_one)
11
12-------------------------------------------------------------------------
13-- TEST: if we index a yielded lane, we should get the last yielded value
14-------------------------------------------------------------------------
15if true then
16 -- launch coroutine lane
17 local h = coro_g("hello", "world", "!")
18 -- read the first yielded value, sending back the expected index
19 assert(h:resume(1) == "hello")
20 -- indexing multiple times gives back the same us the same yielded value
21 local r1 = h[1]
22 local r2 = h[1]
23 local r3 = h[1]
24 assert(r1 == "world" and r2 == "world" and r3 == "world", "got " .. r1 .. " " .. r2 .. " " .. r3)
25 -- once the lane was indexed, it is no longer resumable (just like after join)
26 local b, e = pcall(h.resume, h, 2)
27 assert(b == false and e == "cannot resume non-suspended coroutine Lane")
28end
diff --git a/unit_tests/scripts/coro/join_suspended.lua b/unit_tests/scripts/coro/join_suspended.lua
new file mode 100644
index 0000000..33be406
--- /dev/null
+++ b/unit_tests/scripts/coro/join_suspended.lua
@@ -0,0 +1,24 @@
1local lanes = require "lanes"
2
3local fixture = require "fixture"
4lanes.finally(fixture.throwing_finalizer)
5
6local utils = lanes.require "_utils"
7local PRINT = utils.MAKE_PRINT()
8
9-- the coroutine generator
10local coro_g = lanes.coro("*", {name = "auto"}, utils.yield_one_by_one)
11
12---------------------------------------------------
13-- TEST: if we join a yielded lane, the lane aborts
14---------------------------------------------------
15if true then
16 -- launch coroutine lane
17 local h = coro_g("hello", "world", "!")
18 -- read the first yielded value, sending back the expected index
19 assert(h:resume(1) == "hello")
20 -- join the lane. since it will reach a yield point, it unblocks and ends. last yielded values are returned normally
21 local b, r = h:join(0.5)
22 local s = h.status
23 assert(s == "done" and b == true and r == "world", "got " .. s .. " " .. tostring(b) .. " " .. tostring(r))
24end
diff --git a/unit_tests/scripts/coro/linda_in_close_handler.lua b/unit_tests/scripts/coro/linda_in_close_handler.lua
new file mode 100644
index 0000000..8636f01
--- /dev/null
+++ b/unit_tests/scripts/coro/linda_in_close_handler.lua
@@ -0,0 +1,43 @@
1local fixture = require "fixture"
2local lanes = require "lanes".configure{on_state_create = fixture.on_state_create}
3
4local fixture = require "fixture"
5lanes.finally(fixture.throwing_finalizer)
6
7-- this test is only for Lua 5.4+
8local utils = lanes.require "_utils54"
9local PRINT = utils.MAKE_PRINT()
10
11local out_linda = lanes.linda()
12
13local test_close = function(what_, f_)
14 local c = coroutine.create(f_)
15 for i = 1, 10 do
16 local t, r1, r2 = coroutine.resume(c, out_linda) -- returns true + <yielded values>
17 assert(t == true and r1 == "I yield!" and r2 == i, "got " .. tostring(t) .. " " .. tostring(r1) .. " " .. tostring(r2))
18 local s = coroutine.status(c)
19 assert(s == "suspended")
20 end
21 local r, s = coroutine.close(c)
22 assert(r == true and s == nil)
23 -- the local variable inside the yielder body should be closed
24 local s, r = out_linda:receive(0, "out")
25 assert(s == "out" and r == "Closed!", what_ .. " got " .. tostring(s) .. " " .. tostring(r))
26end
27
28---------------------------------------------------------
29-- TEST: first, try the close mechanism outside of a lane
30---------------------------------------------------------
31if true then
32 assert(type(utils.yielder_with_to_be_closed) == "function")
33 test_close("base", utils.yielder_with_to_be_closed)
34end
35
36---------------------------------------------------------------
37-- TEST: try again with a function obtained through dump/undump
38---------------------------------------------------------------
39if true then
40 -- note this means our yielder implementation can't have upvalues, as they are lost in the process
41 test_close("dumped", load(string.dump(utils.yielder_with_to_be_closed)))
42end
43
diff --git a/unit_tests/scripts/coro/regular_function.lua b/unit_tests/scripts/coro/regular_function.lua
new file mode 100644
index 0000000..09aa3b7
--- /dev/null
+++ b/unit_tests/scripts/coro/regular_function.lua
@@ -0,0 +1,38 @@
1local lanes = require "lanes".configure()
2
3local utils = lanes.require "_utils"
4local PRINT = utils.MAKE_PRINT()
5
6-- a lane body that just returns some value
7local returner = function(msg_)
8 local utils = lanes.require "_utils"
9 local PRINT = utils.MAKE_PRINT()
10 PRINT "In lane"
11 assert(msg_ == "hi")
12 return "bye"
13end
14
15-- a function that returns some value can run in a coroutine
16if true then
17 -- the generator
18 local g = lanes.coro("*", {name = "auto"}, returner)
19
20 -- launch lane
21 local h = g("hi")
22
23 local r = h[1]
24 assert(r == "bye")
25end
26
27-- can't resume a coro after the lane body has returned
28if true then
29 -- the generator
30 local g = lanes.coro("*", {name = "auto"}, returner)
31
32 -- launch lane
33 local h = g("hi")
34
35 -- resuming a lane that terminated execution should raise an error
36 local b, e = pcall(h.resume, h)
37 assert(b == false and type(e) == "string")
38end
diff --git a/unit_tests/scripts/coro/resume_basics.lua b/unit_tests/scripts/coro/resume_basics.lua
new file mode 100644
index 0000000..5b124f5
--- /dev/null
+++ b/unit_tests/scripts/coro/resume_basics.lua
@@ -0,0 +1,40 @@
1local lanes = require "lanes"
2
3local fixture = require "fixture"
4lanes.finally(fixture.throwing_finalizer)
5
6local utils = lanes.require "_utils"
7local PRINT = utils.MAKE_PRINT()
8
9-- the coroutine generator
10local coro_g = lanes.coro("*", {name = "auto"}, utils.yield_one_by_one)
11
12-------------------------------------------------------------------------------------------------
13-- TEST: we can resume as many times as the lane yields, then read the returned value on indexing
14-------------------------------------------------------------------------------------------------
15if true then
16 -- launch coroutine lane
17 local h = coro_g("hello", "world", "!")
18 -- read the yielded values, sending back the expected index
19 assert(h:resume(1) == "hello")
20 assert(h:resume(2) == "world")
21 assert(h:resume(3) == "!")
22 -- the lane return value is available as usual
23 local r = h[1]
24 assert(r == "bye!")
25end
26
27---------------------------------------------------------------------------------------------
28-- TEST: we can resume as many times as the lane yields, then read the returned value on join
29---------------------------------------------------------------------------------------------
30if true then
31 -- launch coroutine lane
32 local h = coro_g("hello", "world", "!")
33 -- read the yielded values, sending back the expected index
34 assert(h:resume(1) == "hello")
35 assert(h:resume(2) == "world")
36 assert(h:resume(3) == "!")
37 -- the lane return value is available as usual
38 local s, r = h:join()
39 assert(h.status == "done" and s == true and r == "bye!")
40end
diff --git a/unit_tests/scripts/coro/yielding_in_non_coro_errors.lua b/unit_tests/scripts/coro/yielding_in_non_coro_errors.lua
new file mode 100644
index 0000000..fc0c072
--- /dev/null
+++ b/unit_tests/scripts/coro/yielding_in_non_coro_errors.lua
@@ -0,0 +1,28 @@
1local lanes = require "lanes"
2
3local fixture = require "fixture"
4lanes.finally(fixture.throwing_finalizer)
5
6local utils = lanes.require "_utils"
7local PRINT = utils.MAKE_PRINT()
8
9--------------------------------------------------------------------------------------------------
10-- TEST: if we start a non-coroutine lane with a yielding function, we should get an error, right?
11--------------------------------------------------------------------------------------------------
12local fun_g = lanes.gen("*", { name = 'auto' }, utils.yield_one_by_one)
13local h = fun_g("hello", "world", "!")
14local err, status, stack = h:join()
15PRINT(err, status, stack)
16-- the actual error message is not the same for Lua 5.1
17-- of course, it also has to be different for LuaJIT as well
18-- also, LuaJIT prepends a file:line to the actual error message, which Lua5.1 does not.
19local msgs = {
20 ["Lua 5.1"] = jit and "attempt to yield across C-call boundary" or "attempt to yield across metamethod/C-call boundary",
21 ["Lua 5.2"] = "attempt to yield from outside a coroutine",
22 ["Lua 5.3"] = "attempt to yield from outside a coroutine",
23 ["Lua 5.4"] = "attempt to yield from outside a coroutine",
24 ["Lua 5.5"] = "attempt to yield from outside a coroutine"
25}
26local expected_msg = msgs[_VERSION]
27PRINT("expected_msg = " .. expected_msg)
28assert(err == nil and string.find(status, expected_msg, 1, true) and stack == nil, "status = " .. status)
diff --git a/unit_tests/scripts/lane/body_is_a_c_function.lua b/unit_tests/scripts/lane/body_is_a_c_function.lua
new file mode 100644
index 0000000..d8d329f
--- /dev/null
+++ b/unit_tests/scripts/lane/body_is_a_c_function.lua
@@ -0,0 +1,28 @@
1local lanes = require "lanes".configure()
2
3-- ##################################################################################################
4-- ##################################################################################################
5-- ##################################################################################################
6
7-- we can create a generator where the lane body is a C function
8do
9 local b, g = pcall(lanes.gen, "*", print)
10 assert(b == true and type(g) == "function")
11 -- we can start the lane
12 local b, h = pcall(g, "hello")
13 -- the lane runs normally
14 h:join()
15 assert(h.status == "done")
16end
17
18-- we can create a generator where the lane body is a C function that raises an error
19do
20 local b, g = pcall(lanes.gen, "*", error)
21 assert(b == true and type(g) == "function")
22 -- we can start the lane
23 local b, h = pcall(g, "this is an error")
24 -- this provides the error that occurred in the lane
25 local s, e, t = h:join()
26 assert(h.status == "error")
27 assert(s == nil and e == "this is an error" and t == nil)
28end
diff --git a/unit_tests/scripts/lane/cooperative_shutdown.lua b/unit_tests/scripts/lane/cooperative_shutdown.lua
index 756e33c..0a0943e 100644
--- a/unit_tests/scripts/lane/cooperative_shutdown.lua
+++ b/unit_tests/scripts/lane/cooperative_shutdown.lua
@@ -1,10 +1,10 @@
1local lanes = require "lanes" 1local lanes = require "lanes".configure{on_state_create = require "fixture".on_state_create}
2 2
3-- launch lanes that cooperate properly with cancellation request 3-- launch lanes that cooperate properly with cancellation request
4 4
5local lane1 = function() 5local lane1 = function()
6 lane_threadname("lane1") 6 lane_threadname("lane1")
7 -- loop breaks on cancellation request 7 -- loop breaks on soft cancellation request
8 repeat 8 repeat
9 lanes.sleep(0) 9 lanes.sleep(0)
10 until cancel_test() 10 until cancel_test()
@@ -23,7 +23,6 @@ end
23local lane3 = function() 23local lane3 = function()
24 lane_threadname("lane3") 24 lane_threadname("lane3")
25 -- this one cooperates too, because of the hook cancellation modes that Lanes will be using 25 -- this one cooperates too, because of the hook cancellation modes that Lanes will be using
26 -- but not with LuaJIT, because the function is compiled, and we don't call anyone, so no hook triggers
27 local fixture = require "fixture" 26 local fixture = require "fixture"
28 repeat until fixture.give_me_back(false) 27 repeat until fixture.give_me_back(false)
29end 28end
@@ -43,7 +42,14 @@ local h2 = g2(linda)
43 42
44local h3 = g3() 43local h3 = g3()
45 44
46-- wait until they are both started 45lanes.sleep(0.1)
47repeat until h1.status == "running" and h2.status == "waiting" and h3.status == "running" 46
47local is_running = function(lane_h)
48 local status = lane_h.status
49 return status == "running" or status == "waiting"
50end
51
52-- wait until they are all started
53repeat until is_running(h1) and is_running(h2) and is_running(h3)
48 54
49-- let the script terminate, Lanes should not crash at shutdown 55-- let the script terminate, Lanes should not crash at shutdown
diff --git a/unit_tests/scripts/lane/tasking_cancelling.lua b/unit_tests/scripts/lane/tasking_cancelling.lua
index 873140e..d153ffa 100644
--- a/unit_tests/scripts/lane/tasking_cancelling.lua
+++ b/unit_tests/scripts/lane/tasking_cancelling.lua
@@ -1,4 +1,7 @@
1local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure(config).configure() 1local require_fixture_result_1, require_fixture_result_2 = require "fixture"
2local fixture = assert(require_fixture_result_1)
3
4local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure{on_state_create = fixture.on_state_create}.configure()
2print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2) 5print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2)
3local lanes = require_lanes_result_1 6local lanes = require_lanes_result_1
4 7
@@ -15,6 +18,28 @@ local lanes_linda = assert(lanes.linda)
15-- ################################################################################################## 18-- ##################################################################################################
16-- ################################################################################################## 19-- ##################################################################################################
17 20
21-- cancellation of cooperating lanes
22local cooperative = function()
23 local fixture = assert(require "fixture")
24 local which_cancel
25 repeat
26 fixture.block_for(0.2)
27 which_cancel = cancel_test()
28 until which_cancel
29 return which_cancel
30end
31-- soft and hard are behaviorally equivalent when no blocking linda operation is involved
32local cooperative_lane_soft = lanes_gen("*", { name = 'auto' }, cooperative)()
33local a, b = cooperative_lane_soft:cancel("soft", 0) -- issue request, do not wait for lane to terminate
34assert(a == false and b == "timeout", "got " .. tostring(a) .. " " .. tostring(b))
35assert(cooperative_lane_soft[1] == "soft") -- return value of the lane body is the value returned by cancel_test()
36local cooperative_lane_hard = lanes_gen("*", { name = 'auto' }, cooperative)()
37local c, d = cooperative_lane_hard:cancel("hard", 0) -- issue request, do not wait for lane to terminate
38assert(a == false and b == "timeout", "got " .. tostring(c) .. " " .. tostring(d))
39assert(cooperative_lane_hard[1] == "hard") -- return value of the lane body is the value returned by cancel_test()
40
41-- ##################################################################################################
42
18-- cancellation of lanes waiting on a linda 43-- cancellation of lanes waiting on a linda
19local limited = lanes_linda{name = "limited"} 44local limited = lanes_linda{name = "limited"}
20assert.fails(function() limited:limit("key", -1) end) 45assert.fails(function() limited:limit("key", -1) end)
diff --git a/unit_tests/scripts/lane/tasking_join_test.lua b/unit_tests/scripts/lane/tasking_join_test.lua
index 2fbce6c..495a709 100644
--- a/unit_tests/scripts/lane/tasking_join_test.lua
+++ b/unit_tests/scripts/lane/tasking_join_test.lua
@@ -30,14 +30,19 @@ end
30 30
31PRINT("---=== :join test ===---", "\n\n") 31PRINT("---=== :join test ===---", "\n\n")
32 32
33-- a lane body that returns nothing is successfully joined with true, nil
34local r, ret = lanes_gen(function() end)():join()
35assert(r == true and ret == nil)
36
33-- NOTE: 'unpack()' cannot be used on the lane handle; it will always return nil 37-- NOTE: 'unpack()' cannot be used on the lane handle; it will always return nil
34-- (unless [1..n] has been read earlier, in which case it would seemingly 38-- (unless [1..n] has been read earlier, in which case it would seemingly
35-- work). 39-- work).
36 40
37local S= lanes_gen("table", { name = 'auto', gc_cb = gc_cb }, 41local S = lanes_gen("table", { name = 'auto', gc_cb = gc_cb },
38 function(arg) 42 function(arg)
39 lane_threadname "join test lane" 43 lane_threadname "join test lane"
40 set_finalizer(function() end) 44 set_finalizer(function() end)
45 -- take arg table, reverse its contents in aux, then return the unpacked result
41 local aux= {} 46 local aux= {}
42 for i, v in ipairs(arg) do 47 for i, v in ipairs(arg) do
43 table.insert(aux, 1, v) 48 table.insert(aux, 1, v)
@@ -46,15 +51,16 @@ local S= lanes_gen("table", { name = 'auto', gc_cb = gc_cb },
46 return (unpack or table.unpack)(aux) 51 return (unpack or table.unpack)(aux)
47end) 52end)
48 53
49h= S { 12, 13, 14 } -- execution starts, h[1..3] will get the return values 54local h = S { 12, 13, 14 } -- execution starts, h[1..3] will get the return values
50-- wait a bit so that the lane has a chance to set its debug name 55-- wait a bit so that the lane has a chance to set its debug name
51SLEEP(0.5) 56SLEEP(0.5)
52print("joining with '" .. h:get_threadname() .. "'") 57print("joining with '" .. h:get_threadname() .. "'")
53local a,b,c,d= h:join() 58local r, a, b, c, d = h:join()
54if h.status == "error" then 59if h.status == "error" then
55 print(h:get_threadname(), "error: " , a, b, c, d) 60 print(h:get_threadname(), "error: " , r, a, b, c, d)
56else 61else
57 print(h:get_threadname(), a,b,c,d) 62 print(h:get_threadname(), r, a, b, c, d)
63 assert(r==true, "r == " .. tostring(r))
58 assert(a==14, "a == " .. tostring(a)) 64 assert(a==14, "a == " .. tostring(a))
59 assert(b==13, "b == " .. tostring(b)) 65 assert(b==13, "b == " .. tostring(b))
60 assert(c==12, "c == " .. tostring(c)) 66 assert(c==12, "c == " .. tostring(c))
diff --git a/unit_tests/scripts/lane/tasking_send_receive_code.lua b/unit_tests/scripts/lane/tasking_send_receive_code.lua
index cb3663f..fdc2602 100644
--- a/unit_tests/scripts/lane/tasking_send_receive_code.lua
+++ b/unit_tests/scripts/lane/tasking_send_receive_code.lua
@@ -53,28 +53,26 @@ local function chunk2(linda)
53 assert(info.linedefined == 32, "bad linedefined") -- start of 'chunk2' 53 assert(info.linedefined == 32, "bad linedefined") -- start of 'chunk2'
54 assert(config.strip_functions and info.currentline==-1 or info.currentline > info.linedefined, "bad currentline") -- line of 'debug.getinfo' 54 assert(config.strip_functions and info.currentline==-1 or info.currentline > info.linedefined, "bad currentline") -- line of 'debug.getinfo'
55 assert(info.lastlinedefined > info.currentline, "bad lastlinedefined") -- end of 'chunk2' 55 assert(info.lastlinedefined > info.currentline, "bad lastlinedefined") -- end of 'chunk2'
56 local k,func= linda:receive("down") 56 assert(linda:count("down") == 2, "bad linda contents") -- function, "ok"
57 assert(type(func)=="function", "not a function") 57 local k,func,str= linda:receive_batched("down", 2)
58 assert(k=="down") 58 assert(k=="down")
59 assert(type(func)=="function", "not a function")
60 assert(str=="ok", "bad receive result: " .. tostring(k) .. " -> ".. tostring(str))
61 assert(linda:count("down") == 0, "bad linda contents") -- nothing
59 62
60 func(linda) 63 func(linda)
61
62 local k,str= linda:receive("down")
63 assert(str=="ok", "bad receive result")
64
65 linda:send("up", function() return ":)" end, "ok2") 64 linda:send("up", function() return ":)" end, "ok2")
66end 65end
67 66
68local linda = lanes_linda{name = "auto"} 67local linda = lanes_linda{name = "auto"}
69local t2= lanes_gen("debug,package,string,io", { name = 'auto', gc_cb = gc_cb }, chunk2)(linda) -- prepare & launch 68local t2= lanes_gen("debug,package,string,io", { name = 'auto', gc_cb = gc_cb }, chunk2)(linda) -- prepare & launch
70linda:send("down", function(linda) linda:send("up", "ready!") end, 69linda:send("down", function(linda) linda:send("up", "ready!") end, "ok")
71 "ok")
72-- wait to see if the tiny function gets executed 70-- wait to see if the tiny function gets executed
73-- 71--
74local k,s= linda:receive(1, "up") 72local k,s= linda:receive(1, "up")
75if t2.status == "error" then 73if t2.status == "error" then
76 PRINT("t2 error: " , t2:join()) 74 local n,err,s = t2:join()
77 assert(false) 75 assert(false, "t2 error: " .. err)
78end 76end
79PRINT(s) 77PRINT(s)
80assert(s=="ready!", s .. " is not 'ready!'") 78assert(s=="ready!", s .. " is not 'ready!'")
diff --git a/unit_tests/scripts/lane/uncooperative_shutdown.lua b/unit_tests/scripts/lane/uncooperative_shutdown.lua
index 89e1ff8..eb89ed3 100644
--- a/unit_tests/scripts/lane/uncooperative_shutdown.lua
+++ b/unit_tests/scripts/lane/uncooperative_shutdown.lua
@@ -8,7 +8,7 @@ local lanes = require "lanes".configure{shutdown_timeout = 0.001, on_state_creat
8-- launch lanes that blocks forever 8-- launch lanes that blocks forever
9local lane = function() 9local lane = function()
10 local fixture = require "fixture" 10 local fixture = require "fixture"
11 fixture.sleep_for() 11 fixture.block_for()
12end 12end
13 13
14-- the generator 14-- the generator
diff --git a/unit_tests/scripts/linda/send_receive_func_and_string.lua b/unit_tests/scripts/linda/send_receive_func_and_string.lua
new file mode 100644
index 0000000..188cfcd
--- /dev/null
+++ b/unit_tests/scripts/linda/send_receive_func_and_string.lua
@@ -0,0 +1,13 @@
1local lanes = require "lanes"
2
3-- a newly created linda doesn't contain anything
4local l = lanes.linda()
5
6-- send a function and a string, make sure that's what we read back
7l:send("k", function() end, "str")
8local c = l:count("k")
9assert(c == 2, "got " .. c)
10local k, v1, v2 = l:receive_batched("k", 2)
11local tv1, tv2 = type(v1), type(v2)
12assert(k == "k" and tv1 == "function" and tv2 == "string", "got " .. tv1 .. " " .. tv2)
13assert(l:count("k") == 0)
diff --git a/unit_tests/scripts/linda/wake_period.lua b/unit_tests/scripts/linda/wake_period.lua
index e4a900d..d2dccc3 100644
--- a/unit_tests/scripts/linda/wake_period.lua
+++ b/unit_tests/scripts/linda/wake_period.lua
@@ -6,7 +6,7 @@ local lanes = require_lanes_result_1
6local body = function(linda_) 6local body = function(linda_)
7 -- a blocking read that lasts longer than the tested wake_period values 7 -- a blocking read that lasts longer than the tested wake_period values
8 linda_:receive(2, "empty_slot") 8 linda_:receive(2, "empty_slot")
9 return true 9 return "done"
10end 10end
11 11
12-- if we don't cancel the lane, we should wait the whole duration 12-- if we don't cancel the lane, we should wait the whole duration
@@ -22,7 +22,8 @@ local function check_wake_duration(linda_, expected_, do_cancel_)
22 assert(result == false and reason == 'timeout', "unexpected cancel result") 22 assert(result == false and reason == 'timeout', "unexpected cancel result")
23 end 23 end
24 -- this should wait until the linda wakes by itself before the actual receive timeout and sees the cancel request 24 -- this should wait until the linda wakes by itself before the actual receive timeout and sees the cancel request
25 h:join() 25 local r, ret = h:join()
26 assert(r == true and ret == "done")
26 local t1 = lanes.now_secs() 27 local t1 = lanes.now_secs()
27 local delta = t1 - t0 28 local delta = t1 - t0
28 -- the linda should check for cancellation at about the expected period, not earlier 29 -- the linda should check for cancellation at about the expected period, not earlier
diff --git a/unit_tests/scripts/misc/deeptest.lua b/unit_tests/scripts/misc/deeptest.lua
new file mode 100644
index 0000000..542c35b
--- /dev/null
+++ b/unit_tests/scripts/misc/deeptest.lua
@@ -0,0 +1,161 @@
1local fixture = require "fixture"
2local lanes = require("lanes").configure{on_state_create = fixture.on_state_create}
3local l = lanes.linda{name = "my linda"}
4
5local table_unpack = table.unpack or unpack -- Lua 5.1 support
6
7-- we will transfer userdata created by this module, so we need to make Lanes aware of it
8local dt = lanes.require "deep_userdata_example"
9
10-- set DEEP to any non-false value to run the Deep Userdata tests. "gc" selects a special test for debug purposes
11DEEP = DEEP or true
12-- set CLONABLE to any non-false value to run the Clonable Userdata tests
13CLONABLE = CLONABLE or true
14
15-- lua 5.1->5.2 support a single table uservalue
16-- lua 5.3->5.4 supports an arbitrary type uservalue
17local test_uvtype = (_VERSION == "Lua 5.4") and "function" or (_VERSION == "Lua 5.3") and "string" or "table"
18-- lua 5.4 supports multiple uservalues
19local nupvals = _VERSION == "Lua 5.4" and 3 or 1
20
21local makeUserValue = function( obj_)
22 if test_uvtype == "table" then
23 return {"some uservalue"}
24 elseif test_uvtype == "string" then
25 return "some uservalue"
26 elseif test_uvtype == "function" then
27 -- a function that pull the userdata as upvalue
28 local f = function()
29 return "-> '" .. tostring( obj_) .. "'"
30 end
31 return f
32 end
33end
34
35local printDeep = function( prefix_, obj_, t_)
36 print( prefix_, obj_)
37 for uvi = 1, nupvals do
38 local uservalue = obj_:getuv(uvi)
39 print ("uv #" .. uvi, type( uservalue), uservalue, type(uservalue) == "function" and uservalue() or "")
40 end
41 if t_ then
42 local count = 0
43 for k, v in ipairs( t_) do
44 print( "t["..tostring(k).."]", v)
45 count = count + 1
46 end
47 -- we should have only 2 indexed entries with the same value
48 assert(count == 2 and t_[1] == t_[2])
49 end
50 print()
51end
52
53local performTest = function( obj_)
54 -- setup the userdata with some value and a uservalue
55 obj_:set( 666)
56 obj_:setuv( 1, makeUserValue( obj_))
57 if nupvals > 1 then
58 -- keep uv #2 as nil
59 obj_:setuv( 3, "ENDUV")
60 end
61
62 local t =
63 {
64 -- two indices with an identical value: we should also have identical values on the other side (even if not the same as the original ones when they are clonables)
65 obj_,
66 obj_,
67 -- this one won't transfer because we don't support full uservalue as keys
68 [obj_] = "val"
69 }
70
71 -- read back the contents of the object
72 printDeep( "immediate:", obj_, t)
73
74 -- send the object in a linda, get it back out, read the contents
75 l:set( "key", obj_, t)
76 -- when obj_ is a deep userdata, out is the same userdata as obj_ (not another one pointing on the same deep memory block) because of an internal cache table [deep*] -> proxy)
77 -- when obj_ is a clonable userdata, we get a different clone everytime we cross a linda or lane barrier
78 local _n, _val1, _val2 = l:get( "key", 2)
79 assert(_n == (_val2 and 2 or 1))
80 printDeep( "out of linda:", _val1, _val2)
81
82 -- send the object in a lane through argument passing, the lane body returns it as return value, read the contents
83 local g = lanes.gen(
84 "package"
85 , {
86 name = 'auto',
87 required = { "deep_userdata_example"} -- we will transfer userdata created by this module, so we need to make this lane aware of it
88 }
89 , function( arg_, t_)
90 -- read contents inside lane: arg_ and t_ by argument
91 printDeep( "in lane, as arguments:", arg_, t_)
92 -- read contents inside lane: obj_ and t by upvalue
93 printDeep( "in lane, as upvalues:", obj_, t)
94 -- read contents inside lane: in linda
95 local _n, _val1, _val2 = l:get( "key", 2)
96 assert(_n == (_val2 and 2 or 1))
97 printDeep( "in lane, from linda:", _val1, _val2)
98 return arg_, t_
99 end
100 )
101 h = g( obj_, t)
102 -- when obj_ is a deep userdata, from_lane is the same userdata as obj_ (not another one pointing on the same deep memory block) because of an internal cache table [deep*] -> proxy)
103 -- when obj_ is a clonable userdata, we get a different clone everytime we cross a linda or lane barrier
104 printDeep( "from lane:", h[1], h[2])
105end
106
107if DEEP then
108 print "================================================================"
109 print "DEEP"
110 local d = dt.new_deep(nupvals)
111 if type(DEEP) == "string" then
112 local gc_tests = {
113 thrasher = function(repeat_, size_)
114 print "in thrasher"
115 -- result is a table of repeat_ tables, each containing size_ entries
116 local result = {}
117 for i = 1, repeat_ do
118 local batch_values = {}
119 for j = 1, size_ do
120 table.insert(batch_values, j)
121 end
122 table.insert(result, batch_values)
123 end
124 print "thrasher done"
125 return result
126 end,
127 stack_abuser = function(repeat_, size_)
128 print "in stack_abuser"
129 for i = 1, repeat_ do
130 local batch_values = {}
131 for j = 1, size_ do
132 table.insert(batch_values, j)
133 end
134 -- return size_ values
135 local _ = table_unpack(batch_values)
136 end
137 print "stack_abuser done"
138 return result
139 end
140 }
141 -- have the object call the function from inside one of its functions, to detect if it gets collected from there (while in use!)
142 local testf = gc_tests[DEEP]
143 if testf then
144 local r = d:invoke(gc_tests[DEEP], REPEAT or 10, SIZE or 10)
145 print("invoke -> ", tostring(r))
146 else
147 print("unknown test '" .. DEEP .. "'")
148 end
149 else
150 performTest(d)
151 end
152end
153
154if CLONABLE then
155 print "================================================================"
156 print "CLONABLE"
157 performTest( dt.new_clonable(nupvals))
158end
159
160print "================================================================"
161print "TEST OK" \ No newline at end of file
diff --git a/unit_tests/shared.cpp b/unit_tests/shared.cpp
index e70d5d8..9f3b08e 100644
--- a/unit_tests/shared.cpp
+++ b/unit_tests/shared.cpp
@@ -18,9 +18,9 @@ namespace
18 { 18 {
19 STACK_CHECK_START_REL(L_, 0); 19 STACK_CHECK_START_REL(L_, 0);
20 lua_getglobal(L_, "package"); // L_: package 20 lua_getglobal(L_, "package"); // L_: package
21 std::ignore = luaG_getfield(L_, kIdxTop, "preload"); // L_: package package.preload 21 std::ignore = luaW_getfield(L_, kIdxTop, "preload"); // L_: package package.preload
22 lua_pushcfunction(L_, openf_); // L_: package package.preload openf_ 22 lua_pushcfunction(L_, openf_); // L_: package package.preload openf_
23 luaG_setfield(L_, StackIndex{ -2 }, name_); // L_: package package.preload 23 luaW_setfield(L_, StackIndex{ -2 }, name_); // L_: package package.preload
24 lua_pop(L_, 2); 24 lua_pop(L_, 2);
25 STACK_CHECK(L_, 0); 25 STACK_CHECK(L_, 0);
26 } 26 }
@@ -32,7 +32,7 @@ namespace
32 lua_CFunction sFreezingFinalizer = +[](lua_State* const L_) { 32 lua_CFunction sFreezingFinalizer = +[](lua_State* const L_) {
33 std::lock_guard _guard{ sCallCountsLock }; 33 std::lock_guard _guard{ sCallCountsLock };
34 sFinalizerHits[L_].test_and_set(); 34 sFinalizerHits[L_].test_and_set();
35 luaG_pushstring(L_, "freeze"); // just freeze the thread in place so that it can be debugged 35 luaW_pushstring(L_, "freeze"); // just freeze the thread in place so that it can be debugged
36 return 1; 36 return 1;
37 }; 37 };
38 38
@@ -47,22 +47,22 @@ namespace
47 }; 47 };
48 48
49 lua_CFunction sNewUserData = +[](lua_State* const L_) { 49 lua_CFunction sNewUserData = +[](lua_State* const L_) {
50 std::ignore = luaG_newuserdatauv<int>(L_, UserValueCount{ 0 }); 50 std::ignore = luaW_newuserdatauv<int>(L_, UserValueCount{ 0 });
51 return 1; 51 return 1;
52 }; 52 };
53 53
54 // a function that enables any lane to require "fixture" 54 // a function that enables any lane to require "fixture" and "deep_userdata_example"
55 lua_CFunction sOnStateCreate = +[](lua_State* const L_) { 55 lua_CFunction sOnStateCreate = +[](lua_State* const L_) {
56 PreloadModule(L_, "fixture", luaopen_fixture); 56 PreloadModule(L_, "fixture", luaopen_fixture);
57 PreloadModule(L_, "deep_userdata_example", luaopen_deep_userdata_example); 57 PreloadModule(L_, "deep_userdata_example", luaopen_deep_userdata_example);
58 return 0; 58 return 0;
59 }; 59 };
60 60
61 // a function that sleeps for the specified duration (in seconds) 61 // a function that blocks for the specified duration (in seconds) by putting the current thread to sleep
62 lua_CFunction sSleepFor = +[](lua_State* const L_) { 62 lua_CFunction sBlockFor = +[](lua_State* const L_) {
63 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; 63 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() };
64 lua_settop(L_, 1); 64 lua_settop(L_, 1);
65 if (luaG_type(L_, kIdxTop) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion 65 if (luaW_type(L_, kIdxTop) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion
66 lua_Duration const _duration{ lua_tonumber(L_, kIdxTop) }; 66 lua_Duration const _duration{ lua_tonumber(L_, kIdxTop) };
67 if (_duration.count() >= 0.0) { 67 if (_duration.count() >= 0.0) {
68 _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(_duration); 68 _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(_duration);
@@ -82,17 +82,17 @@ namespace
82 std::lock_guard _guard{ sCallCountsLock }; 82 std::lock_guard _guard{ sCallCountsLock };
83 sFinalizerHits[L_].test_and_set(); 83 sFinalizerHits[L_].test_and_set();
84 bool const _allLanesTerminated = lua_toboolean(L_, kIdxTop); 84 bool const _allLanesTerminated = lua_toboolean(L_, kIdxTop);
85 luaG_pushstring(L_, "Finalizer%s", _allLanesTerminated ? "" : ": Uncooperative lanes detected"); 85 luaW_pushstring(L_, "Finalizer%s", _allLanesTerminated ? "" : ": Uncooperative lanes detected");
86 return 1; 86 return 1;
87 }; 87 };
88 88
89 static luaL_Reg const sFixture[] = { 89 static luaL_Reg const sFixture[] = {
90 { "freezing_finalizer", sFreezingFinalizer }, 90 { "freezing_finalizer", sFreezingFinalizer },
91 { "give_me_back()", sGiveMeBack }, 91 { "give_me_back", sGiveMeBack },
92 { "newlightuserdata", sNewLightUserData }, 92 { "newlightuserdata", sNewLightUserData },
93 { "newuserdata", sNewUserData }, 93 { "newuserdata", sNewUserData },
94 { "on_state_create", sOnStateCreate }, 94 { "on_state_create", sOnStateCreate },
95 { "sleep_for", sSleepFor }, 95 { "block_for", sBlockFor },
96 { "throwing_finalizer", sThrowingFinalizer }, 96 { "throwing_finalizer", sThrowingFinalizer },
97 { nullptr, nullptr } 97 { nullptr, nullptr }
98 }; 98 };
@@ -103,7 +103,7 @@ namespace
103 int luaopen_fixture(lua_State* L_) 103 int luaopen_fixture(lua_State* L_)
104 { 104 {
105 STACK_CHECK_START_REL(L_, 0); 105 STACK_CHECK_START_REL(L_, 0);
106 luaG_newlib<std::size(local::sFixture)>(L_, local::sFixture); // M 106 luaW_newlib<std::size(local::sFixture)>(L_, local::sFixture); // M
107 STACK_CHECK(L_, 1); 107 STACK_CHECK(L_, 1);
108 return 1; 108 return 1;
109 } 109 }
@@ -246,7 +246,7 @@ LuaError LuaState::doString(std::string_view const& str_) const
246 return _loadErr; 246 return _loadErr;
247 } 247 }
248 LuaError const _callErr{ lua_pcall(L, 0, 1, 0) }; // L: "<msg>"? 248 LuaError const _callErr{ lua_pcall(L, 0, 1, 0) }; // L: "<msg>"?
249 [[maybe_unused]] std::string_view const _out{ luaG_tostring(L, kIdxTop) }; 249 [[maybe_unused]] std::string_view const _out{ luaW_tostring(L, kIdxTop) };
250 STACK_CHECK(L, 1); 250 STACK_CHECK(L, 1);
251 return _callErr; 251 return _callErr;
252} 252}
@@ -257,8 +257,8 @@ std::string_view LuaState::doStringAndRet(std::string_view const& str_) const
257{ 257{
258 lua_settop(L, 0); 258 lua_settop(L, 0);
259 if (str_.empty()) { 259 if (str_.empty()) {
260 luaG_pushstring(L, ""); 260 luaW_pushstring(L, "");
261 return luaG_tostring(L, kIdxTop); 261 return luaW_tostring(L, kIdxTop);
262 } 262 }
263 STACK_CHECK_START_REL(L, 0); 263 STACK_CHECK_START_REL(L, 0);
264 LuaError const _loadErr{ luaL_loadstring(L, str_.data()) }; // L: chunk() 264 LuaError const _loadErr{ luaL_loadstring(L, str_.data()) }; // L: chunk()
@@ -268,7 +268,7 @@ std::string_view LuaState::doStringAndRet(std::string_view const& str_) const
268 } 268 }
269 [[maybe_unused]] LuaError const _callErr{ lua_pcall(L, 0, 1, 0) }; // L: "<msg>"?|retstring 269 [[maybe_unused]] LuaError const _callErr{ lua_pcall(L, 0, 1, 0) }; // L: "<msg>"?|retstring
270 STACK_CHECK(L, 1); 270 STACK_CHECK(L, 1);
271 return luaG_tostring(L, kIdxTop); 271 return luaW_tostring(L, kIdxTop);
272} 272}
273 273
274// ################################################################################################# 274// #################################################################################################
@@ -336,7 +336,7 @@ void LuaState::requireFailure(std::string_view const& script_)
336{ 336{
337 auto const _result{ doString(script_) }; 337 auto const _result{ doString(script_) };
338 if (_result == LuaError::OK) { 338 if (_result == LuaError::OK) {
339 WARN(luaG_tostring(L, kIdxTop)); 339 WARN(luaW_tostring(L, kIdxTop));
340 } 340 }
341 REQUIRE(_result != LuaError::OK); 341 REQUIRE(_result != LuaError::OK);
342 lua_settop(L, 0); 342 lua_settop(L, 0);
@@ -372,7 +372,7 @@ void LuaState::requireSuccess(std::string_view const& script_)
372{ 372{
373 auto const _result{ doString(script_) }; 373 auto const _result{ doString(script_) };
374 if (_result != LuaError::OK) { 374 if (_result != LuaError::OK) {
375 WARN(luaG_tostring(L, kIdxTop)); 375 WARN(luaW_tostring(L, kIdxTop));
376 } 376 }
377 REQUIRE(_result == LuaError::OK); 377 REQUIRE(_result == LuaError::OK);
378 lua_settop(L, 0); 378 lua_settop(L, 0);
@@ -384,7 +384,7 @@ void LuaState::requireSuccess(std::filesystem::path const& root_, std::string_vi
384{ 384{
385 auto const _result{ doFile(root_, path_) }; 385 auto const _result{ doFile(root_, path_) };
386 if (_result != LuaError::OK) { 386 if (_result != LuaError::OK) {
387 WARN(luaG_tostring(L, kIdxTop)); 387 WARN(luaW_tostring(L, kIdxTop));
388 } 388 }
389 REQUIRE(_result == LuaError::OK); 389 REQUIRE(_result == LuaError::OK);
390 lua_settop(L, 0); 390 lua_settop(L, 0);
@@ -407,20 +407,20 @@ TEST_CASE("LuaState.doString")
407{ 407{
408 LuaState _L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; 408 LuaState _L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } };
409 // if the script fails to load, we should find the error message at the top of the stack 409 // if the script fails to load, we should find the error message at the top of the stack
410 REQUIRE([&L = _L]() { std::ignore = L.doString("function end"); return lua_gettop(L) == 1 && luaG_type(L, StackIndex{1}) == LuaType::STRING; }()); 410 REQUIRE([&L = _L]() { std::ignore = L.doString("function end"); return lua_gettop(L) == 1 && luaW_type(L, StackIndex{1}) == LuaType::STRING; }());
411 411
412 // if the script runs, the stack should contain its return value 412 // if the script runs, the stack should contain its return value
413 REQUIRE([&L = _L]() { std::ignore = L.doString("return true"); return lua_gettop(L) == 1 && luaG_type(L, StackIndex{1}) == LuaType::BOOLEAN; }()); 413 REQUIRE([&L = _L]() { std::ignore = L.doString("return true"); return lua_gettop(L) == 1 && luaW_type(L, StackIndex{1}) == LuaType::BOOLEAN; }());
414 REQUIRE([&L = _L]() { std::ignore = L.doString("return 'hello'"); return lua_gettop(L) == 1 && luaG_tostring(L, StackIndex{1}) == "hello"; }()); 414 REQUIRE([&L = _L]() { std::ignore = L.doString("return 'hello'"); return lua_gettop(L) == 1 && luaW_tostring(L, StackIndex{1}) == "hello"; }());
415 // or nil if it didn't return anything 415 // or nil if it didn't return anything
416 REQUIRE([&L = _L]() { std::ignore = L.doString("return"); return lua_gettop(L) == 1 && luaG_type(L, StackIndex{1}) == LuaType::NIL; }()); 416 REQUIRE([&L = _L]() { std::ignore = L.doString("return"); return lua_gettop(L) == 1 && luaW_type(L, StackIndex{1}) == LuaType::NIL; }());
417 417
418 // on failure, doStringAndRet returns "", and the error message is on the stack 418 // on failure, doStringAndRet returns "", and the error message is on the stack
419 REQUIRE([&L = _L]() { return L.doStringAndRet("function end") == "" && lua_gettop(L) == 1 && luaG_type(L, StackIndex{ 1 }) == LuaType::STRING && luaG_tostring(L, StackIndex{ 1 }) != ""; }()); 419 REQUIRE([&L = _L]() { return L.doStringAndRet("function end") == "" && lua_gettop(L) == 1 && luaW_type(L, StackIndex{ 1 }) == LuaType::STRING && luaW_tostring(L, StackIndex{ 1 }) != ""; }());
420 // on success doStringAndRet returns the string returned by the script, that is also at the top of the stack 420 // on success doStringAndRet returns the string returned by the script, that is also at the top of the stack
421 REQUIRE([&L = _L]() { return L.doStringAndRet("return 'hello'") == "hello" && lua_gettop(L) == 1 && luaG_type(L, StackIndex{ 1 }) == LuaType::STRING && luaG_tostring(L, StackIndex{ 1 }) == "hello"; }()); 421 REQUIRE([&L = _L]() { return L.doStringAndRet("return 'hello'") == "hello" && lua_gettop(L) == 1 && luaW_type(L, StackIndex{ 1 }) == LuaType::STRING && luaW_tostring(L, StackIndex{ 1 }) == "hello"; }());
422 // if the returned value is not (convertible to) a string, we should get an empty string out of doStringAndRet 422 // if the returned value is not (convertible to) a string, we should get an empty string out of doStringAndRet
423 REQUIRE([&L = _L]() { return L.doStringAndRet("return function() end") == "" && lua_gettop(L) == 1 && luaG_type(L, StackIndex{ 1 }) == LuaType::FUNCTION && luaG_tostring(L, StackIndex{ 1 }) == ""; }()); 423 REQUIRE([&L = _L]() { return L.doStringAndRet("return function() end") == "" && lua_gettop(L) == 1 && luaW_type(L, StackIndex{ 1 }) == LuaType::FUNCTION && luaW_tostring(L, StackIndex{ 1 }) == ""; }());
424} 424}
425 425
426// ################################################################################################# 426// #################################################################################################
@@ -436,9 +436,9 @@ FileRunner::FileRunner(std::string_view const& where_)
436 // because the VS Test Explorer doesn't appreciate the text output of some scripts, so absorb them 436 // because the VS Test Explorer doesn't appreciate the text output of some scripts, so absorb them
437 if constexpr (1) { 437 if constexpr (1) {
438 auto const _nullprint = +[](lua_State* const L_) { return 0; }; 438 auto const _nullprint = +[](lua_State* const L_) { return 0; };
439 luaG_pushglobaltable(L); 439 luaW_pushglobaltable(L);
440 lua_pushcfunction(L, _nullprint); 440 lua_pushcfunction(L, _nullprint);
441 luaG_setfield(L, StackIndex{ -2 }, std::string_view{ "print" }); 441 luaW_setfield(L, StackIndex{ -2 }, std::string_view{ "print" });
442 lua_pop(L, 1); 442 lua_pop(L, 1);
443 stackCheck(0); 443 stackCheck(0);
444 } 444 }
diff --git a/unit_tests/shared.h b/unit_tests/shared.h
index b884df0..c6c3339 100644
--- a/unit_tests/shared.h
+++ b/unit_tests/shared.h
@@ -56,7 +56,7 @@ class LuaState
56 56
57 friend std::ostream& operator<<(std::ostream& os_, LuaState const& s_) 57 friend std::ostream& operator<<(std::ostream& os_, LuaState const& s_)
58 { 58 {
59 os_ << luaG_tostring(s_.L, kIdxTop); 59 os_ << luaW_tostring(s_.L, kIdxTop);
60 return os_; 60 return os_;
61 } 61 }
62}; 62};