diff options
99 files changed, 4228 insertions, 2099 deletions
@@ -2,6 +2,7 @@ _Output | |||
2 | _Tmp | 2 | _Tmp |
3 | _LuaVersions | 3 | _LuaVersions |
4 | .vs | 4 | .vs |
5 | .vscode | ||
5 | *.dll | 6 | *.dll |
6 | *.exe | 7 | *.exe |
7 | *.gch | 8 | *.gch |
diff --git a/.runsettings b/.runsettings index 8114d6a..e349e01 100644 --- a/.runsettings +++ b/.runsettings | |||
@@ -8,10 +8,10 @@ | |||
8 | <!-- The whole setup relies on Lua Binaries and headers to be located in a folder $(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName) | 8 | <!-- The whole setup relies on Lua Binaries and headers to be located in a folder $(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName) |
9 | this is also true for linker input folders, the folder where lanes.lua is copied by the custom build operation, etc. | 9 | this is also true for linker input folders, the folder where lanes.lua is copied by the custom build operation, etc. |
10 | --> | 10 | --> |
11 | <Environment> | 11 | <!-- Environment> |
12 | <LUA_PATH value="$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)" /> | 12 | <LUA_PATH>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)</LUA_PATH> |
13 | <LUA_CPATH value="$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)" /> | 13 | <LUA_CPATH>$(SolutionDir)/_LuaVersions/$(PlatformName)/$(ConfigurationName)</LUA_CPATH> |
14 | </Environment> | 14 | </Environment --> |
15 | 15 | ||
16 | <!-- Executable Filename | 16 | <!-- Executable Filename |
17 | Discover filenames with ... (must not include the .exe extension) | 17 | Discover filenames with ... (must not include the .exe extension) |
diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..a2781fd --- /dev/null +++ b/.vscode/launch.json | |||
@@ -0,0 +1,44 @@ | |||
1 | { | ||
2 | "version": "0.2.0", | ||
3 | "configurations": [ | ||
4 | |||
5 | { | ||
6 | "name": "Debug MinGW-w64", | ||
7 | "type": "cppdbg", | ||
8 | "request": "launch", | ||
9 | "program": "${workspaceFolder}/unit_tests/UnitTests.exe", | ||
10 | "args": [ | ||
11 | //"--list-tests", | ||
12 | "--rng-seed 0", | ||
13 | "-s scripted_tests.lane.tasking_cancelling" | ||
14 | ], | ||
15 | "stopAtEntry": true, | ||
16 | "cwd": "${workspaceFolder}", | ||
17 | "environment": [ | ||
18 | { | ||
19 | "name" : "LUA_CPATH", | ||
20 | "value" : "./src/?.dll;./deep_userdata_example/?.dll" | ||
21 | }, | ||
22 | { | ||
23 | "name" : "LUA_PATH", | ||
24 | "value" : "./src/?.lua;./tests/?.lua" | ||
25 | } | ||
26 | ], | ||
27 | "externalConsole": false, // or true, depending on your preference | ||
28 | "MIMode": "gdb", | ||
29 | "miDebuggerPath": "C:/msys64/ucrt64/bin/gdb.exe", // Replace with your GDB path | ||
30 | "setupCommands": [ | ||
31 | { | ||
32 | "description": "Enable pretty-printing for gdb", | ||
33 | "text": "-enable-pretty-printing", | ||
34 | "ignoreFailures": true | ||
35 | }, | ||
36 | { | ||
37 | "description": "Show GDB commands", | ||
38 | "text": "-interpreter-exec console \"monitor set debug 1\"", | ||
39 | "ignoreFailures": true | ||
40 | } | ||
41 | ] | ||
42 | } | ||
43 | ] | ||
44 | } | ||
@@ -1,11 +1,12 @@ | |||
1 | CHANGES: | 1 | CHANGES: |
2 | 2 | ||
3 | CHANGE 2: BGe 27-Nov-24 | 3 | CHANGE 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. |
@@ -45,6 +48,7 @@ CHANGE 2: BGe 27-Nov-24 | |||
45 | - Providing "auto" as name when constructing a Linda cause Lanes to provide a name built from the source location of the construction. | 48 | - Providing "auto" as name when constructing a Linda cause Lanes to provide a name built from the source location of the construction. |
46 | - Specifying a group to lanes.linda() is mandatory when Lanes is configured with user Keepers. | 49 | - Specifying a group to lanes.linda() is mandatory when Lanes is configured with user Keepers. |
47 | - linda:deep() result no longer contains the raw C pointer of the Linda object. | 50 | - linda:deep() result no longer contains the raw C pointer of the Linda object. |
51 | - new function linda:receive_batched() to replace linda:receive(linda.batched). linda.batched special value is removed. | ||
48 | - linda :receive(), :send(), :get(), :set(), :limit() return nil, error in case of problem. Returned values in case of success change too. | 52 | - linda :receive(), :send(), :get(), :set(), :limit() return nil, error in case of problem. Returned values in case of success change too. |
49 | - linda:limit() can be used to read the value if no new limit is provided. | 53 | - linda:limit() can be used to read the value if no new limit is provided. |
50 | - linda:restrict() can restrain the use of send/receive or set/get on any key. | 54 | - linda:restrict() can restrain the use of send/receive or set/get on any key. |
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. |
6 | CMAKE_MINIMUM_REQUIRED(VERSION 3.18) | ||
7 | PROJECT(lanes CXX) | ||
8 | set (CMAKE_CXX_STANDARD 20) | ||
6 | 9 | ||
7 | PROJECT(lanes C) | ||
8 | CMAKE_MINIMUM_REQUIRED(VERSION 2.6) | ||
9 | 10 | ||
10 | 11 | ||
11 | FIND_PACKAGE(Lua51 REQUIRED) | 12 | FIND_PACKAGE(Lua51 REQUIRED) |
@@ -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)" | ||
810 | xcopy /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)" | ||
1016 | xcopy /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)" | ||
1198 | xcopy /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)" | ||
1358 | xcopy /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" /> |
@@ -79,7 +79,13 @@ build_DUE: | |||
79 | # also run a test that shows whether lanes is successfully loaded or not | 79 | # also run a test that shows whether lanes is successfully loaded or not |
80 | run_unit_tests: build_lanes build_unit_tests build_DUE | 80 | run_unit_tests: build_lanes build_unit_tests build_DUE |
81 | @echo ========================================================================================= | 81 | @echo ========================================================================================= |
82 | $(_PREFIX) $(_UNITTEST_TARGET) "lanes.require 'lanes'" | 82 | $(_PREFIX) $(_UNITTEST_TARGET) --list-tests |
83 | $(_PREFIX) $(_UNITTEST_TARGET) --rng-seed 0 | ||
84 | |||
85 | debug_unit_tests: build_lanes build_unit_tests build_DUE | ||
86 | @echo ========================================================================================= | ||
87 | $(_PREFIX) $(_UNITTEST_TARGET) --list-tests | ||
88 | $(_PREFIX) gdb --args $(_UNITTEST_TARGET) --rng-seed 0 -s scripted_tests.lane.tasking_cancelling | ||
83 | 89 | ||
84 | clean: | 90 | clean: |
85 | cd src && $(MAKE) -f Lanes.makefile clean | 91 | cd src && $(MAKE) -f Lanes.makefile clean |
@@ -267,13 +273,11 @@ DESTDIR:=/usr/local | |||
267 | LUA_LIBDIR:=$(DESTDIR)/lib/lua/$(LUA_VERSION) | 273 | LUA_LIBDIR:=$(DESTDIR)/lib/lua/$(LUA_VERSION) |
268 | LUA_SHAREDIR:=$(DESTDIR)/share/lua/$(LUA_VERSION) | 274 | LUA_SHAREDIR:=$(DESTDIR)/share/lua/$(LUA_VERSION) |
269 | 275 | ||
270 | # | ||
271 | # AKa 17-Oct: changed to use 'install -m 644' and 'cp -p' | ||
272 | # | ||
273 | install: $(_LANES_TARGET) src/lanes.lua | 276 | install: $(_LANES_TARGET) src/lanes.lua |
274 | mkdir -p $(LUA_LIBDIR) $(LUA_SHAREDIR) | 277 | mkdir -p $(LUA_LIBDIR) $(LUA_SHAREDIR) |
275 | install -m 644 $(_LANES_TARGET) $(LUA_LIBDIR) | 278 | install -m 644 $(_LANES_TARGET) $(LUA_LIBDIR) |
276 | cp -p src/lanes.lua $(LUA_SHAREDIR) | 279 | cp -p src/lanes.lua $(LUA_SHAREDIR) |
280 | install -m 644 $(_DUE_TARGET) $(LUA_LIBDIR) | ||
277 | 281 | ||
278 | uninstall: | 282 | uninstall: |
279 | rm $(LUA_LIBDIR)/lanes_core.$(_SO) | 283 | rm $(LUA_LIBDIR)/lanes_core.$(_SO) |
diff --git a/Shared.makefile b/Shared.makefile index 492c05d..3809538 100644 --- a/Shared.makefile +++ b/Shared.makefile | |||
@@ -5,7 +5,7 @@ CC := g++ -std=c++20 | |||
5 | LIBFLAG := -shared | 5 | LIBFLAG := -shared |
6 | 6 | ||
7 | OPT_FLAGS := -O2 | 7 | OPT_FLAGS := -O2 |
8 | # -O0 -g | 8 | #OPT_FLAGS := -O0 -g3 |
9 | 9 | ||
10 | ifeq "$(findstring MINGW,$(shell uname -s))" "MINGW" | 10 | ifeq "$(findstring MINGW,$(shell uname -s))" "MINGW" |
11 | # MinGW MSYS on Windows | 11 | # MinGW MSYS on Windows |
@@ -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 a45cc7f..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. |
29 | struct MyDeepUserdata : public DeepPrelude // Deep userdata MUST start with a DeepPrelude | 29 | struct 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_) | |||
241 | static int clonable_tostring(lua_State* const L_) | 241 | static 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 | ||
@@ -261,21 +261,21 @@ static int clonable_gc(lua_State* const L_) | |||
261 | 261 | ||
262 | // this is all we need to make a userdata lanes-clonable. no dependency on Lanes code. | 262 | // this is all we need to make a userdata lanes-clonable. no dependency on Lanes code. |
263 | [[nodiscard]] | 263 | [[nodiscard]] |
264 | static int clonable_lanesclone(lua_State* L) | 264 | static int clonable_lanesclone(lua_State* const L_) |
265 | { | 265 | { |
266 | switch (lua_gettop(L)) { | 266 | switch (lua_gettop(L_)) { |
267 | case 3: | 267 | case 3: |
268 | { | 268 | { |
269 | MyClonableUserdata* self = static_cast<MyClonableUserdata*>(lua_touserdata(L, 1)); | 269 | MyClonableUserdata* const _self = static_cast<MyClonableUserdata*>(lua_touserdata(L_, 1)); |
270 | MyClonableUserdata* from = static_cast<MyClonableUserdata*>(lua_touserdata(L, 2)); | 270 | MyClonableUserdata* const _from = static_cast<MyClonableUserdata*>(lua_touserdata(L_, 2)); |
271 | size_t len = lua_tointeger(L, 3); | 271 | auto const _len{ static_cast<size_t>(lua_tointeger(L_, 3)) }; // make 32-bits builds happy |
272 | assert(len == sizeof(MyClonableUserdata)); | 272 | assert(_len == sizeof(MyClonableUserdata)); |
273 | *self = *from; | 273 | *_self = *_from; |
274 | } | 274 | } |
275 | return 0; | 275 | return 0; |
276 | 276 | ||
277 | default: | 277 | default: |
278 | raise_luaL_error(L, "Lanes called clonable_lanesclone with unexpected arguments"); | 278 | raise_luaL_error(L_, "Lanes called clonable_lanesclone with unexpected arguments"); |
279 | } | 279 | } |
280 | return 0; | 280 | return 0; |
281 | } | 281 | } |
@@ -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 | ||
309 | static luaL_Reg const deep_module[] = { | 309 | static 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 | ||
318 | LANES_API int luaopen_deep_userdata_example(lua_State* L) | 318 | LANES_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 @@ | |||
1 | local lanes = require("lanes").configure{ with_timers = false} | 1 | local lanes = require("lanes").configure{ with_timers = false} |
2 | local l = lanes.linda "my linda" | 2 | local l = lanes.linda{name = "my linda"} |
3 | 3 | ||
4 | local table_unpack = table.unpack or unpack -- Lua 5.1 support | 4 | local table_unpack = table.unpack or unpack -- Lua 5.1 support |
5 | 5 | ||
diff --git a/docs/index.html b/docs/index.html index d0f3940..2e74495 100644 --- a/docs/index.html +++ b/docs/index.html | |||
@@ -38,6 +38,7 @@ | |||
38 | <a href="#description">Description</a> · | 38 | <a href="#description">Description</a> · |
39 | <a href="#systems">Supported systems</a> · | 39 | <a href="#systems">Supported systems</a> · |
40 | <a href="#installing">Building and Installing</a> · | 40 | <a href="#installing">Building and Installing</a> · |
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 | ||
@@ -64,13 +65,13 @@ | |||
64 | <font size="-1"> | 65 | <font size="-1"> |
65 | <p> | 66 | <p> |
66 | <br /> | 67 | <br /> |
67 | <i>Copyright © 2007-24 Asko Kauppi, Benoit Germain. All rights reserved.</i> | 68 | <i>Copyright © 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 17-Mar-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 (-> <A HREF="#deep_userdata">deep userdata</A> and -> <A HREF="#clonable_userdata">clonable userdata</A>).</li> | 117 | <li>Sharing full userdata between states needs special C side preparations (-> <A HREF="#deep_userdata">deep userdata</A> and -> <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> |
@@ -271,7 +350,7 @@ | |||
271 | </p> | 350 | </p> |
272 | 351 | ||
273 | <p> | 352 | <p> |
274 | <tt>lanes.configure</tt> accepts an optional options table as sole argument. | 353 | <tt>lanes.configure</tt> accepts an optional table as sole argument. |
275 | <table border="1" cellpadding="10" style="width:100%"> | 354 | <table border="1" cellpadding="10" style="width:100%"> |
276 | <tr> | 355 | <tr> |
277 | <th style="width:15%">name</th> | 356 | <th style="width:15%">name</th> |
@@ -337,6 +416,22 @@ | |||
337 | </tr> | 416 | </tr> |
338 | 417 | ||
339 | <tr valign=top> | 418 | <tr valign=top> |
419 | <td id="linda_wake_period"> | ||
420 | <code>.linda_wake_period</code> | ||
421 | </td> | ||
422 | <td> | ||
423 | number > 0 | ||
424 | </td> | ||
425 | <td> | ||
426 | Sets the default period in seconds a linda will wake by itself during blocked operations. Default is never.<br /> | ||
427 | When a Linda enters a blocking call (<tt>send()</tt>, <tt>receive()</tt>, <tt>receive_batched()</tt>, <tt>sleep()</tt>), it normally sleeps either until the operation completes | ||
428 | or the specified timeout expires. With this setting, the default behavior can be changed to wake periodically. This can help for example with timing issues where a lane is signalled | ||
429 | for cancellation, but a linda inside the lane was in the middle of processing an operation but did not actually start the wait. This can result in the signal to be ignored, thus | ||
430 | causing the Linda to wait out the full operation timeout before cancellation is processed. | ||
431 | </td> | ||
432 | </tr> | ||
433 | |||
434 | <tr valign=top> | ||
340 | <td id="nb_user_keepers"> | 435 | <td id="nb_user_keepers"> |
341 | <code>.nb_user_keepers</code> | 436 | <code>.nb_user_keepers</code> |
342 | </td> | 437 | </td> |
@@ -769,12 +864,13 @@ | |||
769 | </tr> | 864 | </tr> |
770 | <tr valign=top> | 865 | <tr valign=top> |
771 | <td> | 866 | <td> |
772 | <code>.priority</code> | 867 | <code>.priority</code><br /> |
868 | <code>.native_priority</code> | ||
773 | </td> | 869 | </td> |
774 | <td>integer</td> | 870 | <td>integer</td> |
775 | <td> | 871 | <td> |
776 | 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 /> |
777 | 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. |
778 | 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 /> |
779 | 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>. |
780 | </td> | 876 | </td> |
@@ -797,7 +893,7 @@ | |||
797 | 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 /> |
798 | 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 /> |
799 | The lane also has a method <tt>lane:get_threadname()</tt> that gives access to that name from the caller side (returns <tt>"<unnamed>"</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>"<unnamed>"</tt> if unset).<br /> |
800 | 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>. |
801 | </p> | 897 | </p> |
802 | 898 | ||
803 | <p> | 899 | <p> |
@@ -826,8 +922,9 @@ | |||
826 | </tr> | 922 | </tr> |
827 | </table> | 923 | </table> |
828 | 924 | ||
829 | 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 /> |
830 | 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 /> | ||
831 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"> | 928 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"> |
832 | <tr> | 929 | <tr> |
833 | <td> | 930 | <td> |
@@ -836,8 +933,8 @@ | |||
836 | </tr> | 933 | </tr> |
837 | </table> | 934 | </table> |
838 | 935 | ||
839 | 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 /> |
840 | 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. |
841 | </p> | 938 | </p> |
842 | <h3>Free running lanes</h3> | 939 | <h3>Free running lanes</h3> |
843 | 940 | ||
@@ -863,14 +960,17 @@ | |||
863 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> | 960 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"> |
864 | <tr> | 961 | <tr> |
865 | <td> | 962 | <td> |
866 | <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> | ||
867 | </td> | 965 | </td> |
868 | </tr> | 966 | </tr> |
869 | </table> | 967 | </table> |
870 | <p> | 968 | <p> |
871 | 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. |
872 | <br /> | 970 | <br /> |
873 | 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. | ||
874 | </p> | 974 | </p> |
875 | 975 | ||
876 | 976 | ||
@@ -1057,7 +1157,7 @@ | |||
1057 | </p> | 1157 | </p> |
1058 | 1158 | ||
1059 | <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> |
1060 | [...]|[nil,err,stack_tbl]= lane_h:join([timeout]) | 1160 | [true, ...]|[nil,err,stack_tbl]= lane_h:join([timeout]) |
1061 | </pre></td></tr></table> | 1161 | </pre></td></tr></table> |
1062 | 1162 | ||
1063 | <p> | 1163 | <p> |
@@ -1075,9 +1175,9 @@ | |||
1075 | </ul> | 1175 | </ul> |
1076 | </li> | 1176 | </li> |
1077 | <li><tt>nil, "killed"</tt> if forcefully killed.</li> | 1177 | <li><tt>nil, "killed"</tt> if forcefully killed.</li> |
1078 | <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> |
1079 | </ul> | 1179 | </ul> |
1080 | 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>. |
1081 | </p> | 1181 | </p> |
1082 | 1182 | ||
1083 | <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> |
@@ -1107,7 +1207,7 @@ | |||
1107 | b = f() | 1207 | b = f() |
1108 | c = f() | 1208 | c = f() |
1109 | 1209 | ||
1110 | sync_linda:receive(nil, sync_linda.batched, "done", 3) -- wait for 3 lanes to write something in "done" slot of sync_linda | 1210 | sync_linda:receive_batched(nil, "done", 3) -- wait for 3 lanes to write something in "done" slot of sync_linda |
1111 | </pre></td></tr></table> | 1211 | </pre></td></tr></table> |
1112 | 1212 | ||
1113 | <!-- cancelling +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> | 1213 | <!-- cancelling +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ --> |
@@ -1121,38 +1221,49 @@ | |||
1121 | </pre></td></tr></table> | 1221 | </pre></td></tr></table> |
1122 | 1222 | ||
1123 | <p> | 1223 | <p> |
1124 | <tt>timeout</tt> is an optional number >= 0. Defaults to 0 if left unspecified or <tt>nil</tt>. | ||
1125 | <br /> | ||
1126 | <tt>cancel()</tt> sends a cancellation request to the lane. | 1224 | <tt>cancel()</tt> sends a cancellation request to the lane. |
1127 | <br /> | 1225 | <p> |
1128 | 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: | ||
1129 | <ul> | 1230 | <ul> |
1130 | <li> | 1231 | <li> |
1131 | <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>. | ||
1132 | </li> | 1235 | </li> |
1133 | <li> | 1236 | <li> |
1134 | <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 /> | ||
1135 | <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. |
1136 | </li> | 1242 | </li> |
1137 | <li> | 1243 | <li> |
1138 | <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>. | ||
1139 | </li> | 1247 | </li> |
1140 | <li> | 1248 | <li> |
1141 | <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. |
1142 | </li> | 1250 | </li> |
1143 | </ul> | 1251 | </ul> |
1144 | 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> | ||
1145 | 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>. |
1146 | </p> | 1258 | </p> |
1147 | <p> | 1259 | <p> |
1148 | 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 >= 0. Defaults to infinite if left unspecified or <tt>nil</tt>. |
1149 | Returns <tt>false, "timeout"</tt> otherwise. | ||
1150 | </p> | 1261 | </p> |
1151 | <p> | 1262 | <p> |
1152 | 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. |
1153 | </p> | 1264 | </p> |
1154 | <p> | 1265 | <p> |
1155 | 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. |
1156 | <br /> | 1267 | <br /> |
1157 | 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). |
1158 | <br /> | 1269 | <br /> |
@@ -1222,7 +1333,7 @@ | |||
1222 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> | 1333 | <table border="1" bgcolor="#FFFFE0" cellpadding="10" style="width:50%"><tr><td><pre> |
1223 | local lanes = require "lanes" | 1334 | local lanes = require "lanes" |
1224 | 1335 | ||
1225 | local linda = lanes.linda("my linda") | 1336 | local linda = lanes.linda{name = "my linda"} |
1226 | 1337 | ||
1227 | local function loop(max) | 1338 | local function loop(max) |
1228 | for i = 1, max do | 1339 | for i = 1, max do |
@@ -1260,7 +1371,7 @@ | |||
1260 | <li>Two producer-side methods: <tt>:send</tt> and <tt>:set</tt> (not out).</li> | 1371 | <li>Two producer-side methods: <tt>:send</tt> and <tt>:set</tt> (not out).</li> |
1261 | <li><tt>send</tt> allows for sending multiple values -atomically- to a given slot.</li> | 1372 | <li><tt>send</tt> allows for sending multiple values -atomically- to a given slot.</li> |
1262 | <li><tt>receive</tt> can wait for multiple slots at once.</li> | 1373 | <li><tt>receive</tt> can wait for multiple slots at once.</li> |
1263 | <li><tt>receive</tt> has a batched mode to consume more than one value from a single slot, as in <tt>linda:receive(1.0, linda.batched, "slot", 3, 6).</tt></li> | 1374 | <li><tt>receive_batched</tt> can be used to consume more than one value from a single slot, as in <tt>linda:receive_batched(1.0, "slot", 3, 6).</tt></li> |
1264 | <li><tt>restrict</tt> can restrain a particular slot to function either with <tt>send/receive</tt> or <tt>set/get</tt>.</li> | 1375 | <li><tt>restrict</tt> can restrain a particular slot to function either with <tt>send/receive</tt> or <tt>set/get</tt>.</li> |
1265 | <li>Individual slots' queue length can be limited, balancing speed differences in a producer/consumer scenario (making <tt>:send</tt> wait).</li> | 1376 | <li>Individual slots' queue length can be limited, balancing speed differences in a producer/consumer scenario (making <tt>:send</tt> wait).</li> |
1266 | <li><tt>tostring(linda)</tt> returns a string of the form <tt>"Linda: <opt_name>"</tt></li> | 1377 | <li><tt>tostring(linda)</tt> returns a string of the form <tt>"Linda: <opt_name>"</tt></li> |
@@ -1276,16 +1387,24 @@ | |||
1276 | </p> | 1387 | </p> |
1277 | 1388 | ||
1278 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> | 1389 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> |
1279 | h = lanes.linda([name],[group],[close_handler]) | 1390 | h = lanes.linda(table|nil) |
1280 | </pre></td></tr></table> | 1391 | </pre></td></tr></table> |
1281 | 1392 | ||
1282 | <p> | 1393 | <p> |
1283 | Arguments to <tt>lanes.linda()</tt> can be provided in any order, as long as there is a single string, a single number, and a single callable value (all are optional).<br /> | 1394 | Argument to <tt>lanes.linda()</tt> is either <tt>nil</tt> or a single table. The table may contain the following entries: |
1284 | Converting the linda to a string will yield the provided name prefixed by <tt>"Linda: "</tt>.<br /> | 1395 | <ul> |
1285 | If <tt>opt_name</tt> is omitted, it will evaluate to an hexadecimal number uniquely representing that linda when the linda is converted to a string. The value is the same as returned by <tt>linda:deep()</tt>.<br /> | 1396 | <li><tt>close_handler</tt>: a callable object (function or table/userdata with <tt>__call</tt> metamethod). If provided, and the linda is to-be-closed (Lua 5.4+), it will be called with all the provided arguments. For older Lua versions, its presence is ignored.</li> |
1286 | If <tt>opt_name</tt> is <tt>"auto"</tt>, Lanes will try to construct a name from the source location that called <tt>lanes.linda()</tt>. If that fails, the linda name will be <tt>"<unresolved>"</tt>.<br /> | 1397 | <li><tt>group</tt>: an integer between 0 and the number of Keeper states. Mandatory if Lanes is configured with more than one Keeper state. Group 0 is used by the internal timer linda.</li> |
1287 | If Lanes is configured with more than one Keeper state, <tt>group</tt> is mandatory.<br /> | 1398 | <li> |
1288 | If the linda is to-be-closed (Lua 5.4+), and a <tt>close_handler</tt> is provided, it will be called with all the provided arguments. For older Lua versions, its presence will cause an error. | 1399 | <tt>name</tt>: a string. Converting the linda to a string will yield the provided name prefixed by <tt>"Linda: "</tt>. |
1400 | If omitted or empty, it will evaluate to the string representation of a hexadecimal number uniquely representing that linda when the linda is converted to a string. The numeric value is the same as returned by <tt>linda:deep()</tt>.<br /> | ||
1401 | If <tt>"auto"</tt>, Lanes will try to construct a name from the source location that called <tt>lanes.linda()</tt>. If that fails, the linda name will be <tt>"<unresolved>"</tt>. | ||
1402 | </li> | ||
1403 | <li> | ||
1404 | <tt>wake_period</tt>: a number > 0 (unit: seconds). If provided, overrides <a href="#linda_wake_period"><tt>linda_wake_period</tt></a> provided to <a href="#initialization"><tt>lanes.configure()</tt></a>. | ||
1405 | </li> | ||
1406 | </ul> | ||
1407 | Unknown fields are silently ignored. | ||
1289 | </p> | 1408 | </p> |
1290 | 1409 | ||
1291 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> | 1410 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> |
@@ -1349,12 +1468,12 @@ | |||
1349 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> | 1468 | <table border="1" bgcolor="#E0E0FF" cellpadding="10" style="width:50%"><tr><td><pre> |
1350 | slot, val = h:receive([timeout_secs,] slot [, slot...]) | 1469 | slot, val = h:receive([timeout_secs,] slot [, slot...]) |
1351 | 1470 | ||
1352 | slot, val [, val...] = h:receive([timeout,] h.batched, slot, n_uint_min[, n_uint_max]) | 1471 | slot, val [, val...] = h:receive_batched([timeout,] slot, n_uint_min[, n_uint_max]) |
1353 | </pre></td></tr></table> | 1472 | </pre></td></tr></table> |
1354 | 1473 | ||
1355 | <p> | 1474 | <p> |
1356 | <tt>receive()</tt> raises an error if called when a restriction forbids its use on any provided slot.<br /> | 1475 | <tt>receive()</tt> and <tt>receive_batched()</tt> raise an error if called when a restriction forbids their use on any provided slot.<br /> |
1357 | In batched mode, <tt>receive()</tt> will raise an error if <tt>min_count < 1</tt> or <tt>max_count < min_count</tt>. | 1476 | <tt>receive_batched()</tt> will raise an error if <tt>min_count < 1</tt> or <tt>max_count < min_count</tt>. |
1358 | </p> | 1477 | </p> |
1359 | 1478 | ||
1360 | <p> | 1479 | <p> |
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 | ||
38 | dependencies= { | 38 | dependencies= { |
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 | ||
42 | build = { | 42 | build = { |
@@ -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/_pch.hpp b/src/_pch.hpp index 495a959..a77b7f5 100644 --- a/src/_pch.hpp +++ b/src/_pch.hpp | |||
@@ -1,5 +1,3 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <algorithm> | 1 | #include <algorithm> |
4 | #include <array> | 2 | #include <array> |
5 | #include <atomic> | 3 | #include <atomic> |
@@ -9,6 +7,7 @@ | |||
9 | #include <compare> | 7 | #include <compare> |
10 | #include <concepts> | 8 | #include <concepts> |
11 | #include <condition_variable> | 9 | #include <condition_variable> |
10 | #include <cstring> | ||
12 | #include <functional> | 11 | #include <functional> |
13 | #include <iostream> | 12 | #include <iostream> |
14 | #ifndef __PROSPERO__ | 13 | #ifndef __PROSPERO__ |
@@ -19,6 +18,7 @@ | |||
19 | #include <ranges> | 18 | #include <ranges> |
20 | #include <source_location> | 19 | #include <source_location> |
21 | //#include <stop_token> | 20 | //#include <stop_token> |
21 | #include <span> | ||
22 | #include <string_view> | 22 | #include <string_view> |
23 | #include <thread> | 23 | #include <thread> |
24 | #include <tuple> | 24 | #include <tuple> |
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 | ||
41 | namespace { | ||
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 | |||
84 | static 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]] | ||
107 | static 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_) | |||
133 | LUAG_FUNC(cancel_test) | 120 | LUAG_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]) |
143 | LUAG_FUNC(lane_cancel) | 151 | LUAG_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 | ||
8 | UserValueCount luaG_getalluservalues(lua_State* const L_, StackIndex const idx_) | 8 | UserValueCount 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>"] |
27 | LuaType luaG_getmodule(lua_State* const L_, std::string_view const& name_) | 27 | LuaType 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 | ||
172 | unsigned 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 | |||
82 | inline 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 | ||
93 | void* lua_newuserdatauv(lua_State* L_, size_t sz_, UserValueCount nuvalue_); | 80 | void* 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 | ||
106 | inline int luaL_optint(lua_State* L_, StackIndex n_, lua_Integer d_) | 92 | unsigned 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]] |
139 | inline LuaType luaG_type(lua_State* const L_, StackIndex const idx_) | 122 | inline 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]] |
155 | inline std::string_view luaG_tostring(lua_State* const L_, StackIndex const idx_) | 138 | inline 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]] |
163 | inline std::string_view luaG_checkstring(lua_State* const L_, StackIndex const idx_) | 146 | inline 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]] |
171 | inline std::string_view luaG_optstring(lua_State* const L_, StackIndex const idx_, std::string_view const& default_) | 154 | inline 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 | ||
181 | template <typename... EXTRA> | 164 | template <typename... EXTRA> |
182 | inline std::string_view luaG_pushstring(lua_State* const L_, std::string_view const& str_, EXTRA&&... extra_) | 165 | inline 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 |
201 | inline StackIndex luaG_absindex(lua_State* const L_, StackIndex const idx_) | 184 | inline 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 | ||
230 | static inline int luaG_dump(lua_State* const L_, lua_Writer const writer_, void* const data_, int const strip_) | 213 | static 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 | ||
237 | UserValueCount luaG_getalluservalues(lua_State* L_, StackIndex idx_); | 220 | UserValueCount 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]] |
275 | static inline LuaType luaG_getfield(lua_State* const L_, StackIndex const idx_, std::string_view const& name_) | 258 | static 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]] |
283 | LuaType luaG_getmodule(lua_State* L_, std::string_view const& name_); | 266 | LuaType luaW_getmodule(lua_State* L_, std::string_view const& name_); |
267 | |||
268 | // ################################################################################################# | ||
269 | |||
270 | template <typename LUA_NEWSTATE> | ||
271 | concept RequiresOldLuaNewState = requires(LUA_NEWSTATE f_) | ||
272 | { | ||
273 | { | ||
274 | f_(nullptr, 0) | ||
275 | } -> std::same_as<lua_State*>; | ||
276 | }; | ||
277 | |||
278 | template <RequiresOldLuaNewState LUA_NEWSTATE> | ||
279 | static 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 | |||
287 | template <typename LUA_NEWSTATE> | ||
288 | concept RequiresNewLuaNewState = requires(LUA_NEWSTATE f_) | ||
289 | { | ||
290 | { | ||
291 | f_(nullptr, nullptr, 0) | ||
292 | } -> std::same_as<lua_State*>; | ||
293 | }; | ||
294 | |||
295 | template <RequiresNewLuaNewState LUA_NEWSTATE> | ||
296 | static 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 | |||
304 | static 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 | ||
287 | template<typename ENUM> | 311 | template<typename ENUM> |
288 | requires std::is_enum_v<ENUM> | 312 | requires std::is_enum_v<ENUM> |
289 | [[nodiscard]] | 313 | [[nodiscard]] |
290 | ENUM luaG_optenum(lua_State* const L_, StackIndex const idx_, ENUM const def_) | 314 | ENUM 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 | ||
297 | inline void luaG_registerlibfuncs(lua_State* const L_, luaL_Reg const* funcs_) | 321 | inline 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]] |
356 | static inline LuaError luaG_resume(lua_State* const L_, lua_State* const from_, int const nargs_, int* const nresults_) | 380 | static 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> | |||
364 | concept RequiresOldLuaRawget = requires(LUA_RAWGET f_) { { f_(nullptr, 0) } -> std::same_as<void>; }; | 388 | concept RequiresOldLuaRawget = requires(LUA_RAWGET f_) { { f_(nullptr, 0) } -> std::same_as<void>; }; |
365 | 389 | ||
366 | template <RequiresOldLuaRawget LUA_RAWGET> | 390 | template <RequiresOldLuaRawget LUA_RAWGET> |
367 | static inline LuaType WrapLuaRawget(LUA_RAWGET lua_rawget_, lua_State* const L_, StackIndex const idx_) | 391 | static 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> | |||
377 | concept RequiresNewLuaRawget = requires(LUA_RAWGET f_) { { f_(nullptr, 0) } -> std::same_as<int>; }; | 401 | concept RequiresNewLuaRawget = requires(LUA_RAWGET f_) { { f_(nullptr, 0) } -> std::same_as<int>; }; |
378 | 402 | ||
379 | template <RequiresNewLuaRawget LUA_RAWGET> | 403 | template <RequiresNewLuaRawget LUA_RAWGET> |
380 | static inline LuaType WrapLuaRawget(LUA_RAWGET lua_rawget_, lua_State* const L_, StackIndex const idx_) | 404 | static 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 | ||
388 | static inline LuaType luaG_rawget(lua_State* const L_, StackIndex const idx_) | 412 | static 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 | ||
395 | static inline LuaType luaG_rawgetfield(lua_State* const L_, StackIndex const idx_, std::string_view const& name_) | 419 | static 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 | ||
405 | template <size_t N> | 429 | template <size_t N> |
406 | static inline void luaG_newlib(lua_State* const L_, luaL_Reg const (&funcs_)[N]) | 430 | static 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 | ||
414 | template <typename T> | 438 | template <typename T> |
415 | [[nodiscard]] | 439 | [[nodiscard]] |
416 | T* luaG_newuserdatauv(lua_State* const L_, UserValueCount const nuvalue_) | 440 | T* 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 | ||
423 | inline void luaG_pushglobaltable(lua_State* const L_) | 447 | inline 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 | ||
434 | inline void luaG_setfield(lua_State* const L_, StackIndex const idx_, char const* const k_) = delete; | 458 | inline void luaW_setfield(lua_State* const L_, StackIndex const idx_, char const* const k_) = delete; |
435 | inline void luaG_setfield(lua_State* const L_, StackIndex const idx_, std::string_view const& k_) | 459 | inline 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 | ||
442 | inline void luaG_setmetatable(lua_State* const L_, std::string_view const& tname_) | 466 | inline 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 |
457 | template <typename T> | 481 | template <typename T> |
458 | [[nodiscard]] | 482 | [[nodiscard]] |
459 | T* luaG_tofulluserdata(lua_State* const L_, StackIndex const index_) | 483 | T* 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 | ||
467 | template <typename T> | 491 | template <typename T> |
468 | [[nodiscard]] | 492 | [[nodiscard]] |
469 | auto luaG_tolightuserdata(lua_State* const L_, StackIndex const index_) | 493 | auto 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]] |
482 | inline std::string_view luaG_typename(lua_State* const L_, LuaType const t_) | 506 | inline 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]] |
490 | inline std::string_view luaG_typename(lua_State* const L_, StackIndex const idx_) | 514 | inline 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]] |
104 | int DeepFactory::DeepGC(lua_State* const L_) | 104 | int 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 d6716a3..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]] | ||
44 | static 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]] |
58 | static int func_lookup_sentinel(lua_State* const L_) | 41 | static 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]] |
94 | std::string_view InterCopyContext::findLookupName() const | 77 | std::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]] |
159 | static lua_Integer get_mt_id(Universe* const U_, lua_State* const L_, StackIndex const idx_) | 142 | static 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 |
196 | void InterCopyContext::copyFunction() const | 179 | void 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'. |
369 | void InterCopyContext::copyCachedFunction() const | 354 | void 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]] |
737 | bool InterCopyContext::tryCopyClonable() const | 722 | bool 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 | size_t const userdata_size{ lua_rawlen(L1, _L1_i) }; | 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); |
@@ -930,10 +915,10 @@ bool InterCopyContext::interCopyFunction() const | |||
930 | _source = lua_touserdata(L1, -1); | 915 | _source = lua_touserdata(L1, -1); |
931 | void* _clone{ nullptr }; | 916 | void* _clone{ nullptr }; |
932 | // get the number of bytes to allocate for the clone | 917 | // get the number of bytes to allocate for the clone |
933 | size_t const _userdata_size{ lua_rawlen(L1, kIdxTop) }; | 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 |
@@ -994,7 +979,7 @@ bool InterCopyContext::interCopyLightuserdata() const | |||
994 | // recognize and print known UniqueKey names here | 979 | // recognize and print known UniqueKey names here |
995 | if constexpr (USE_DEBUG_SPEW()) { | 980 | if constexpr (USE_DEBUG_SPEW()) { |
996 | bool _found{ false }; | 981 | bool _found{ false }; |
997 | static constexpr std::array<std::reference_wrapper<UniqueKey const>, 3> kKeysToCheck{ kLindaBatched, kCancelError, kNilSentinel }; | 982 | static constexpr std::array<std::reference_wrapper<UniqueKey const>, 2> kKeysToCheck{ kCancelError, kNilSentinel }; |
998 | for (UniqueKey const& _key : kKeysToCheck) { | 983 | for (UniqueKey const& _key : kKeysToCheck) { |
999 | if (_key.equals(L1, L1_i)) { | 984 | if (_key.equals(L1, L1_i)) { |
1000 | DEBUGSPEW_CODE(DebugSpew(nullptr) << _key.debugName); | 985 | DEBUGSPEW_CODE(DebugSpew(nullptr) << _key.debugName); |
@@ -1060,9 +1045,9 @@ bool InterCopyContext::interCopyNumber() const | |||
1060 | [[nodiscard]] | 1045 | [[nodiscard]] |
1061 | bool InterCopyContext::interCopyString() const | 1046 | bool 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 cad9207..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]] | ||
107 | bool KeyUD::changeLimit(LindaLimit const limit_) | 108 | bool 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]] | ||
130 | KeyUD* KeyUD::Create(KeeperState const K_) | 132 | KeyUD* 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]] | ||
144 | KeyUD* KeyUD::GetPtr(KeeperState const K_, StackIndex const idx_) | 147 | KeyUD* 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]] | ||
184 | int KeyUD::pop(KeeperState const K_, int const minCount_, int const maxCount_) | 188 | int 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) |
223 | void KeyUD::prepareAccess(KeeperState const K_, StackIndex const idx_) const | 237 | void 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]] | ||
236 | bool KeyUD::push(KeeperState const K_, int const count_, bool const enforceLimit_) | 251 | bool 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 | |||
259 | void KeyUD::pushFillStatus(KeeperState const K_) const | 274 | void 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]] | ||
289 | bool KeyUD::reset(KeeperState const K_) | 307 | bool 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]] | ||
340 | int keepercall_collectgarbage(lua_State* const L_) | 359 | int 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]] | ||
349 | int keepercall_count(lua_State* const L_) | 369 | int 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]] | ||
412 | int keepercall_destruct(lua_State* const L_) | 433 | int 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]] | ||
430 | int keepercall_get(lua_State* const L_) | 452 | int 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]] | ||
464 | int keepercall_limit(lua_State* const L_) | 487 | int 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]] | ||
507 | int keepercall_receive(lua_State* const L_) | 531 | int 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]] | ||
551 | int keepercall_receive_batched(lua_State* const L_) | 576 | int 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]] | ||
584 | int keepercall_restrict(lua_State* const L_) | 610 | int 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]] | ||
648 | int keepercall_send(lua_State* const L_) | 675 | int 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]] | ||
687 | int keepercall_set(lua_State* const L_) | 715 | int 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]] | ||
756 | KeeperCallResult keeper_call(KeeperState const K_, keeper_api_t const func_, lua_State* const L_, Linda* const linda_, StackIndex const starting_index_) | 785 | KeeperCallResult 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; |
@@ -811,22 +840,6 @@ KeeperCallResult keeper_call(KeeperState const K_, keeper_api_t const func_, lua | |||
811 | // ################################################################################################# | 840 | // ################################################################################################# |
812 | // ################################################################################################# | 841 | // ################################################################################################# |
813 | 842 | ||
814 | void* Keeper::operator new[](size_t size_, Universe* U_) noexcept | ||
815 | { | ||
816 | // size_ is the memory for the element count followed by the elements themselves | ||
817 | return U_->internalAllocator.alloc(size_); | ||
818 | } | ||
819 | |||
820 | // ################################################################################################# | ||
821 | |||
822 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | ||
823 | void Keeper::operator delete[](void* p_, Universe* U_) | ||
824 | { | ||
825 | U_->internalAllocator.free(p_, *static_cast<size_t*>(p_) * sizeof(Keeper) + sizeof(size_t)); | ||
826 | } | ||
827 | |||
828 | // ################################################################################################# | ||
829 | |||
830 | // only used by linda:dump() and linda:__towatch() for debugging purposes | 843 | // only used by linda:dump() and linda:__towatch() for debugging purposes |
831 | // table is populated as follows: | 844 | // table is populated as follows: |
832 | // { | 845 | // { |
@@ -838,6 +851,7 @@ void Keeper::operator delete[](void* p_, Universe* U_) | |||
838 | // } | 851 | // } |
839 | // ... | 852 | // ... |
840 | // } | 853 | // } |
854 | [[nodiscard]] | ||
841 | int Keeper::PushLindaStorage(Linda& linda_, DestState const L_) | 855 | int Keeper::PushLindaStorage(Linda& linda_, DestState const L_) |
842 | { | 856 | { |
843 | Keeper* const _keeper{ linda_.whichKeeper() }; | 857 | Keeper* const _keeper{ linda_.whichKeeper() }; |
@@ -849,7 +863,7 @@ int Keeper::PushLindaStorage(Linda& linda_, DestState const L_) | |||
849 | STACK_CHECK_START_REL(_K, 0); | 863 | STACK_CHECK_START_REL(_K, 0); |
850 | kLindasRegKey.pushValue(_K); // _K: LindasDB L_: | 864 | kLindasRegKey.pushValue(_K); // _K: LindasDB L_: |
851 | lua_pushlightuserdata(_K, &linda_); // _K: LindasDB linda L_: | 865 | lua_pushlightuserdata(_K, &linda_); // _K: LindasDB linda L_: |
852 | 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_: |
853 | lua_remove(_K, -2); // _K: KeysDB L_: | 867 | lua_remove(_K, -2); // _K: KeysDB L_: |
854 | 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 |
855 | lua_pop(_K, 1); // _K: L_: | 869 | lua_pop(_K, 1); // _K: L_: |
@@ -886,20 +900,20 @@ int Keeper::PushLindaStorage(Linda& linda_, DestState const L_) | |||
886 | if (_key->limit >= 0) { | 900 | if (_key->limit >= 0) { |
887 | 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 |
888 | } else { | 902 | } else { |
889 | 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 |
890 | } | 904 | } |
891 | STACK_CHECK(L_, 5); | 905 | STACK_CHECK(L_, 5); |
892 | 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 |
893 | // keyout.restrict | 907 | // keyout.restrict |
894 | switch (_key->restrict) { | 908 | switch (_key->restrict) { |
895 | case LindaRestrict::None: | 909 | case LindaRestrict::None: |
896 | 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 |
897 | break; | 911 | break; |
898 | case LindaRestrict::SetGet: | 912 | case LindaRestrict::SetGet: |
899 | 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 |
900 | break; | 914 | break; |
901 | case LindaRestrict::SendReceive: | 915 | case LindaRestrict::SendReceive: |
902 | 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 |
903 | break; | 917 | break; |
904 | } | 918 | } |
905 | STACK_CHECK(L_, 5); | 919 | STACK_CHECK(L_, 5); |
@@ -927,7 +941,7 @@ void Keepers::DeleteKV::operator()(Keeper* const k_) const | |||
927 | for (auto& _k : std::span<Keeper>(k_, count)) { | 941 | for (auto& _k : std::span<Keeper>(k_, count)) { |
928 | _k.~Keeper(); | 942 | _k.~Keeper(); |
929 | } | 943 | } |
930 | U->internalAllocator.free(k_, count * sizeof(Keeper)); | 944 | U.internalAllocator.free(k_, count * sizeof(Keeper)); |
931 | } | 945 | } |
932 | 946 | ||
933 | // ################################################################################################# | 947 | // ################################################################################################# |
@@ -959,24 +973,24 @@ void Keepers::collectGarbage() | |||
959 | // when keeper N+1 is closed, object is GCed, linda operation is called, which attempts to acquire keeper N, whose Lua state no longer exists | 973 | // when keeper N+1 is closed, object is GCed, linda operation is called, which attempts to acquire keeper N, whose Lua state no longer exists |
960 | // in that case, the linda operation should do nothing. which means that these operations must check for keeper acquisition success | 974 | // in that case, the linda operation should do nothing. which means that these operations must check for keeper acquisition success |
961 | // which is early-outed with a keepers->nbKeepers null-check | 975 | // which is early-outed with a keepers->nbKeepers null-check |
962 | for (size_t const _i : std::ranges::iota_view{ size_t{ 0 }, _kv.nbKeepers }) { | 976 | for (Keeper& _k : std::span<Keeper>{ _kv.keepers.get(), _kv.nbKeepers }) { |
963 | _gcOneKeeper(_kv.keepers[_i]); | 977 | _gcOneKeeper(_k); |
964 | } | 978 | } |
965 | } | 979 | } |
966 | } | 980 | } |
967 | 981 | ||
968 | // ################################################################################################# | 982 | // ################################################################################################# |
969 | 983 | ||
970 | 984 | [[nodiscard]] | |
971 | void Keepers::close() | 985 | bool Keepers::close() |
972 | { | 986 | { |
973 | if (isClosing.test_and_set(std::memory_order_release)) { | 987 | if (isClosing.test_and_set(std::memory_order_release)) { |
974 | assert(false); // should never close more than once in practice | 988 | return false; // should never close more than once in practice |
975 | return; | ||
976 | } | 989 | } |
977 | 990 | ||
991 | // We may have not initialized the keepers if an error was raised in Universe::Create because of bad settings | ||
978 | if (std::holds_alternative<std::monostate>(keeper_array)) { | 992 | if (std::holds_alternative<std::monostate>(keeper_array)) { |
979 | return; | 993 | return true; |
980 | } | 994 | } |
981 | 995 | ||
982 | auto _closeOneKeeper = [](Keeper& keeper_) { | 996 | auto _closeOneKeeper = [](Keeper& keeper_) { |
@@ -996,9 +1010,8 @@ void Keepers::close() | |||
996 | // when keeper N+1 is closed, object is GCed, linda operation is called, which attempts to acquire keeper N, whose Lua state no longer exists | 1010 | // when keeper N+1 is closed, object is GCed, linda operation is called, which attempts to acquire keeper N, whose Lua state no longer exists |
997 | // in that case, the linda operation should do nothing. which means that these operations must check for keeper acquisition success | 1011 | // in that case, the linda operation should do nothing. which means that these operations must check for keeper acquisition success |
998 | // which is early-outed with a keepers->nbKeepers null-check | 1012 | // which is early-outed with a keepers->nbKeepers null-check |
999 | size_t const _nbKeepers{ std::exchange(_kv.nbKeepers, size_t{ 0 }) }; | 1013 | for (Keeper& _k : std::span<Keeper>{ _kv.keepers.get(), std::exchange(_kv.nbKeepers, size_t{ 0 }) }) { |
1000 | for (size_t const _i : std::ranges::iota_view{ size_t{ 0 }, _nbKeepers }) { | 1014 | if (!_closeOneKeeper(_k)) { |
1001 | if (!_closeOneKeeper(_kv.keepers[_i])) { | ||
1002 | // detected partial init: destroy only the mutexes that got initialized properly | 1015 | // detected partial init: destroy only the mutexes that got initialized properly |
1003 | break; | 1016 | break; |
1004 | } | 1017 | } |
@@ -1006,6 +1019,7 @@ void Keepers::close() | |||
1006 | } | 1019 | } |
1007 | 1020 | ||
1008 | keeper_array.emplace<std::monostate>(); | 1021 | keeper_array.emplace<std::monostate>(); |
1022 | return true; | ||
1009 | } | 1023 | } |
1010 | 1024 | ||
1011 | // ################################################################################################# | 1025 | // ################################################################################################# |
@@ -1076,7 +1090,7 @@ void Keepers::initialize(Universe& U_, lua_State* L_, size_t const nbKeepers_, i | |||
1076 | keeper_.K = _K; | 1090 | keeper_.K = _K; |
1077 | 1091 | ||
1078 | // Give a name to the state | 1092 | // Give a name to the state |
1079 | 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" |
1080 | if constexpr (HAVE_DECODA_SUPPORT()) { | 1094 | if constexpr (HAVE_DECODA_SUPPORT()) { |
1081 | lua_pushvalue(_K, -1); // _K: "Keeper #n" Keeper #n" | 1095 | lua_pushvalue(_K, -1); // _K: "Keeper #n" Keeper #n" |
1082 | lua_setglobal(_K, "decoda_name"); // L_: settings _K: "Keeper #n" | 1096 | lua_setglobal(_K, "decoda_name"); // L_: settings _K: "Keeper #n" |
@@ -1098,9 +1112,9 @@ void Keepers::initialize(Universe& U_, lua_State* L_, size_t const nbKeepers_, i | |||
1098 | STACK_CHECK(_K, 0); | 1112 | STACK_CHECK(_K, 0); |
1099 | 1113 | ||
1100 | // copy package.path and package.cpath from the source state | 1114 | // copy package.path and package.cpath from the source state |
1101 | 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: |
1102 | // 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 |
1103 | 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, {} }; |
1104 | if (_c.interCopyPackage() != InterCopyResult::Success) { // L_: settings ... error_msg _K: | 1118 | if (_c.interCopyPackage() != InterCopyResult::Success) { // L_: settings ... error_msg _K: |
1105 | // 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 |
1106 | lua_remove(L, -2); // L_: settings error_msg | 1120 | lua_remove(L, -2); // L_: settings error_msg |
@@ -1137,11 +1151,14 @@ void Keepers::initialize(Universe& U_, lua_State* L_, size_t const nbKeepers_, i | |||
1137 | 1151 | ||
1138 | default: | 1152 | default: |
1139 | KV& _kv = keeper_array.emplace<KV>( | 1153 | KV& _kv = keeper_array.emplace<KV>( |
1140 | std::unique_ptr<Keeper[], DeleteKV>{ new(&U_) Keeper[nbKeepers_], DeleteKV{ &U_, nbKeepers_ } }, | 1154 | std::unique_ptr<Keeper, DeleteKV>{ static_cast<Keeper*>(U_.internalAllocator.alloc(sizeof(Keeper) * nbKeepers_)), DeleteKV{ U_, nbKeepers_ } }, |
1141 | nbKeepers_ | 1155 | nbKeepers_ |
1142 | ); | 1156 | ); |
1143 | for (size_t const _i : std::ranges::iota_view{ size_t{ 0 }, nbKeepers_ }) { | 1157 | // fak. std::ranges::views::enumerate is c++23 (would help having item and index iterated over simultaneously) |
1144 | _initOneKeeper(_kv.keepers[_i], static_cast<int>(_i)); | 1158 | int _i{}; |
1159 | for (Keeper& _k : std::span<Keeper>{ _kv.keepers.get(), nbKeepers_ }) { | ||
1160 | new (&_k) Keeper{}; | ||
1161 | _initOneKeeper(_k, _i++); | ||
1145 | } | 1162 | } |
1146 | } | 1163 | } |
1147 | } | 1164 | } |
diff --git a/src/keeper.hpp b/src/keeper.hpp index 5cebe07..955577c 100644 --- a/src/keeper.hpp +++ b/src/keeper.hpp | |||
@@ -26,12 +26,6 @@ struct Keeper | |||
26 | std::mutex mutex; | 26 | std::mutex mutex; |
27 | KeeperState K{ static_cast<lua_State*>(nullptr) }; | 27 | KeeperState K{ static_cast<lua_State*>(nullptr) }; |
28 | 28 | ||
29 | [[nodiscard]] | ||
30 | static void* operator new[](size_t size_, Universe* U_) noexcept; | ||
31 | // can't actually delete the operator because the compiler generates stack unwinding code that could call it in case of exception | ||
32 | static void operator delete[](void* p_, Universe* U_); | ||
33 | |||
34 | |||
35 | ~Keeper() = default; | 29 | ~Keeper() = default; |
36 | Keeper() = default; | 30 | Keeper() = default; |
37 | // non-copyable, non-movable | 31 | // non-copyable, non-movable |
@@ -51,14 +45,15 @@ struct Keepers | |||
51 | private: | 45 | private: |
52 | struct DeleteKV | 46 | struct DeleteKV |
53 | { | 47 | { |
54 | Universe* U{}; | 48 | Universe& U; |
55 | size_t count{}; | 49 | size_t count{}; |
56 | void operator()(Keeper* k_) const; | 50 | void operator()(Keeper* k_) const; |
57 | }; | 51 | }; |
58 | // can't use std::vector<Keeper> because Keeper contains a mutex, so we need a raw memory buffer | 52 | // can't use std::unique_ptr<Keeper[]> because of interactions with placement new and custom deleters |
53 | // and I'm not using std::vector<Keeper> because I don't have an allocator to plug on the Universe (yet) | ||
59 | struct KV | 54 | struct KV |
60 | { | 55 | { |
61 | std::unique_ptr<Keeper[], DeleteKV> keepers; | 56 | std::unique_ptr<Keeper, DeleteKV> keepers; |
62 | size_t nbKeepers{}; | 57 | size_t nbKeepers{}; |
63 | }; | 58 | }; |
64 | std::variant<std::monostate, Keeper, KV> keeper_array; | 59 | std::variant<std::monostate, Keeper, KV> keeper_array; |
@@ -73,7 +68,8 @@ struct Keepers | |||
73 | 68 | ||
74 | Keepers() = default; | 69 | Keepers() = default; |
75 | void collectGarbage(); | 70 | void collectGarbage(); |
76 | void close(); | 71 | [[nodiscard]] |
72 | bool close(); | ||
77 | [[nodiscard]] | 73 | [[nodiscard]] |
78 | Keeper* getKeeper(KeeperIndex idx_); | 74 | Keeper* getKeeper(KeeperIndex idx_); |
79 | [[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) | |||
85 | static LUAG_FUNC(lane_threadname) | 85 | static 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>) | ||
810 | static LUAG_FUNC(lane_close) | 793 | static 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]] |
1097 | int 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]] | ||
1111 | std::string_view Lane::pushErrorTraceLevel(lua_State* L_) const | 1173 | std::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 | ||
1170 | void Lane::startThread(int const priority_) | 1232 | void 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 | ||
1335 | bool Lane::waitForCompletion(std::chrono::time_point<std::chrono::steady_clock> until_) | 1400 | bool 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]] | ||
1416 | bool 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) | |||
137 | LUAG_FUNC(set_thread_priority) | 137 | LUAG_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 |
195 | LUAG_FUNC(require) | 202 | LUAG_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 | ||
246 | LUAG_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 98f8c20..c5b3315 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
@@ -96,6 +96,7 @@ local default_params = | |||
96 | -- it looks also like LuaJIT allocator may not appreciate direct use of its allocator for other purposes than the VM operation | 96 | -- it looks also like LuaJIT allocator may not appreciate direct use of its allocator for other purposes than the VM operation |
97 | internal_allocator = isLuaJIT and "libc" or "allocator", | 97 | internal_allocator = isLuaJIT and "libc" or "allocator", |
98 | keepers_gc_threshold = -1, | 98 | keepers_gc_threshold = -1, |
99 | linda_wake_period = 'never', | ||
99 | nb_user_keepers = 0, | 100 | nb_user_keepers = 0, |
100 | on_state_create = nil, | 101 | on_state_create = nil, |
101 | shutdown_timeout = 0.25, | 102 | shutdown_timeout = 0.25, |
@@ -141,6 +142,19 @@ local param_checkers = | |||
141 | end | 142 | end |
142 | return true | 143 | return true |
143 | end, | 144 | end, |
145 | linda_wake_period = function(val_) | ||
146 | -- linda_wake_period should be a number > 0, or the string 'never' | ||
147 | if val_ == 'never' then | ||
148 | return true | ||
149 | end | ||
150 | if type(val_) ~= "number" then | ||
151 | return nil, "not a number" | ||
152 | end | ||
153 | if val_ <= 0 then | ||
154 | return nil, "value out of range" | ||
155 | end | ||
156 | return true | ||
157 | end, | ||
144 | nb_user_keepers = function(val_) | 158 | nb_user_keepers = function(val_) |
145 | -- nb_user_keepers should be a number in [0,100] (so that nobody tries to run OOM by specifying a huge amount) | 159 | -- nb_user_keepers should be a number in [0,100] (so that nobody tries to run OOM by specifying a huge amount) |
146 | if type(val_) ~= "number" then | 160 | if type(val_) ~= "number" then |
@@ -266,6 +280,10 @@ local opt_validators = | |||
266 | local tv = type(v_) | 280 | local tv = type(v_) |
267 | 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_) |
268 | 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, | ||
269 | package = function(v_) | 287 | package = function(v_) |
270 | local tv = type(v_) | 288 | local tv = type(v_) |
271 | 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_) |
@@ -281,7 +299,7 @@ local opt_validators = | |||
281 | } | 299 | } |
282 | 300 | ||
283 | -- ############################################################################################# | 301 | -- ############################################################################################# |
284 | -- ##################################### lanes.gen() ########################################### | 302 | -- ################################### lanes.gen/coro() ######################################## |
285 | -- ############################################################################################# | 303 | -- ############################################################################################# |
286 | 304 | ||
287 | local process_gen_opt = function(...) | 305 | local process_gen_opt = function(...) |
@@ -353,9 +371,16 @@ local process_gen_opt = function(...) | |||
353 | opt[k] = validator(v) | 371 | opt[k] = validator(v) |
354 | end | 372 | end |
355 | 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 | ||
356 | return func, libs, opt | 379 | return func, libs, opt |
357 | end -- process_gen_opt | 380 | end -- process_gen_opt |
358 | 381 | ||
382 | -- ################################################################################################# | ||
383 | |||
359 | -- 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()' |
360 | -- 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) |
361 | -- lane_h[negative]: error message, without propagating the error | 386 | -- lane_h[negative]: error message, without propagating the error |
@@ -394,25 +419,28 @@ end -- process_gen_opt | |||
394 | -- Calling with a function argument ('lane_func') ends the string/table | 419 | -- Calling with a function argument ('lane_func') ends the string/table |
395 | -- modifiers, and prepares a lane generator. | 420 | -- modifiers, and prepares a lane generator. |
396 | 421 | ||
397 | -- receives a sequence of strings and tables, plus a function | 422 | local make_generator = function(is_coro_, ...) |
398 | local gen = function(...) | ||
399 | local func, libs, opt = process_gen_opt(...) | 423 | local func, libs, opt = process_gen_opt(...) |
400 | local core_lane_new = assert(core.lane_new) | 424 | local core_lane_new = assert(core.lane_new) |
401 | 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] | ||
402 | return function(...) | 427 | return function(...) |
403 | -- 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 |
404 | 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_, ...) |
405 | end | 430 | end |
431 | end -- make_generator | ||
432 | |||
433 | -- ################################################################################################# | ||
434 | |||
435 | -- receives a sequence of strings and tables, plus a function | ||
436 | local gen = function(...) | ||
437 | return make_generator(false, ...) | ||
406 | end -- gen() | 438 | end -- gen() |
407 | 439 | ||
440 | -- ################################################################################################# | ||
441 | |||
408 | local coro = function(...) | 442 | local coro = function(...) |
409 | local func, libs, opt = process_gen_opt(...) | 443 | return make_generator(true, ...) |
410 | local core_lane_new = assert(core.lane_new) | ||
411 | 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] | ||
412 | return function(...) | ||
413 | -- must pass functions args last else they will be truncated to the first one | ||
414 | return core_lane_new(func, libs, priority, globals, package, required, gc_cb, name, error_trace_level, true, ...) | ||
415 | end | ||
416 | end -- coro() | 444 | end -- coro() |
417 | 445 | ||
418 | -- ################################################################################################# | 446 | -- ################################################################################################# |
@@ -603,7 +631,6 @@ local configure_timers = function() | |||
603 | return next_wakeup -- may be 'nil' | 631 | return next_wakeup -- may be 'nil' |
604 | end -- check_timers() | 632 | end -- check_timers() |
605 | 633 | ||
606 | local timer_gateway_batched = timerLinda.batched | ||
607 | set_finalizer(function(err, stk) | 634 | set_finalizer(function(err, stk) |
608 | if err and type(err) ~= "userdata" then | 635 | if err and type(err) ~= "userdata" then |
609 | error("LanesTimer error: "..tostring(err)) | 636 | error("LanesTimer error: "..tostring(err)) |
@@ -628,7 +655,7 @@ local configure_timers = function() | |||
628 | 655 | ||
629 | if _timerKey == TGW_KEY then | 656 | if _timerKey == TGW_KEY then |
630 | assert(getmetatable(_what) == "Linda") -- '_what' should be a linda on which the client sets a timer | 657 | assert(getmetatable(_what) == "Linda") -- '_what' should be a linda on which the client sets a timer |
631 | local _, key, wakeup_at, period = timerLinda:receive(0, timer_gateway_batched, TGW_KEY, 3) | 658 | local _, key, wakeup_at, period = timerLinda:receive_batched(0, TGW_KEY, 3) |
632 | assert(key) | 659 | assert(key) |
633 | set_timer(_what, key, wakeup_at, period and period > 0 and period or nil) | 660 | set_timer(_what, key, wakeup_at, period and period > 0 and period or nil) |
634 | elseif _timerKey == TGW_QUERY then | 661 | elseif _timerKey == TGW_QUERY then |
@@ -643,7 +670,8 @@ local configure_timers = function() | |||
643 | end | 670 | end |
644 | end | 671 | end |
645 | end -- timer_body() | 672 | end -- timer_body() |
646 | 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)() | ||
647 | end -- first_time | 675 | end -- first_time |
648 | 676 | ||
649 | ----- | 677 | ----- |
@@ -758,7 +786,7 @@ local genlock = function(linda_, key_, N) | |||
758 | -- 'nil' timeout allows 'key_' to be numeric | 786 | -- 'nil' timeout allows 'key_' to be numeric |
759 | return linda_:send(timeout, key_, trues(M_)) -- suspends until been able to push them | 787 | return linda_:send(timeout, key_, trues(M_)) -- suspends until been able to push them |
760 | else | 788 | else |
761 | local _k, _v = linda_:receive(nil, linda_.batched, key_, -M_) | 789 | local _k, _v = linda_:receive_batched(nil, key_, -M_) |
762 | -- propagate cancel_error if we got it, else return true or false | 790 | -- propagate cancel_error if we got it, else return true or false |
763 | return (_v == cancel_error and _v) or (_k and true or false) | 791 | return (_v == cancel_error and _v) or (_k and true or false) |
764 | end | 792 | end |
@@ -863,6 +891,7 @@ local configure = function(settings_) | |||
863 | lanes.set_thread_affinity = core.set_thread_affinity | 891 | lanes.set_thread_affinity = core.set_thread_affinity |
864 | lanes.set_thread_priority = core.set_thread_priority | 892 | lanes.set_thread_priority = core.set_thread_priority |
865 | lanes.sleep = core.sleep | 893 | lanes.sleep = core.sleep |
894 | lanes.thread_priority_range = core.thread_priority_range | ||
866 | 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 |
867 | 896 | ||
868 | 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 a094a8f..1f4b19d 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
@@ -43,12 +43,11 @@ namespace { | |||
43 | // ############################################################################################# | 43 | // ############################################################################################# |
44 | // ############################################################################################# | 44 | // ############################################################################################# |
45 | 45 | ||
46 | |||
47 | static void CheckKeyTypes(lua_State* const L_, StackIndex const start_, StackIndex const end_) | 46 | static void CheckKeyTypes(lua_State* const L_, StackIndex const start_, StackIndex const end_) |
48 | { | 47 | { |
49 | STACK_CHECK_START_REL(L_, 0); | 48 | STACK_CHECK_START_REL(L_, 0); |
50 | 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 } }) { |
51 | LuaType const _t{ luaG_type(L_, _i) }; | 50 | LuaType const _t{ luaW_type(L_, _i) }; |
52 | switch (_t) { | 51 | switch (_t) { |
53 | case LuaType::BOOLEAN: | 52 | case LuaType::BOOLEAN: |
54 | case LuaType::NUMBER: | 53 | case LuaType::NUMBER: |
@@ -63,7 +62,7 @@ namespace { | |||
63 | 62 | ||
64 | case LuaType::LIGHTUSERDATA: | 63 | case LuaType::LIGHTUSERDATA: |
65 | { | 64 | { |
66 | static constexpr std::array<std::reference_wrapper<UniqueKey const>, 3> kKeysToCheck{ kLindaBatched, kCancelError, kNilSentinel }; | 65 | static constexpr std::array<std::reference_wrapper<UniqueKey const>, 2> kKeysToCheck{ kCancelError, kNilSentinel }; |
67 | for (UniqueKey const& _key : kKeysToCheck) { | 66 | for (UniqueKey const& _key : kKeysToCheck) { |
68 | if (_key.equals(L_, _i)) { | 67 | if (_key.equals(L_, _i)) { |
69 | raise_luaL_error(L_, "argument #%d: can't use %s as a slot", _i, _key.debugName.data()); | 68 | raise_luaL_error(L_, "argument #%d: can't use %s as a slot", _i, _key.debugName.data()); |
@@ -110,13 +109,13 @@ namespace { | |||
110 | { | 109 | { |
111 | Linda* const _linda{ ToLinda<OPT>(L_, idx_) }; | 110 | Linda* const _linda{ ToLinda<OPT>(L_, idx_) }; |
112 | if (_linda != nullptr) { | 111 | if (_linda != nullptr) { |
113 | luaG_pushstring(L_, "Linda: "); | 112 | luaW_pushstring(L_, "Linda: "); |
114 | std::string_view const _lindaName{ _linda->getName() }; | 113 | std::string_view const _lindaName{ _linda->getName() }; |
115 | if (!_lindaName.empty()) { | 114 | if (!_lindaName.empty()) { |
116 | luaG_pushstring(L_, _lindaName); | 115 | luaW_pushstring(L_, _lindaName); |
117 | } else { | 116 | } else { |
118 | // 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 |
119 | luaG_pushstring(L_, "%p", _linda->obfuscated()); | 118 | luaW_pushstring(L_, "%p", _linda->obfuscated()); |
120 | } | 119 | } |
121 | lua_concat(L_, 2); | 120 | lua_concat(L_, 2); |
122 | return 1; | 121 | return 1; |
@@ -125,6 +124,183 @@ namespace { | |||
125 | } | 124 | } |
126 | 125 | ||
127 | // ############################################################################################# | 126 | // ############################################################################################# |
127 | |||
128 | // a helper to process the timeout argument of linda:send() and linda:receive() | ||
129 | [[nodiscard]] | ||
130 | static auto ProcessTimeoutArg(lua_State* const L_) | ||
131 | { | ||
132 | StackIndex _key_i{ 2 }; // index of first slot, if timeout not there | ||
133 | |||
134 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; | ||
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) }; | ||
137 | if (_duration.count() >= 0.0) { | ||
138 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(_duration); | ||
139 | } else { | ||
140 | raise_luaL_argerror(L_, StackIndex{ 2 }, "duration cannot be < 0"); | ||
141 | } | ||
142 | ++_key_i; | ||
143 | } else if (lua_isnil(L_, 2)) { // alternate explicit "infinite timeout" by passing nil before the slot | ||
144 | ++_key_i; | ||
145 | } | ||
146 | return std::make_pair(_key_i, _until); | ||
147 | } | ||
148 | |||
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 | // ############################################################################################# | ||
186 | |||
187 | // the implementation for linda:receive() and linda:receive_batched() | ||
188 | static int ReceiveInternal(lua_State* const L_, bool const batched_) | ||
189 | { | ||
190 | Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; | ||
191 | |||
192 | auto const [_key_i, _until] = ProcessTimeoutArg(L_); | ||
193 | |||
194 | keeper_api_t _selected_keeper_receive{ nullptr }; | ||
195 | int _expected_pushed_min{ 0 }, _expected_pushed_max{ 0 }; | ||
196 | // are we in batched mode? | ||
197 | if (batched_) { | ||
198 | // make sure the keys are of a valid type | ||
199 | CheckKeyTypes(L_, _key_i, _key_i); | ||
200 | // receive multiple values from a single slot | ||
201 | _selected_keeper_receive = KEEPER_API(receive_batched); | ||
202 | // we expect a user-defined amount of return value | ||
203 | _expected_pushed_min = (int) luaL_checkinteger(L_, _key_i + 1); | ||
204 | if (_expected_pushed_min < 1) { | ||
205 | raise_luaL_argerror(L_, StackIndex{ _key_i + 1 }, "bad min count"); | ||
206 | } | ||
207 | _expected_pushed_max = (int) luaL_optinteger(L_, _key_i + 2, _expected_pushed_min); | ||
208 | // don't forget to count the slot in addition to the values | ||
209 | ++_expected_pushed_min; | ||
210 | ++_expected_pushed_max; | ||
211 | if (_expected_pushed_min > _expected_pushed_max) { | ||
212 | raise_luaL_argerror(L_, StackIndex{ _key_i + 2 }, "batched min/max error"); | ||
213 | } | ||
214 | } else { | ||
215 | // make sure the keys are of a valid type | ||
216 | CheckKeyTypes(L_, _key_i, StackIndex{ lua_gettop(L_) }); | ||
217 | // receive a single value, checking multiple slots | ||
218 | _selected_keeper_receive = KEEPER_API(receive); | ||
219 | // we expect a single (value, slot) pair of returned values | ||
220 | _expected_pushed_min = _expected_pushed_max = 2; | ||
221 | } | ||
222 | |||
223 | Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) }; | ||
224 | Keeper* const _keeper{ _linda->whichKeeper() }; | ||
225 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ static_cast<lua_State*>(nullptr) } }; | ||
226 | if (_K == nullptr) | ||
227 | return 0; | ||
228 | |||
229 | CancelRequest _cancel{ CancelRequest::None }; | ||
230 | KeeperCallResult _pushed{}; | ||
231 | |||
232 | STACK_CHECK_START_REL(_K, 0); | ||
233 | for (bool _try_again{ true };;) { | ||
234 | if (_lane != nullptr) { | ||
235 | _cancel = _lane->cancelRequest.load(std::memory_order_relaxed); | ||
236 | } | ||
237 | _cancel = (_cancel != CancelRequest::None) | ||
238 | ? _cancel | ||
239 | : ((_linda->cancelStatus == Linda::Cancelled) ? CancelRequest::Soft : CancelRequest::None); | ||
240 | |||
241 | // if user wants to cancel, or looped because of a timeout, the call returns without sending anything | ||
242 | if (!_try_again || _cancel != CancelRequest::None) { | ||
243 | _pushed.emplace(0); | ||
244 | break; | ||
245 | } | ||
246 | |||
247 | // all arguments of receive() but the first are passed to the keeper's receive function | ||
248 | STACK_CHECK(_K, 0); | ||
249 | _pushed = keeper_call(_K, _selected_keeper_receive, L_, _linda, _key_i); | ||
250 | if (!_pushed.has_value()) { | ||
251 | break; | ||
252 | } | ||
253 | if (_pushed.value() > 0) { | ||
254 | LUA_ASSERT(L_, _pushed.value() >= _expected_pushed_min && _pushed.value() <= _expected_pushed_max); | ||
255 | if (kRestrictedChannel.equals(L_, StackIndex{ kIdxTop })) { | ||
256 | raise_luaL_error(L_, "Key is restricted"); | ||
257 | } | ||
258 | _linda->readHappened.notify_all(); | ||
259 | break; | ||
260 | } | ||
261 | |||
262 | if (std::chrono::steady_clock::now() >= _until) { | ||
263 | break; /* instant timeout */ | ||
264 | } | ||
265 | |||
266 | // nothing received, wait until timeout or signalled that we should try again | ||
267 | _try_again = WaitInternal(L_, _lane, _linda, _keeper, _linda->writeHappened, _until); | ||
268 | } | ||
269 | STACK_CHECK(_K, 0); | ||
270 | |||
271 | if (!_pushed.has_value()) { | ||
272 | raise_luaL_error(L_, "tried to copy unsupported types"); | ||
273 | } | ||
274 | |||
275 | switch (_cancel) { | ||
276 | case CancelRequest::None: | ||
277 | { | ||
278 | int const _nbPushed{ _pushed.value() }; | ||
279 | if (_nbPushed == 0) { | ||
280 | // not enough data in the linda slot to fulfill the request, return nil, "timeout" | ||
281 | lua_pushnil(L_); | ||
282 | luaW_pushstring(L_, "timeout"); | ||
283 | return 2; | ||
284 | } | ||
285 | return _nbPushed; | ||
286 | } | ||
287 | |||
288 | case CancelRequest::Soft: | ||
289 | // if user wants to soft-cancel, the call returns nil, kCancelError | ||
290 | lua_pushnil(L_); | ||
291 | kCancelError.pushKey(L_); | ||
292 | return 2; | ||
293 | |||
294 | case CancelRequest::Hard: | ||
295 | // raise an error interrupting execution only in case of hard cancel | ||
296 | raise_cancel_error(L_); // raises an error and doesn't return | ||
297 | |||
298 | default: | ||
299 | raise_luaL_error(L_, "internal error: unknown cancel request"); | ||
300 | } | ||
301 | } | ||
302 | |||
303 | // ############################################################################################# | ||
128 | // ############################################################################################# | 304 | // ############################################################################################# |
129 | } // namespace | 305 | } // namespace |
130 | // ################################################################################################# | 306 | // ################################################################################################# |
@@ -138,9 +314,10 @@ LUAG_FUNC(linda); | |||
138 | // ################################################################################################# | 314 | // ################################################################################################# |
139 | // ################################################################################################# | 315 | // ################################################################################################# |
140 | 316 | ||
141 | Linda::Linda(Universe* const U_, LindaGroup const group_, std::string_view const& name_) | 317 | Linda::Linda(Universe* const U_, std::string_view const& name_, lua_Duration const wake_period_, LindaGroup const group_) |
142 | : DeepPrelude{ LindaFactory::Instance } | 318 | : DeepPrelude{ LindaFactory::Instance } |
143 | , U{ U_ } | 319 | , U{ U_ } |
320 | , wakePeriod{ wake_period_ } | ||
144 | , keeperIndex{ group_ % U_->keepers.getNbKeepers() } | 321 | , keeperIndex{ group_ % U_->keepers.getNbKeepers() } |
145 | { | 322 | { |
146 | setName(name_); | 323 | setName(name_); |
@@ -161,6 +338,7 @@ Keeper* Linda::acquireKeeper() const | |||
161 | Keeper* const _keeper{ whichKeeper() }; | 338 | Keeper* const _keeper{ whichKeeper() }; |
162 | if (_keeper) { | 339 | if (_keeper) { |
163 | _keeper->mutex.lock(); | 340 | _keeper->mutex.lock(); |
341 | keeperOperationCount.fetch_add(1, std::memory_order_seq_cst); | ||
164 | } | 342 | } |
165 | return _keeper; | 343 | return _keeper; |
166 | } | 344 | } |
@@ -172,13 +350,17 @@ Linda* Linda::CreateTimerLinda(lua_State* const L_) | |||
172 | STACK_CHECK_START_REL(L_, 0); // L_: | 350 | STACK_CHECK_START_REL(L_, 0); // L_: |
173 | // Initialize 'timerLinda'; a common Linda object shared by all states | 351 | // Initialize 'timerLinda'; a common Linda object shared by all states |
174 | lua_pushcfunction(L_, LG_linda); // L_: lanes.linda | 352 | lua_pushcfunction(L_, LG_linda); // L_: lanes.linda |
175 | luaG_pushstring(L_, "lanes-timer"); // L_: lanes.linda "lanes-timer" | 353 | lua_createtable(L_, 0, 3); // L_: lanes.linda {} |
176 | lua_pushinteger(L_, 0); // L_: lanes.linda "lanes-timer" 0 | 354 | luaW_pushstring(L_, "lanes-timer"); // L_: lanes.linda {} "lanes-timer" |
177 | lua_call(L_, 2, 1); // L_: linda | 355 | luaW_setfield(L_, StackIndex{ -2 }, std::string_view{ "name" }); // L_: lanes.linda { .name="lanes-timer" } |
356 | lua_pushinteger(L_, 0); // L_: lanes.linda { .name="lanes-timer" } 0 | ||
357 | luaW_setfield(L_, StackIndex{ -2 }, std::string_view{ "group" }); // L_: lanes.linda { .name="lanes-timer" .group = 0 } | ||
358 | // note that wake_period is not set (will default to the value in the universe) | ||
359 | lua_call(L_, 1, 1); // L_: linda | ||
178 | STACK_CHECK(L_, 1); | 360 | STACK_CHECK(L_, 1); |
179 | 361 | ||
180 | // Proxy userdata contents is only a 'DeepPrelude*' pointer | 362 | // Proxy userdata contents is only a 'DeepPrelude*' pointer |
181 | auto const _timerLinda{ *luaG_tofulluserdata<Linda*>(L_, kIdxTop) }; | 363 | auto const _timerLinda{ *luaW_tofulluserdata<Linda*>(L_, kIdxTop) }; |
182 | // 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. |
183 | _timerLinda->refcount.fetch_add(1, std::memory_order_relaxed); | 365 | _timerLinda->refcount.fetch_add(1, std::memory_order_relaxed); |
184 | lua_pop(L_, 1); // L_: | 366 | lua_pop(L_, 1); // L_: |
@@ -241,7 +423,6 @@ int Linda::ProtectedCall(lua_State* const L_, lua_CFunction const f_) | |||
241 | // doing LindaFactory::deleteDeepObjectInternal -> keeper_call(clear) | 423 | // doing LindaFactory::deleteDeepObjectInternal -> keeper_call(clear) |
242 | lua_gc(L_, LUA_GCSTOP, 0); | 424 | lua_gc(L_, LUA_GCSTOP, 0); |
243 | 425 | ||
244 | LUA_ASSERT_CODE(auto const _koip{ _linda->startKeeperOperation(L_) }); | ||
245 | // 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 |
246 | LUA_ASSERT(L_, lua_gettop(_K) == 0); | 427 | LUA_ASSERT(L_, lua_gettop(_K) == 0); |
247 | 428 | ||
@@ -249,7 +430,7 @@ int Linda::ProtectedCall(lua_State* const L_, lua_CFunction const f_) | |||
249 | lua_pushcfunction(L_, f_); | 430 | lua_pushcfunction(L_, f_); |
250 | lua_insert(L_, 1); | 431 | lua_insert(L_, 1); |
251 | // do a protected call | 432 | // do a protected call |
252 | 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)) }; |
253 | // 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 |
254 | lua_settop(_K, 0); | 435 | lua_settop(_K, 0); |
255 | 436 | ||
@@ -271,7 +452,7 @@ int Linda::ProtectedCall(lua_State* const L_, lua_CFunction const f_) | |||
271 | 452 | ||
272 | void Linda::pushCancelString(lua_State* L_) const | 453 | void Linda::pushCancelString(lua_State* L_) const |
273 | { | 454 | { |
274 | luaG_pushstring(L_, cancelStatus == Status::Cancelled ? "cancelled" : "active"); | 455 | luaW_pushstring(L_, cancelStatus == Status::Cancelled ? "cancelled" : "active"); |
275 | } | 456 | } |
276 | 457 | ||
277 | // ################################################################################################# | 458 | // ################################################################################################# |
@@ -280,6 +461,7 @@ void Linda::releaseKeeper(Keeper* const keeper_) const | |||
280 | { | 461 | { |
281 | 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 |
282 | assert(keeper_ == whichKeeper()); | 463 | assert(keeper_ == whichKeeper()); |
464 | keeperOperationCount.fetch_sub(1, std::memory_order_seq_cst); | ||
283 | keeper_->mutex.unlock(); | 465 | keeper_->mutex.unlock(); |
284 | } | 466 | } |
285 | } | 467 | } |
@@ -323,7 +505,7 @@ void Linda::setName(std::string_view const& name_) | |||
323 | LUAG_FUNC(linda_cancel) | 505 | LUAG_FUNC(linda_cancel) |
324 | { | 506 | { |
325 | Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; | 507 | Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; |
326 | std::string_view const _who{ luaG_optstring(L_, StackIndex{ 2 }, "both") }; | 508 | std::string_view const _who{ luaW_optstring(L_, StackIndex{ 2 }, "both") }; |
327 | // 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 |
328 | 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"); |
329 | 511 | ||
@@ -411,13 +593,13 @@ static int linda_index_string(lua_State* L_) | |||
411 | Linda* const _linda{ ToLinda<false>(L_, kIdxSelf) }; | 593 | Linda* const _linda{ ToLinda<false>(L_, kIdxSelf) }; |
412 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: linda "key" | 594 | LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: linda "key" |
413 | 595 | ||
414 | std::string_view const _keystr{ luaG_tostring(L_, kIdxKey) }; | 596 | std::string_view const _keystr{ luaW_tostring(L_, kIdxKey) }; |
415 | 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 |
416 | 598 | ||
417 | // look in metatable first | 599 | // look in metatable first |
418 | lua_getmetatable(L_, kIdxSelf); // L_: linda "key" mt | 600 | lua_getmetatable(L_, kIdxSelf); // L_: linda "key" mt |
419 | lua_replace(L_, -3); // L_: mt "key" | 601 | lua_replace(L_, -3); // L_: mt "key" |
420 | 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 |
421 | return 1; // done | 603 | return 1; // done |
422 | } | 604 | } |
423 | 605 | ||
@@ -437,12 +619,12 @@ static LUAG_FUNC(linda_index) | |||
437 | static constexpr StackIndex kIdxKey{ 2 }; | 619 | static constexpr StackIndex kIdxKey{ 2 }; |
438 | LUA_ASSERT(L_, lua_gettop(L_) == 2); | 620 | LUA_ASSERT(L_, lua_gettop(L_) == 2); |
439 | 621 | ||
440 | switch (luaG_type(L_, kIdxKey)) { | 622 | switch (luaW_type(L_, kIdxKey)) { |
441 | case LuaType::STRING: | 623 | case LuaType::STRING: |
442 | 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 |
443 | 625 | ||
444 | default: // unknown key | 626 | default: // unknown key |
445 | 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()); |
446 | } | 628 | } |
447 | } | 629 | } |
448 | 630 | ||
@@ -585,7 +767,7 @@ LUAG_FUNC(linda_limit) | |||
585 | int const _nargs{ lua_gettop(L_) }; | 767 | int const _nargs{ lua_gettop(L_) }; |
586 | 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"); |
587 | // make sure we got a numeric limit, or "unlimited", (or nothing) | 769 | // make sure we got a numeric limit, or "unlimited", (or nothing) |
588 | bool const _unlimited{ luaG_tostring(L_, StackIndex{ 3 }) == "unlimited" }; | 770 | bool const _unlimited{ luaW_tostring(L_, StackIndex{ 3 }) == "unlimited" }; |
589 | 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)) }; |
590 | if (_val < 0) { | 772 | if (_val < 0) { |
591 | raise_luaL_argerror(L_, StackIndex{ 3 }, "limit must be >= 0"); | 773 | raise_luaL_argerror(L_, StackIndex{ 3 }, "limit must be >= 0"); |
@@ -596,23 +778,23 @@ LUAG_FUNC(linda_limit) | |||
596 | KeeperCallResult _pushed; | 778 | KeeperCallResult _pushed; |
597 | if (_linda->cancelStatus == Linda::Active) { | 779 | if (_linda->cancelStatus == Linda::Active) { |
598 | if (_unlimited) { | 780 | if (_unlimited) { |
599 | 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"); |
600 | // 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!) |
601 | lua_pop(L_, 1); // L_: linda slot | 783 | lua_pop(L_, 1); // L_: linda slot |
602 | lua_pushinteger(L_, -1); // L_: linda slot nil | 784 | lua_pushinteger(L_, -1); // L_: linda slot nil |
603 | } | 785 | } |
604 | Keeper* const _keeper{ _linda->whichKeeper() }; | 786 | Keeper* const _keeper{ _linda->whichKeeper() }; |
605 | _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 }); |
606 | 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); |
607 | if (_nargs == 3) { // 3 args: setting the limit | 789 | if (_nargs == 3) { // 3 args: setting the limit |
608 | // 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 |
609 | 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 |
610 | if (lua_toboolean(L_, -2)) { | 792 | if (lua_toboolean(L_, -2)) { |
611 | _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 |
612 | } | 794 | } |
613 | } else { // 2 args: reading the limit | 795 | } else { // 2 args: reading the limit |
614 | // reading the limit: a number >=0 or "unlimited" | 796 | // reading the limit: a number >=0 or "unlimited" |
615 | 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"); |
616 | } | 798 | } |
617 | } else { // linda is cancelled | 799 | } else { // linda is cancelled |
618 | // do nothing and return nil,lanes.cancel_error | 800 | // do nothing and return nil,lanes.cancel_error |
@@ -630,163 +812,25 @@ LUAG_FUNC(linda_limit) | |||
630 | // ################################################################################################# | 812 | // ################################################################################################# |
631 | 813 | ||
632 | /* | 814 | /* |
633 | * 2 modes of operation | 815 | * [val, slot] = linda:receive([timeout_secs_num=nil], key_num|str|bool|lightuserdata [, ...] ) |
634 | * [val, slot]= linda:receive([timeout_secs_num=nil], key_num|str|bool|lightuserdata [, ...] ) | ||
635 | * Consumes a single value from the Linda, in any slot. | 816 | * Consumes a single value from the Linda, in any slot. |
636 | * Returns: received value (which is consumed from the slot), and the slot which had it | 817 | * Returns: received value (which is consumed from the slot), and the slot which had it |
637 | |||
638 | * [val1, ... valCOUNT]= linda_receive( linda_ud, [timeout_secs_num=-1], linda.batched, key_num|str|bool|lightuserdata, min_COUNT[, max_COUNT]) | ||
639 | * Consumes between min_COUNT and max_COUNT values from the linda, from a single slot. | ||
640 | * returns the actual consumed values, or nil if there weren't enough values to consume | ||
641 | */ | 818 | */ |
642 | LUAG_FUNC(linda_receive) | 819 | LUAG_FUNC(linda_receive) |
643 | { | 820 | { |
644 | static constexpr lua_CFunction _receive{ | 821 | return Linda::ProtectedCall(L_, [](lua_State* const L_) { return ReceiveInternal(L_, false); }); |
645 | +[](lua_State* const L_) { | 822 | } |
646 | Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; | ||
647 | StackIndex _key_i{ 2 }; // index of first slot, if timeout not there | ||
648 | |||
649 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; | ||
650 | if (luaG_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion | ||
651 | lua_Duration const _duration{ lua_tonumber(L_, 2) }; | ||
652 | if (_duration.count() >= 0.0) { | ||
653 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(_duration); | ||
654 | } else { | ||
655 | raise_luaL_argerror(L_, StackIndex{ 2 }, "duration cannot be < 0"); | ||
656 | } | ||
657 | ++_key_i; | ||
658 | } else if (lua_isnil(L_, 2)) { // alternate explicit "infinite timeout" by passing nil before the slot | ||
659 | ++_key_i; | ||
660 | } | ||
661 | |||
662 | keeper_api_t _selected_keeper_receive{ nullptr }; | ||
663 | int _expected_pushed_min{ 0 }, _expected_pushed_max{ 0 }; | ||
664 | // are we in batched mode? | ||
665 | if (kLindaBatched.equals(L_, _key_i)) { | ||
666 | // no need to pass linda.batched in the keeper state | ||
667 | ++_key_i; | ||
668 | // make sure the keys are of a valid type | ||
669 | CheckKeyTypes(L_, _key_i, _key_i); | ||
670 | // receive multiple values from a single slot | ||
671 | _selected_keeper_receive = KEEPER_API(receive_batched); | ||
672 | // we expect a user-defined amount of return value | ||
673 | _expected_pushed_min = (int) luaL_checkinteger(L_, _key_i + 1); | ||
674 | if (_expected_pushed_min < 1) { | ||
675 | raise_luaL_argerror(L_, StackIndex{ _key_i + 1 }, "bad min count"); | ||
676 | } | ||
677 | _expected_pushed_max = (int) luaL_optinteger(L_, _key_i + 2, _expected_pushed_min); | ||
678 | // don't forget to count the slot in addition to the values | ||
679 | ++_expected_pushed_min; | ||
680 | ++_expected_pushed_max; | ||
681 | if (_expected_pushed_min > _expected_pushed_max) { | ||
682 | raise_luaL_argerror(L_, StackIndex{ _key_i + 2 }, "batched min/max error"); | ||
683 | } | ||
684 | } else { | ||
685 | // make sure the keys are of a valid type | ||
686 | CheckKeyTypes(L_, _key_i, StackIndex{ lua_gettop(L_) }); | ||
687 | // receive a single value, checking multiple slots | ||
688 | _selected_keeper_receive = KEEPER_API(receive); | ||
689 | // we expect a single (value, slot) pair of returned values | ||
690 | _expected_pushed_min = _expected_pushed_max = 2; | ||
691 | } | ||
692 | |||
693 | Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) }; | ||
694 | Keeper* const _keeper{ _linda->whichKeeper() }; | ||
695 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ static_cast<lua_State*>(nullptr) } }; | ||
696 | if (_K == nullptr) | ||
697 | return 0; | ||
698 | |||
699 | CancelRequest _cancel{ CancelRequest::None }; | ||
700 | KeeperCallResult _pushed{}; | ||
701 | STACK_CHECK_START_REL(_K, 0); | ||
702 | for (bool _try_again{ true };;) { | ||
703 | if (_lane != nullptr) { | ||
704 | _cancel = _lane->cancelRequest.load(std::memory_order_relaxed); | ||
705 | } | ||
706 | _cancel = (_cancel != CancelRequest::None) | ||
707 | ? _cancel | ||
708 | : ((_linda->cancelStatus == Linda::Cancelled) ? CancelRequest::Soft : CancelRequest::None); | ||
709 | // if user wants to cancel, or looped because of a timeout, the call returns without sending anything | ||
710 | if (!_try_again || _cancel != CancelRequest::None) { | ||
711 | _pushed.emplace(0); | ||
712 | break; | ||
713 | } | ||
714 | |||
715 | // all arguments of receive() but the first are passed to the keeper's receive function | ||
716 | _pushed = keeper_call(_K, _selected_keeper_receive, L_, _linda, _key_i); | ||
717 | if (!_pushed.has_value()) { | ||
718 | break; | ||
719 | } | ||
720 | if (_pushed.value() > 0) { | ||
721 | LUA_ASSERT(L_, _pushed.value() >= _expected_pushed_min && _pushed.value() <= _expected_pushed_max); | ||
722 | if (kRestrictedChannel.equals(L_, StackIndex{ kIdxTop })) { | ||
723 | raise_luaL_error(L_, "Key is restricted"); | ||
724 | } | ||
725 | _linda->readHappened.notify_all(); | ||
726 | break; | ||
727 | } | ||
728 | |||
729 | if (std::chrono::steady_clock::now() >= _until) { | ||
730 | break; /* instant timeout */ | ||
731 | } | ||
732 | |||
733 | // nothing received, wait until timeout or signalled that we should try again | ||
734 | { | ||
735 | Lane::Status _prev_status{ Lane::Error }; // prevent 'might be used uninitialized' warnings | ||
736 | if (_lane != nullptr) { | ||
737 | // change status of lane to "waiting" | ||
738 | _prev_status = _lane->status.load(std::memory_order_acquire); // Running, most likely | ||
739 | LUA_ASSERT(L_, _prev_status == Lane::Running); // but check, just in case | ||
740 | LUA_ASSERT(L_, _lane->waiting_on == nullptr); | ||
741 | _lane->waiting_on = &_linda->writeHappened; | ||
742 | _lane->status.store(Lane::Waiting, std::memory_order_release); | ||
743 | } | ||
744 | // not enough data to read: wakeup when data was sent, or when timeout is reached | ||
745 | std::unique_lock<std::mutex> _guard{ _keeper->mutex, std::adopt_lock }; | ||
746 | std::cv_status const _status{ _linda->writeHappened.wait_until(_guard, _until) }; | ||
747 | _guard.release(); // we don't want to unlock the mutex on exit! | ||
748 | _try_again = (_status == std::cv_status::no_timeout); // detect spurious wakeups | ||
749 | if (_lane != nullptr) { | ||
750 | _lane->waiting_on = nullptr; | ||
751 | _lane->status.store(_prev_status, std::memory_order_release); | ||
752 | } | ||
753 | } | ||
754 | } | ||
755 | STACK_CHECK(_K, 0); | ||
756 | |||
757 | if (!_pushed.has_value()) { | ||
758 | raise_luaL_error(L_, "tried to copy unsupported types"); | ||
759 | } | ||
760 | |||
761 | switch (_cancel) { | ||
762 | case CancelRequest::None: | ||
763 | { | ||
764 | int const _nbPushed{ _pushed.value() }; | ||
765 | if (_nbPushed == 0) { | ||
766 | // not enough data in the linda slot to fulfill the request, return nil, "timeout" | ||
767 | lua_pushnil(L_); | ||
768 | luaG_pushstring(L_, "timeout"); | ||
769 | return 2; | ||
770 | } | ||
771 | return _nbPushed; | ||
772 | } | ||
773 | |||
774 | case CancelRequest::Soft: | ||
775 | // if user wants to soft-cancel, the call returns nil, kCancelError | ||
776 | lua_pushnil(L_); | ||
777 | kCancelError.pushKey(L_); | ||
778 | return 2; | ||
779 | 823 | ||
780 | case CancelRequest::Hard: | 824 | // ################################################################################################# |
781 | // raise an error interrupting execution only in case of hard cancel | ||
782 | raise_cancel_error(L_); // raises an error and doesn't return | ||
783 | 825 | ||
784 | default: | 826 | /* |
785 | raise_luaL_error(L_, "internal error: unknown cancel request"); | 827 | * [val1, ... valCOUNT] = linda_receive_batched( linda_ud, [timeout_secs_num=-1], key_num|str|bool|lightuserdata, min_COUNT[, max_COUNT]) |
786 | } | 828 | * Consumes between min_COUNT and max_COUNT values from the linda, from a single slot. |
787 | } | 829 | * returns the actual consumed values, or nil if there weren't enough values to consume |
788 | }; | 830 | */ |
789 | return Linda::ProtectedCall(L_, _receive); | 831 | LUAG_FUNC(linda_receive_batched) |
832 | { | ||
833 | return Linda::ProtectedCall(L_, [](lua_State* const L_) { return ReceiveInternal(L_, true); }); | ||
790 | } | 834 | } |
791 | 835 | ||
792 | // ################################################################################################# | 836 | // ################################################################################################# |
@@ -806,7 +850,7 @@ LUAG_FUNC(linda_restrict) | |||
806 | int const _nargs{ lua_gettop(L_) }; | 850 | int const _nargs{ lua_gettop(L_) }; |
807 | 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"); |
808 | // make sure we got a known restrict mode, (or nothing) | 852 | // make sure we got a known restrict mode, (or nothing) |
809 | std::string_view const _mode{ luaG_tostring(L_, StackIndex{ 3 }) }; | 853 | std::string_view const _mode{ luaW_tostring(L_, StackIndex{ 3 }) }; |
810 | if (!_mode.empty() && (_mode != "none" && _mode != "set/get" && _mode != "send/receive")) { | 854 | if (!_mode.empty() && (_mode != "none" && _mode != "set/get" && _mode != "send/receive")) { |
811 | raise_luaL_argerror(L_, StackIndex{ 3 }, "unknown restrict mode"); | 855 | raise_luaL_argerror(L_, StackIndex{ 3 }, "unknown restrict mode"); |
812 | } | 856 | } |
@@ -818,7 +862,7 @@ LUAG_FUNC(linda_restrict) | |||
818 | Keeper* const _keeper{ _linda->whichKeeper() }; | 862 | Keeper* const _keeper{ _linda->whichKeeper() }; |
819 | _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 }); |
820 | // 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 |
821 | 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); |
822 | } else { // linda is cancelled | 866 | } else { // linda is cancelled |
823 | // do nothing and return nil,lanes.cancel_error | 867 | // do nothing and return nil,lanes.cancel_error |
824 | lua_pushnil(L_); | 868 | lua_pushnil(L_); |
@@ -848,20 +892,8 @@ LUAG_FUNC(linda_send) | |||
848 | static constexpr lua_CFunction _send{ | 892 | static constexpr lua_CFunction _send{ |
849 | +[](lua_State* const L_) { | 893 | +[](lua_State* const L_) { |
850 | Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; | 894 | Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; |
851 | StackIndex _key_i{ 2 }; // index of first slot, if timeout not there | ||
852 | 895 | ||
853 | std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; | 896 | auto const [_key_i, _until] = ProcessTimeoutArg(L_); |
854 | if (luaG_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion | ||
855 | lua_Duration const _duration{ lua_tonumber(L_, 2) }; | ||
856 | if (_duration.count() >= 0.0) { | ||
857 | _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(_duration); | ||
858 | } else { | ||
859 | raise_luaL_argerror(L_, StackIndex{ 2 }, "duration cannot be < 0"); | ||
860 | } | ||
861 | ++_key_i; | ||
862 | } else if (lua_isnil(L_, 2)) { // alternate explicit "infinite timeout" by passing nil before the slot | ||
863 | ++_key_i; | ||
864 | } | ||
865 | 897 | ||
866 | // make sure the slot is of a valid type | 898 | // make sure the slot is of a valid type |
867 | CheckKeyTypes(L_, _key_i, _key_i); | 899 | CheckKeyTypes(L_, _key_i, _key_i); |
@@ -873,78 +905,60 @@ LUAG_FUNC(linda_send) | |||
873 | raise_luaL_error(L_, "no data to send"); | 905 | raise_luaL_error(L_, "no data to send"); |
874 | } | 906 | } |
875 | 907 | ||
908 | Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) }; | ||
909 | Keeper* const _keeper{ _linda->whichKeeper() }; | ||
910 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ static_cast<lua_State*>(nullptr) } }; | ||
911 | if (_K == nullptr) | ||
912 | return 0; | ||
913 | |||
876 | bool _ret{ false }; | 914 | bool _ret{ false }; |
877 | CancelRequest _cancel{ CancelRequest::None }; | 915 | CancelRequest _cancel{ CancelRequest::None }; |
878 | KeeperCallResult _pushed; | 916 | KeeperCallResult _pushed{}; |
879 | { | ||
880 | Lane* const _lane{ kLanePointerRegKey.readLightUserDataValue<Lane>(L_) }; | ||
881 | Keeper* const _keeper{ _linda->whichKeeper() }; | ||
882 | KeeperState const _K{ _keeper ? _keeper->K : KeeperState{ static_cast<lua_State*>(nullptr) } }; | ||
883 | if (_K == nullptr) | ||
884 | return 0; | ||
885 | |||
886 | STACK_CHECK_START_REL(_K, 0); | ||
887 | for (bool _try_again{ true };;) { | ||
888 | if (_lane != nullptr) { | ||
889 | _cancel = _lane->cancelRequest.load(std::memory_order_relaxed); | ||
890 | } | ||
891 | _cancel = (_cancel != CancelRequest::None) | ||
892 | ? _cancel | ||
893 | : ((_linda->cancelStatus == Linda::Cancelled) ? CancelRequest::Soft : CancelRequest::None); | ||
894 | // if user wants to cancel, or looped because of a timeout, the call returns without sending anything | ||
895 | if (!_try_again || _cancel != CancelRequest::None) { | ||
896 | _pushed.emplace(0); | ||
897 | break; | ||
898 | } | ||
899 | 917 | ||
900 | STACK_CHECK(_K, 0); | 918 | STACK_CHECK_START_REL(_K, 0); |
901 | _pushed = keeper_call(_K, KEEPER_API(send), L_, _linda, _key_i); | 919 | for (bool _try_again{ true };;) { |
902 | if (!_pushed.has_value()) { | 920 | if (_lane != nullptr) { |
903 | break; | 921 | _cancel = _lane->cancelRequest.load(std::memory_order_relaxed); |
904 | } | 922 | } |
905 | LUA_ASSERT(L_, _pushed.value() == 1); | 923 | _cancel = (_cancel != CancelRequest::None) |
924 | ? _cancel | ||
925 | : ((_linda->cancelStatus == Linda::Cancelled) ? CancelRequest::Soft : CancelRequest::None); | ||
906 | 926 | ||
907 | if (kRestrictedChannel.equals(L_, StackIndex{ kIdxTop })) { | 927 | // if user wants to cancel, or looped because of a timeout, the call returns without sending anything |
908 | raise_luaL_error(L_, "Key is restricted"); | 928 | if (!_try_again || _cancel != CancelRequest::None) { |
909 | } | 929 | _pushed.emplace(0); |
910 | _ret = lua_toboolean(L_, -1) ? true : false; | 930 | break; |
911 | lua_pop(L_, 1); | 931 | } |
912 | 932 | ||
913 | if (_ret) { | 933 | // all arguments of send() but the first are passed to the keeper's send function |
914 | // Wake up ALL waiting threads | 934 | STACK_CHECK(_K, 0); |
915 | _linda->writeHappened.notify_all(); | 935 | _pushed = keeper_call(_K, KEEPER_API(send), L_, _linda, _key_i); |
916 | break; | 936 | if (!_pushed.has_value()) { |
917 | } | 937 | break; |
938 | } | ||
939 | LUA_ASSERT(L_, _pushed.value() == 1); | ||
918 | 940 | ||
919 | // instant timout to bypass the wait syscall | 941 | if (kRestrictedChannel.equals(L_, StackIndex{ kIdxTop })) { |
920 | if (std::chrono::steady_clock::now() >= _until) { | 942 | raise_luaL_error(L_, "Key is restricted"); |
921 | break; /* no wait; instant timeout */ | 943 | } |
922 | } | 944 | _ret = lua_toboolean(L_, -1) ? true : false; |
945 | lua_pop(L_, 1); | ||
923 | 946 | ||
924 | // storage limit hit, wait until timeout or signalled that we should try again | 947 | if (_ret) { |
925 | { | 948 | // Wake up ALL waiting threads |
926 | Lane::Status _prev_status{ Lane::Error }; // prevent 'might be used uninitialized' warnings | 949 | _linda->writeHappened.notify_all(); |
927 | if (_lane != nullptr) { | 950 | break; |
928 | // change status of lane to "waiting" | ||
929 | _prev_status = _lane->status.load(std::memory_order_acquire); // Running, most likely | ||
930 | LUA_ASSERT(L_, _prev_status == Lane::Running); // but check, just in case | ||
931 | LUA_ASSERT(L_, _lane->waiting_on == nullptr); | ||
932 | _lane->waiting_on = &_linda->readHappened; | ||
933 | _lane->status.store(Lane::Waiting, std::memory_order_release); | ||
934 | } | ||
935 | // could not send because no room: wait until some data was read before trying again, or until timeout is reached | ||
936 | std::unique_lock<std::mutex> _guard{ _keeper->mutex, std::adopt_lock }; | ||
937 | std::cv_status const status{ _linda->readHappened.wait_until(_guard, _until) }; | ||
938 | _guard.release(); // we don't want to unlock the mutex on exit! | ||
939 | _try_again = (status == std::cv_status::no_timeout); // detect spurious wakeups | ||
940 | if (_lane != nullptr) { | ||
941 | _lane->waiting_on = nullptr; | ||
942 | _lane->status.store(_prev_status, std::memory_order_release); | ||
943 | } | ||
944 | } | ||
945 | } | 951 | } |
946 | STACK_CHECK(_K, 0); | 952 | |
953 | // instant timout to bypass the wait syscall | ||
954 | if (std::chrono::steady_clock::now() >= _until) { | ||
955 | break; /* no wait; instant timeout */ | ||
956 | } | ||
957 | |||
958 | // storage limit hit, wait until timeout or signalled that we should try again | ||
959 | _try_again = WaitInternal(L_, _lane, _linda, _keeper, _linda->readHappened, _until); | ||
947 | } | 960 | } |
961 | STACK_CHECK(_K, 0); | ||
948 | 962 | ||
949 | if (!_pushed.has_value()) { | 963 | if (!_pushed.has_value()) { |
950 | raise_luaL_error(L_, "tried to copy unsupported types"); | 964 | raise_luaL_error(L_, "tried to copy unsupported types"); |
@@ -968,7 +982,7 @@ LUAG_FUNC(linda_send) | |||
968 | } else { | 982 | } else { |
969 | // 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" |
970 | lua_pushnil(L_); | 984 | lua_pushnil(L_); |
971 | luaG_pushstring(L_, "timeout"); | 985 | luaW_pushstring(L_, "timeout"); |
972 | return 2; | 986 | return 2; |
973 | } | 987 | } |
974 | } | 988 | } |
@@ -1003,7 +1017,7 @@ LUAG_FUNC(linda_set) | |||
1003 | if (kRestrictedChannel.equals(L_, kIdxTop)) { | 1017 | if (kRestrictedChannel.equals(L_, kIdxTop)) { |
1004 | raise_luaL_error(L_, "Key is restricted"); | 1018 | raise_luaL_error(L_, "Key is restricted"); |
1005 | } | 1019 | } |
1006 | 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); |
1007 | 1021 | ||
1008 | if (_has_data) { | 1022 | if (_has_data) { |
1009 | // 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 |
@@ -1065,7 +1079,7 @@ LUAG_FUNC(linda_towatch) | |||
1065 | LUAG_FUNC(linda_wake) | 1079 | LUAG_FUNC(linda_wake) |
1066 | { | 1080 | { |
1067 | Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; | 1081 | Linda* const _linda{ ToLinda<false>(L_, StackIndex{ 1 }) }; |
1068 | std::string_view const _who{ luaG_optstring(L_, StackIndex{ 2 }, "both") }; | 1082 | std::string_view const _who{ luaW_optstring(L_, StackIndex{ 2 }, "both") }; |
1069 | // 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 |
1070 | 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"); |
1071 | 1085 | ||
@@ -1104,6 +1118,7 @@ namespace { | |||
1104 | { "get", LG_linda_get }, | 1118 | { "get", LG_linda_get }, |
1105 | { "limit", LG_linda_limit }, | 1119 | { "limit", LG_linda_limit }, |
1106 | { "receive", LG_linda_receive }, | 1120 | { "receive", LG_linda_receive }, |
1121 | { "receive_batched", LG_linda_receive_batched }, | ||
1107 | { "restrict", LG_linda_restrict }, | 1122 | { "restrict", LG_linda_restrict }, |
1108 | { "send", LG_linda_send }, | 1123 | { "send", LG_linda_send }, |
1109 | { "set", LG_linda_set }, | 1124 | { "set", LG_linda_set }, |
@@ -1120,88 +1135,77 @@ namespace { | |||
1120 | // ################################################################################################# | 1135 | // ################################################################################################# |
1121 | 1136 | ||
1122 | /* | 1137 | /* |
1123 | * ud = lanes.linda( [name[,group[,close_handler]]]) | 1138 | * ud = lanes.linda{.name = <string>, .group = <number>, .close_handler = <callable>, .wake_period = <number>} |
1124 | * | 1139 | * |
1125 | * returns a linda object, or raises an error if creation failed | 1140 | * returns a linda object, or raises an error if creation failed |
1126 | */ | 1141 | */ |
1127 | LUAG_FUNC(linda) | 1142 | LUAG_FUNC(linda) |
1128 | { | 1143 | { |
1129 | static constexpr StackIndex kLastArg{ LUA_VERSION_NUM >= 504 ? 3 : 2 }; | 1144 | // unpack the received table on the stack, putting name wake_period group close_handler in that order |
1130 | StackIndex const _top{ lua_gettop(L_) }; | 1145 | StackIndex const _top{ lua_gettop(L_) }; |
1131 | luaL_argcheck(L_, _top <= kLastArg, _top, "too many arguments"); | 1146 | luaL_argcheck(L_, _top <= 1, _top, "too many arguments"); |
1132 | StackIndex _closeHandlerIdx{}; | 1147 | if (_top == 0) { |
1133 | StackIndex _nameIdx{}; | 1148 | lua_settop(L_, 3); // L_: nil nil nil |
1134 | StackIndex _groupIdx{}; | 1149 | } |
1135 | for (StackIndex const _i : std::ranges::iota_view{ StackIndex{ 1 }, StackIndex{ _top + 1 }}) { | 1150 | else if (!lua_istable(L_, kIdxTop)) { |
1136 | switch (luaG_type(L_, _i)) { | 1151 | luaL_argerror(L_, 1, "expecting a table"); |
1152 | } else { | ||
1153 | auto* const _U{ Universe::Get(L_) }; | ||
1154 | lua_getfield(L_, 1, "wake_period"); // L_: {} wake_period | ||
1155 | if (lua_isnil(L_, kIdxTop)) { | ||
1156 | lua_pop(L_, 1); | ||
1157 | lua_pushnumber(L_, _U->lindaWakePeriod.count()); | ||
1158 | } else if (luaW_type(L_, kIdxTop) == LuaType::STRING) { | ||
1159 | if (luaW_tostring(L_, kIdxTop) != "never") { | ||
1160 | luaL_argerror(L_, 1, "invalid wake_period"); | ||
1161 | } else { | ||
1162 | lua_pop(L_, 1); | ||
1163 | lua_pushnumber(L_, 0); | ||
1164 | } | ||
1165 | } | ||
1166 | else { | ||
1167 | luaL_argcheck(L_, luaL_optnumber(L_, 2, 0) > 0, 1, "wake_period must be > 0"); | ||
1168 | } | ||
1169 | |||
1170 | lua_getfield(L_, 1, "group"); // L_: {} wake_period group | ||
1171 | int const _nbKeepers{ _U->keepers.getNbKeepers() }; | ||
1172 | if (lua_isnil(L_, kIdxTop)) { | ||
1173 | luaL_argcheck(L_, _nbKeepers < 2, 0, "Group is mandatory in multiple Keeper scenarios"); | ||
1174 | } else { | ||
1175 | int const _group{ static_cast<int>(lua_tointeger(L_, kIdxTop)) }; | ||
1176 | luaL_argcheck(L_, _group >= 0 && _group < _nbKeepers, 1, "group out of range"); | ||
1177 | } | ||
1178 | |||
1137 | #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 |
1138 | case LuaType::FUNCTION: | 1180 | lua_getfield(L_, 1, "close_handler"); // L_: {} wake_period group close_handler |
1139 | luaL_argcheck(L_, _closeHandlerIdx == 0, _i, "More than one __close handler"); | 1181 | LuaType const _handlerType{ luaW_type(L_, kIdxTop) }; |
1140 | _closeHandlerIdx = _i; | 1182 | if (_handlerType == LuaType::NIL) { |
1141 | break; | 1183 | lua_pop(L_, 1); // L_: {} wake_period group |
1142 | 1184 | } else if (_handlerType == LuaType::USERDATA || _handlerType == LuaType::TABLE) { | |
1143 | case LuaType::USERDATA: | 1185 | luaL_argcheck(L_, luaL_getmetafield(L_, kIdxTop, "__call") != 0, 1, "__close handler is not callable"); |
1144 | case LuaType::TABLE: | ||
1145 | luaL_argcheck(L_, _closeHandlerIdx == 0, _i, "More than one __close handler"); | ||
1146 | luaL_argcheck(L_, luaL_getmetafield(L_, _i, "__call") != 0, _i, "__close handler is not callable"); | ||
1147 | lua_pop(L_, 1); // luaL_getmetafield() pushed the field, we need to pop it | 1186 | lua_pop(L_, 1); // luaL_getmetafield() pushed the field, we need to pop it |
1148 | _closeHandlerIdx = _i; | 1187 | } else { |
1149 | break; | 1188 | luaL_argcheck(L_, _handlerType == LuaType::FUNCTION, 1, "__close handler is not a function"); |
1189 | } | ||
1150 | #endif // LUA_VERSION_NUM >= 504 | 1190 | #endif // LUA_VERSION_NUM >= 504 |
1151 | 1191 | ||
1152 | case LuaType::STRING: | 1192 | auto const _nameType{ luaW_getfield(L_, StackIndex{ 1 }, "name") }; // L_: {} wake_period group [close_handler] name |
1153 | luaL_argcheck(L_, _nameIdx == 0, _i, "More than one name"); | 1193 | luaL_argcheck(L_, _nameType == LuaType::NIL || _nameType == LuaType::STRING, 1, "name is not a string"); |
1154 | _nameIdx = _i; | 1194 | lua_replace(L_, 1); // L_: name wake_period group [close_handler] |
1155 | break; | ||
1156 | |||
1157 | case LuaType::NUMBER: | ||
1158 | luaL_argcheck(L_, _groupIdx == 0, _i, "More than one group"); | ||
1159 | _groupIdx = _i; | ||
1160 | break; | ||
1161 | |||
1162 | default: | ||
1163 | luaL_argcheck(L_, false, _i, "Bad argument type (should be a string, a number, or a callable type)"); | ||
1164 | } | ||
1165 | } | ||
1166 | |||
1167 | int const _nbKeepers{ Universe::Get(L_)->keepers.getNbKeepers() }; | ||
1168 | if (!_groupIdx) { | ||
1169 | luaL_argcheck(L_, _nbKeepers < 2, 0, "Group is mandatory in multiple Keeper scenarios"); | ||
1170 | } else { | ||
1171 | int const _group{ static_cast<int>(lua_tointeger(L_, _groupIdx)) }; | ||
1172 | luaL_argcheck(L_, _group >= 0 && _group < _nbKeepers, _groupIdx, "Group out of range"); | ||
1173 | } | 1195 | } |
1174 | 1196 | ||
1175 | // done with argument checking, let's proceed | 1197 | // done with argument checking, let's proceed |
1176 | if constexpr (LUA_VERSION_NUM >= 504) { | 1198 | if (lua_gettop(L_) == 4) { |
1177 | // make sure we have kMaxArgs arguments on the stack for processing, with name, group, and handler, in that order | ||
1178 | lua_settop(L_, kLastArg); // L_: a b c | ||
1179 | // If either index is 0, lua_settop() adjusted the stack with a nil in slot kLastArg | ||
1180 | lua_pushvalue(L_, _closeHandlerIdx ? _closeHandlerIdx : kLastArg); // L_: a b c close_handler | ||
1181 | lua_pushvalue(L_, _groupIdx ? _groupIdx : kLastArg); // L_: a b c close_handler group | ||
1182 | lua_pushvalue(L_, _nameIdx ? _nameIdx : kLastArg); // L_: a b c close_handler group name | ||
1183 | lua_replace(L_, 1); // L_: name b c close_handler group | ||
1184 | lua_replace(L_, 2); // L_: name group c close_handler | ||
1185 | lua_replace(L_, 3); // L_: name group close_handler | ||
1186 | |||
1187 | // if we have a __close handler, we need a uservalue slot to store it | 1199 | // if we have a __close handler, we need a uservalue slot to store it |
1188 | UserValueCount const _nuv{ _closeHandlerIdx ? 1 : 0 }; | 1200 | LindaFactory::Instance.pushDeepUserdata(DestState{ L_ }, UserValueCount{ 1 }); // L_: name wake_period group [close_handler] linda |
1189 | LindaFactory::Instance.pushDeepUserdata(DestState{ L_ }, _nuv); // L_: name group close_handler linda | 1201 | lua_replace(L_, 3); // L_: name wake_period linda close_handler |
1190 | if (_closeHandlerIdx != 0) { | 1202 | lua_setiuservalue(L_, StackIndex{ 3 }, UserValueIndex{ 1 }); // L_: name wake_period linda |
1191 | lua_replace(L_, 2); // L_: name linda close_handler | ||
1192 | lua_setiuservalue(L_, StackIndex{ 2 }, UserValueIndex{ 1 }); // L_: name linda | ||
1193 | } | ||
1194 | // depending on whether we have a handler or not, the stack is not in the same state at this point | 1203 | // depending on whether we have a handler or not, the stack is not in the same state at this point |
1195 | // just make sure we have our Linda at the top | 1204 | // just make sure we have our Linda at the top |
1196 | LUA_ASSERT(L_, ToLinda<true>(L_, kIdxTop)); | 1205 | LUA_ASSERT(L_, ToLinda<true>(L_, kIdxTop)); |
1197 | return 1; | 1206 | return 1; |
1198 | } else { // no to-be-closed support | 1207 | } else { // no to-be-closed support |
1199 | // ensure we have name, group in that order on the stack | 1208 | LindaFactory::Instance.pushDeepUserdata(DestState{ L_ }, UserValueCount{ 0 }); // L_: name wake_period group linda |
1200 | if (_nameIdx > _groupIdx) { | ||
1201 | lua_insert(L_, 1); // L_: name group | ||
1202 | } | ||
1203 | LindaFactory::Instance.pushDeepUserdata(DestState{ L_ }, UserValueCount{ 0 }); // L_: name group linda | ||
1204 | return 1; | 1209 | return 1; |
1205 | } | 1210 | } |
1206 | |||
1207 | } | 1211 | } |
diff --git a/src/linda.hpp b/src/linda.hpp index 01ca7e1..f02c46e 100644 --- a/src/linda.hpp +++ b/src/linda.hpp | |||
@@ -8,37 +8,12 @@ struct Keeper; | |||
8 | 8 | ||
9 | // ################################################################################################# | 9 | // ################################################################################################# |
10 | 10 | ||
11 | // xxh64 of string "kLindaBatched" generated at https://www.pelock.com/products/hash-calculator | ||
12 | static constexpr UniqueKey kLindaBatched{ 0xB8234DF772646567ull, "linda.batched" }; | ||
13 | |||
14 | // ################################################################################################# | ||
15 | |||
16 | DECLARE_UNIQUE_TYPE(LindaGroup, int); | 11 | DECLARE_UNIQUE_TYPE(LindaGroup, int); |
17 | 12 | ||
18 | class Linda final | 13 | class Linda final |
19 | : public DeepPrelude // Deep userdata MUST start with this header | 14 | : public DeepPrelude // Deep userdata MUST start with this header |
20 | { | 15 | { |
21 | public: | 16 | public: |
22 | class [[nodiscard]] KeeperOperationInProgress final | ||
23 | { | ||
24 | private: | ||
25 | Linda& linda; | ||
26 | [[maybe_unused]] lua_State* const L; // just here for inspection while debugging | ||
27 | |||
28 | public: | ||
29 | KeeperOperationInProgress(Linda& linda_, lua_State* const L_) | ||
30 | : linda{ linda_ } | ||
31 | , L{ L_ } | ||
32 | { | ||
33 | [[maybe_unused]] UnusedInt const _prev{ linda.keeperOperationCount.fetch_add(1, std::memory_order_seq_cst) }; | ||
34 | } | ||
35 | |||
36 | public: | ||
37 | ~KeeperOperationInProgress() | ||
38 | { | ||
39 | [[maybe_unused]] UnusedInt const _prev{ linda.keeperOperationCount.fetch_sub(1, std::memory_order_seq_cst) }; | ||
40 | } | ||
41 | }; | ||
42 | 17 | ||
43 | enum class [[nodiscard]] Status | 18 | enum class [[nodiscard]] Status |
44 | { | 19 | { |
@@ -47,19 +22,21 @@ class Linda final | |||
47 | }; | 22 | }; |
48 | using enum Status; | 23 | using enum Status; |
49 | 24 | ||
50 | private: | 25 | public: |
26 | Universe* const U{ nullptr }; // the universe this linda belongs to | ||
51 | 27 | ||
28 | private: | ||
52 | static constexpr size_t kEmbeddedNameLength = 24; | 29 | static constexpr size_t kEmbeddedNameLength = 24; |
53 | using EmbeddedName = std::array<char, kEmbeddedNameLength>; | 30 | using EmbeddedName = std::array<char, kEmbeddedNameLength>; |
54 | // 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 |
55 | std::variant<std::string_view, EmbeddedName> nameVariant{}; | 32 | std::variant<std::string_view, EmbeddedName> nameVariant{}; |
56 | // counts the keeper operations in progress | 33 | // counts the keeper operations in progress |
57 | std::atomic<int> keeperOperationCount{}; | 34 | mutable std::atomic<int> keeperOperationCount{}; |
35 | lua_Duration wakePeriod{}; | ||
58 | 36 | ||
59 | public: | 37 | public: |
60 | std::condition_variable readHappened{}; | 38 | std::condition_variable readHappened{}; |
61 | std::condition_variable writeHappened{}; | 39 | std::condition_variable writeHappened{}; |
62 | Universe* const U{ nullptr }; // the universe this linda belongs to | ||
63 | KeeperIndex const keeperIndex{ -1 }; // the keeper associated to this linda | 40 | KeeperIndex const keeperIndex{ -1 }; // the keeper associated to this linda |
64 | Status cancelStatus{ Status::Active }; | 41 | Status cancelStatus{ Status::Active }; |
65 | 42 | ||
@@ -73,7 +50,7 @@ class Linda final | |||
73 | static void operator delete(void* p_) { static_cast<Linda*>(p_)->U->internalAllocator.free(p_, sizeof(Linda)); } | 50 | static void operator delete(void* p_) { static_cast<Linda*>(p_)->U->internalAllocator.free(p_, sizeof(Linda)); } |
74 | 51 | ||
75 | ~Linda(); | 52 | ~Linda(); |
76 | Linda(Universe* U_, LindaGroup group_, std::string_view const& name_); | 53 | Linda(Universe* U_, std::string_view const& name_, lua_Duration wake_period_, LindaGroup group_); |
77 | Linda() = delete; | 54 | Linda() = delete; |
78 | // non-copyable, non-movable | 55 | // non-copyable, non-movable |
79 | Linda(Linda const&) = delete; | 56 | Linda(Linda const&) = delete; |
@@ -97,6 +74,8 @@ class Linda final | |||
97 | [[nodiscard]] | 74 | [[nodiscard]] |
98 | std::string_view getName() const; | 75 | std::string_view getName() const; |
99 | [[nodiscard]] | 76 | [[nodiscard]] |
77 | auto getWakePeriod() const { return wakePeriod; } | ||
78 | [[nodiscard]] | ||
100 | bool inKeeperOperation() const { return keeperOperationCount.load(std::memory_order_seq_cst) != 0; } | 79 | bool inKeeperOperation() const { return keeperOperationCount.load(std::memory_order_seq_cst) != 0; } |
101 | template <typename T = uintptr_t> | 80 | template <typename T = uintptr_t> |
102 | [[nodiscard]] | 81 | [[nodiscard]] |
@@ -111,7 +90,5 @@ class Linda final | |||
111 | static int ProtectedCall(lua_State* L_, lua_CFunction f_); | 90 | static int ProtectedCall(lua_State* L_, lua_CFunction f_); |
112 | void pushCancelString(lua_State* L_) const; | 91 | void pushCancelString(lua_State* L_) const; |
113 | [[nodiscard]] | 92 | [[nodiscard]] |
114 | KeeperOperationInProgress startKeeperOperation(lua_State* const L_) { return KeeperOperationInProgress{ *this, L_ }; }; | ||
115 | [[nodiscard]] | ||
116 | Keeper* whichKeeper() const { return U->keepers.getKeeper(keeperIndex); } | 93 | Keeper* whichKeeper() const { return U->keepers.getKeeper(keeperIndex); } |
117 | }; | 94 | }; |
diff --git a/src/lindafactory.cpp b/src/lindafactory.cpp index 6e3f759..483037f 100644 --- a/src/lindafactory.cpp +++ b/src/lindafactory.cpp | |||
@@ -47,26 +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 | |||
56 | // some constants | ||
57 | kLindaBatched.pushKey(L_); // L_: mt kLindaBatched | ||
58 | lua_setfield(L_, -2, "batched"); // L_: mt | ||
59 | 55 | ||
60 | kNilSentinel.pushKey(L_); // L_: mt kNilSentinel | 56 | kNilSentinel.pushKey(L_); // L_: mt kNilSentinel |
61 | lua_setfield(L_, -2, "null"); // L_: mt | 57 | lua_setfield(L_, -2, "null"); // L_: mt |
62 | 58 | ||
63 | // if the metatable contains __index, leave it as is | 59 | // if the metatable contains __index, leave it as is |
64 | if (luaG_getfield(L_, kIdxTop, kIndex) != LuaType::NIL) { // L_: mt __index | 60 | if (luaW_getfield(L_, kIdxTop, kIndex) != LuaType::NIL) { // L_: mt __index |
65 | lua_pop(L_, 1); // L_: mt __index | 61 | lua_pop(L_, 1); // L_: mt __index |
66 | } else { | 62 | } else { |
67 | // metatable is its own index | 63 | // metatable is its own index |
68 | lua_pushvalue(L_, kIdxTop); // L_: mt mt | 64 | lua_pushvalue(L_, kIdxTop); // L_: mt mt |
69 | luaG_setfield(L_, StackIndex{ -2 }, kIndex); // L_: mt | 65 | luaW_setfield(L_, StackIndex{ -2 }, kIndex); // L_: mt |
70 | } | 66 | } |
71 | 67 | ||
72 | STACK_CHECK(L_, 1); | 68 | STACK_CHECK(L_, 1); |
@@ -112,27 +108,30 @@ std::string_view LindaFactory::moduleName() const | |||
112 | 108 | ||
113 | DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* const L_) const | 109 | DeepPrelude* LindaFactory::newDeepObjectInternal(lua_State* const L_) const |
114 | { | 110 | { |
115 | // we always expect name and group at the bottom of the stack (either can be nil). any extra stuff we ignore and keep unmodified | 111 | STACK_CHECK_START_REL(L_, 0); |
116 | std::string_view _linda_name{ luaG_tostring(L_, StackIndex{ 1 }) }; | 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 |
117 | LindaGroup _linda_group{ static_cast<int>(lua_tointeger(L_, 2)) }; | 113 | std::string_view _linda_name{ luaW_tostring(L_, StackIndex{ 1 }) }; |
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)) }; | ||
118 | 116 | ||
119 | // store in the linda the location of the script that created it | 117 | // store in the linda the location of the script that created it |
120 | if (_linda_name == "auto") { | 118 | if (_linda_name == "auto") { |
121 | lua_Debug _ar; | 119 | lua_Debug _ar; |
122 | 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) |
123 | lua_getinfo(L_, "Sln", &_ar); | 121 | lua_getinfo(L_, "Sln", &_ar); |
124 | _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); |
125 | } else { | 123 | } else { |
126 | _linda_name = luaG_pushstring(L_, "<unresolved>"); | 124 | _linda_name = luaW_pushstring(L_, "<unresolved>"); |
127 | } | 125 | } |
128 | // 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 |
129 | LUA_ASSERT(L_, luaG_tostring(L_, StackIndex{ 1 }) == "auto"); | 127 | LUA_ASSERT(L_, luaW_tostring(L_, StackIndex{ 1 }) == "auto"); |
130 | lua_replace(L_, 1); | 128 | lua_replace(L_, 1); |
131 | } | 129 | } |
132 | 130 | ||
133 | // The deep data is allocated separately of Lua stack; we might no longer be around when last reference to it is being released. | 131 | // The deep data is allocated separately of Lua stack; we might no longer be around when last reference to it is being released. |
134 | // One can use any memory allocation scheme. Just don't use L's allocF because we don't know which state will get the honor of GCing the linda | 132 | // One can use any memory allocation scheme. Just don't use L's allocF because we don't know which state will get the honor of GCing the linda |
135 | Universe* const _U{ Universe::Get(L_) }; | 133 | Universe* const _U{ Universe::Get(L_) }; |
136 | Linda* const _linda{ new (_U) Linda{ _U, _linda_group, _linda_name } }; | 134 | Linda* const _linda{ new (_U) Linda{ _U, _linda_name, _wake_period, _linda_group } }; |
135 | STACK_CHECK(L_, 0); | ||
137 | return _linda; | 136 | return _linda; |
138 | } | 137 | } |
diff --git a/src/macros_and_utils.hpp b/src/macros_and_utils.hpp index 16011f7..1aca818 100644 --- a/src/macros_and_utils.hpp +++ b/src/macros_and_utils.hpp | |||
@@ -21,6 +21,7 @@ inline void STACK_GROW(lua_State* const L_, int const n_) | |||
21 | 21 | ||
22 | // ################################################################################################# | 22 | // ################################################################################################# |
23 | 23 | ||
24 | // 1 unit of lua_Duration lasts 1 second (using default period of std::ratio<1>) | ||
24 | using lua_Duration = std::chrono::template duration<lua_Number>; | 25 | using lua_Duration = std::chrono::template duration<lua_Number>; |
25 | 26 | ||
26 | // ################################################################################################# | 27 | // ################################################################################################# |
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 3e594ff..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 | ||
86 | static 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 |
90 | static void FAIL(char const* funcname_, DWORD const rc_) | 102 | |
103 | template <typename F, typename... ARGS> | ||
104 | void 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 | ||
124 | void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) | 142 | std::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 | ||
134 | void THREAD_SET_PRIORITY(std::thread& thread_, int prio_, [[maybe_unused]] bool sudo_) | 149 | [[nodiscard]] |
150 | void 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 | ||
146 | void THREAD_SET_AFFINITY(unsigned int aff_) | 158 | [[nodiscard]] |
159 | void 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]] | ||
168 | void 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 | ||
218 | static void _PT_FAIL(int rc, const char* name, const char* file, int line) | 238 | template <typename F, typename... ARGS> |
239 | void 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 |
238 | static int const gs_prio_remap[] = { | 258 | static 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 | ||
360 | void THREAD_SET_PRIORITY(int prio_, [[maybe_unused]] bool sudo_) | 380 | // ################################################################################################# |
381 | |||
382 | std::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 | |||
391 | void 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 | ||
375 | void THREAD_SET_PRIORITY(std::thread& thread_, int prio_, [[maybe_unused]] bool sudo_) | 406 | void 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 | ||
392 | void THREAD_SET_AFFINITY(unsigned int aff_) | 423 | void 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 | ||
399 | void THREAD_SET_AFFINITY(unsigned int aff_) | 430 | void 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,9 +477,11 @@ void THREAD_SETNAME(std::string_view const& name_) | |||
447 | 477 | ||
448 | void THREAD_SETNAME(std::string_view const& name_) | 478 | void 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_BSD && !defined __NetBSD__ | 482 | #if defined PLATFORM_MINGW |
483 | pthread_setname_np(pthread_self(), name_.data()); | ||
484 | #elif defined PLATFORM_BSD && !defined __NetBSD__ | ||
453 | pthread_set_name_np(pthread_self(), name_.data()); | 485 | pthread_set_name_np(pthread_self(), name_.data()); |
454 | #elif defined PLATFORM_BSD && defined __NetBSD__ | 486 | #elif defined PLATFORM_BSD && defined __NetBSD__ |
455 | pthread_setname_np(pthread_self(), "%s", (void*) name_.data()); | 487 | pthread_setname_np(pthread_self(), "%s", (void*) 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 | ||
77 | DECLARE_UNIQUE_TYPE(SudoFlag, bool); | ||
78 | DECLARE_UNIQUE_TYPE(NativePrioFlag, bool); | ||
79 | |||
80 | std::pair<int, int> THREAD_NATIVE_PRIOS(); | ||
81 | |||
76 | void THREAD_SETNAME(std::string_view const& name_); | 82 | void THREAD_SETNAME(std::string_view const& name_); |
77 | void THREAD_SET_PRIORITY(int prio_, bool sudo_); | ||
78 | void THREAD_SET_AFFINITY(unsigned int aff_); | ||
79 | 83 | ||
80 | void THREAD_SET_PRIORITY(std::thread& thread_, int prio_, bool sudo_); | 84 | void THREAD_SET_PRIORITY(lua_State* L_, int prio_, NativePrioFlag native_, SudoFlag sudo_); |
85 | |||
86 | void THREAD_SET_AFFINITY(lua_State* L_, unsigned int aff_); | ||
87 | |||
88 | void 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 | ||
48 | static constexpr int kWriterReturnCode{ 666 }; | 48 | namespace { |
49 | [[nodiscard]] | 49 | namespace local { |
50 | static 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]] |
71 | FuncSubType luaG_getfuncsubtype(lua_State* const L_, StackIndex const i_) | 85 | FuncSubType 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 | ||
94 | namespace tools { | 108 | namespace 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]] |
24 | FuncSubType luaG_getfuncsubtype(lua_State* L_, StackIndex i_); | 24 | FuncSubType 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 89ad02a..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]] | ||
55 | void* 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 | |||
54 | Universe::Universe() | 64 | Universe::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,22 +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, "strip_functions"); // L_: settings strip_functions | 166 | std::ignore = luaW_getfield(L_, kIdxSettings, "linda_wake_period"); // L_: settings linda_wake_period |
167 | if (luaW_type(L_, kIdxTop) == LuaType::NUMBER) { | ||
168 | _U->lindaWakePeriod = lua_Duration{ lua_tonumber(L_, kIdxTop) }; | ||
169 | } else { | ||
170 | LUA_ASSERT(L_, luaW_tostring(L_, kIdxTop) == "never"); | ||
171 | } | ||
172 | lua_pop(L_, 1); // L_: settings | ||
173 | |||
174 | std::ignore = luaW_getfield(L_, kIdxSettings, "strip_functions"); // L_: settings strip_functions | ||
157 | _U->stripFunctions = lua_toboolean(L_, -1) ? true : false; | 175 | _U->stripFunctions = lua_toboolean(L_, -1) ? true : false; |
158 | lua_pop(L_, 1); // L_: settings | 176 | lua_pop(L_, 1); // L_: settings |
159 | 177 | ||
160 | 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 |
161 | _U->verboseErrors = lua_toboolean(L_, -1) ? true : false; | 179 | _U->verboseErrors = lua_toboolean(L_, -1) ? true : false; |
162 | lua_pop(L_, 1); // L_: settings | 180 | lua_pop(L_, 1); // L_: settings |
163 | 181 | ||
164 | // tracking | 182 | // tracking |
165 | 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 |
166 | if (lua_toboolean(L_, -1)) { | 184 | if (lua_toboolean(L_, -1)) { |
167 | _U->tracker.activate(); | 185 | _U->tracker.activate(); |
168 | } | 186 | } |
@@ -170,8 +188,8 @@ Universe* Universe::Create(lua_State* const L_) | |||
170 | 188 | ||
171 | // Linked chains handling | 189 | // Linked chains handling |
172 | _U->selfdestructFirst = SELFDESTRUCT_END; | 190 | _U->selfdestructFirst = SELFDESTRUCT_END; |
173 | _U->initializeAllocatorFunction(L_); | 191 | _U->initializeAllocatorFunction(L_); // this can raise an error |
174 | _U->initializeOnStateCreate(L_); | 192 | _U->initializeOnStateCreate(L_); // this can raise an error |
175 | _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); |
176 | STACK_CHECK(L_, 0); | 194 | STACK_CHECK(L_, 0); |
177 | 195 | ||
@@ -199,7 +217,7 @@ static void* libc_lua_Alloc([[maybe_unused]] void* const ud_, [[maybe_unused]] v | |||
199 | // ################################################################################################# | 217 | // ################################################################################################# |
200 | 218 | ||
201 | [[nodiscard]] | 219 | [[nodiscard]] |
202 | static int luaG_provide_protected_allocator(lua_State* const L_) | 220 | static int luaW_provide_protected_allocator(lua_State* const L_) |
203 | { | 221 | { |
204 | Universe* const _U{ Universe::Get(L_) }; | 222 | Universe* const _U{ Universe::Get(L_) }; |
205 | // 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 |
@@ -209,9 +227,9 @@ static int luaG_provide_protected_allocator(lua_State* const L_) | |||
209 | 227 | ||
210 | // ################################################################################################# | 228 | // ################################################################################################# |
211 | 229 | ||
230 | // already called under protection of selfdestructMutex | ||
212 | void Universe::flagDanglingLanes() const | 231 | void Universe::flagDanglingLanes() const |
213 | { | 232 | { |
214 | std::lock_guard<std::mutex> _guard{ selfdestructMutex }; | ||
215 | Lane* _lane{ selfdestructFirst }; | 233 | Lane* _lane{ selfdestructFirst }; |
216 | while (_lane != SELFDESTRUCT_END) { | 234 | while (_lane != SELFDESTRUCT_END) { |
217 | _lane->flaggedAfterUniverseGC.store(true, std::memory_order_relaxed); | 235 | _lane->flaggedAfterUniverseGC.store(true, std::memory_order_relaxed); |
@@ -227,17 +245,17 @@ void Universe::initializeAllocatorFunction(lua_State* const L_) | |||
227 | // 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 |
228 | protectedAllocator.initFrom(L_); | 246 | protectedAllocator.initFrom(L_); |
229 | STACK_CHECK_START_REL(L_, 1); // L_: settings | 247 | STACK_CHECK_START_REL(L_, 1); // L_: settings |
230 | switch (luaG_getfield(L_, kIdxTop, "allocator")) { // L_: settings allocator|nil|"protected" | 248 | switch (luaW_getfield(L_, kIdxTop, "allocator")) { // L_: settings allocator|nil|"protected" |
231 | case LuaType::NIL: | 249 | case LuaType::NIL: |
232 | // nothing else to do | 250 | // nothing else to do |
233 | break; | 251 | break; |
234 | 252 | ||
235 | case LuaType::STRING: | 253 | case LuaType::STRING: |
236 | LUA_ASSERT(L_, luaG_tostring(L_, kIdxTop) == "protected"); | 254 | LUA_ASSERT(L_, luaW_tostring(L_, kIdxTop) == "protected"); |
237 | // 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 |
238 | protectedAllocator.installIn(L_); | 256 | protectedAllocator.installIn(L_); |
239 | // 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 |
240 | provideAllocator = luaG_provide_protected_allocator; | 258 | provideAllocator = luaW_provide_protected_allocator; |
241 | break; | 259 | break; |
242 | 260 | ||
243 | case LuaType::FUNCTION: | 261 | case LuaType::FUNCTION: |
@@ -258,14 +276,14 @@ void Universe::initializeAllocatorFunction(lua_State* const L_) | |||
258 | break; | 276 | break; |
259 | 277 | ||
260 | default: // should be filtered out in lanes.lua | 278 | default: // should be filtered out in lanes.lua |
261 | 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()); |
262 | } | 280 | } |
263 | lua_pop(L_, 1); // L_: settings | 281 | lua_pop(L_, 1); // L_: settings |
264 | STACK_CHECK(L_, 1); | 282 | STACK_CHECK(L_, 1); |
265 | 283 | ||
266 | 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" |
267 | 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 |
268 | std::string_view const _allocator{ luaG_tostring(L_, kIdxTop) }; | 286 | std::string_view const _allocator{ luaW_tostring(L_, kIdxTop) }; |
269 | // 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 |
270 | // 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 |
271 | internalAllocator = resolveAndValidateAllocator(L_, "internal"); | 289 | internalAllocator = resolveAndValidateAllocator(L_, "internal"); |
@@ -287,7 +305,7 @@ int Universe::InitializeFinalizer(lua_State* const L_) | |||
287 | 305 | ||
288 | // make sure we are only called from the Master Lua State! | 306 | // make sure we are only called from the Master Lua State! |
289 | kUniverseFullRegKey.pushValue(L_); // L_: f U | 307 | kUniverseFullRegKey.pushValue(L_); // L_: f U |
290 | if (luaG_type(L_, kIdxTop) != LuaType::USERDATA) { | 308 | if (luaW_type(L_, kIdxTop) != LuaType::USERDATA) { |
291 | 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); |
292 | } | 310 | } |
293 | lua_pop(L_, 1); // L_: f | 311 | lua_pop(L_, 1); // L_: f |
@@ -303,8 +321,8 @@ int Universe::InitializeFinalizer(lua_State* const L_) | |||
303 | void Universe::initializeOnStateCreate(lua_State* const L_) | 321 | void Universe::initializeOnStateCreate(lua_State* const L_) |
304 | { | 322 | { |
305 | STACK_CHECK_START_REL(L_, 0); // L_: settings | 323 | STACK_CHECK_START_REL(L_, 0); // L_: settings |
306 | 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 |
307 | 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 |
308 | // store C function pointer in an internal variable | 326 | // store C function pointer in an internal variable |
309 | 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 |
310 | if (_func) { | 328 | if (_func) { |
@@ -317,7 +335,7 @@ void Universe::initializeOnStateCreate(lua_State* const L_) | |||
317 | // 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 |
318 | // when we transfer the config table in newly created Lua states | 336 | // when we transfer the config table in newly created Lua states |
319 | lua_pushnil(L_); // L_: settings on_state_create nil | 337 | lua_pushnil(L_); // L_: settings on_state_create nil |
320 | luaG_setfield(L_, StackIndex{ -3 }, kOnStateCreate); // L_: settings on_state_create | 338 | luaW_setfield(L_, StackIndex{ -3 }, kOnStateCreate); // L_: settings on_state_create |
321 | } else { | 339 | } else { |
322 | // 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) |
323 | onStateCreateFunc.emplace<uintptr_t>(std::bit_cast<uintptr_t>(kOnStateCreate.data())); | 341 | onStateCreateFunc.emplace<uintptr_t>(std::bit_cast<uintptr_t>(kOnStateCreate.data())); |
@@ -340,7 +358,7 @@ lanes::AllocatorDefinition Universe::resolveAndValidateAllocator(lua_State* cons | |||
340 | 358 | ||
341 | 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 |
342 | lua_pushcclosure(L_, provideAllocator, 0); // L_: provideAllocator() | 360 | lua_pushcclosure(L_, provideAllocator, 0); // L_: provideAllocator() |
343 | luaG_pushstring(L_, hint_); // L_: provideAllocator() "<hint>" | 361 | luaW_pushstring(L_, hint_); // L_: provideAllocator() "<hint>" |
344 | lua_call(L_, 1, 1); // L_: result | 362 | lua_call(L_, 1, 1); // L_: result |
345 | // 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) |
346 | _ret = lanes::AllocatorDefinition::Validated(L_, kIdxTop); | 364 | _ret = lanes::AllocatorDefinition::Validated(L_, kIdxTop); |
@@ -415,7 +433,7 @@ int Universe::UniverseGC(lua_State* const L_) | |||
415 | { | 433 | { |
416 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; | 434 | lua_Duration const _shutdown_timeout{ lua_tonumber(L_, lua_upvalueindex(1)) }; |
417 | STACK_CHECK_START_ABS(L_, 1); | 435 | STACK_CHECK_START_ABS(L_, 1); |
418 | Universe* const _U{ luaG_tofulluserdata<Universe>(L_, StackIndex{ 1 }) }; // L_: U | 436 | Universe* const _U{ luaW_tofulluserdata<Universe>(L_, StackIndex{ 1 }) }; // L_: U |
419 | 437 | ||
420 | // attempt to terminate all lanes with increasingly stronger cancel methods | 438 | // attempt to terminate all lanes with increasingly stronger cancel methods |
421 | bool const _allLanesTerminated{ | 439 | bool const _allLanesTerminated{ |
@@ -429,7 +447,7 @@ int Universe::UniverseGC(lua_State* const L_) | |||
429 | if (!lua_isnil(L_, -1)) { | 447 | if (!lua_isnil(L_, -1)) { |
430 | lua_pushboolean(L_, _allLanesTerminated); // L_: U finalizer bool | 448 | lua_pushboolean(L_, _allLanesTerminated); // L_: U finalizer bool |
431 | // no protection. Lua rules for errors in finalizers apply normally: | 449 | // no protection. Lua rules for errors in finalizers apply normally: |
432 | // Lua 5.4: error is propagated in the warn system | 450 | // Lua 5.4+: error is propagated in the warn system |
433 | // older: error is swallowed | 451 | // older: error is swallowed |
434 | lua_call(L_, 1, 1); // L_: U msg? | 452 | lua_call(L_, 1, 1); // L_: U msg? |
435 | // phew, no error in finalizer, since we reached that point | 453 | // phew, no error in finalizer, since we reached that point |
@@ -438,24 +456,31 @@ int Universe::UniverseGC(lua_State* const L_) | |||
438 | if (lua_isnil(L_, kIdxTop)) { | 456 | if (lua_isnil(L_, kIdxTop)) { |
439 | lua_pop(L_, 1); // L_: U | 457 | lua_pop(L_, 1); // L_: U |
440 | // 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 |
441 | luaG_pushstring(L_, "uncooperative lanes detected at shutdown"); // L_: U "msg" | 459 | luaW_pushstring(L_, "uncooperative lanes detected at shutdown"); // L_: U "msg" |
442 | } | 460 | } |
443 | STACK_CHECK(L_, 2); | 461 | STACK_CHECK(L_, 2); |
444 | 462 | ||
445 | // now, all remaining lanes are flagged. if they crash because we remove keepers and the Universe from under them, it is their fault | 463 | { |
446 | bool const _detectedUncooperativeLanes{ _U->selfdestructFirst != SELFDESTRUCT_END }; | 464 | std::lock_guard<std::mutex> _guard{ _U->selfdestructMutex }; |
447 | 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 |
448 | _U->flagDanglingLanes(); | 466 | bool const _detectedUncooperativeLanes{ _U->selfdestructFirst != SELFDESTRUCT_END }; |
449 | if (luaG_tostring(L_, kIdxTop) == "freeze") { | 467 | if (_detectedUncooperativeLanes) { |
450 | 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 | } | ||
451 | } else { | 478 | } else { |
452 | // 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 |
453 | // 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 |
454 | // IMPORTANT: lua_error() is used here instead of the wrapper raise_lua_error() to circumvent what looks like a MSVC compiler bug | ||
455 | // that manifests as a crash inside ntdll!longjmp() function, in optimized builds only | ||
456 | lua_error(L_); | ||
457 | } | 481 | } |
458 | } | 482 | } |
483 | STACK_CHECK(L_, 1); | ||
459 | 484 | ||
460 | // --------------------------------------------------------- | 485 | // --------------------------------------------------------- |
461 | // 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 |
@@ -464,7 +489,9 @@ int Universe::UniverseGC(lua_State* const L_) | |||
464 | // 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 |
465 | Linda::DeleteTimerLinda(L_, std::exchange(_U->timerLinda, nullptr), PK); | 490 | Linda::DeleteTimerLinda(L_, std::exchange(_U->timerLinda, nullptr), PK); |
466 | 491 | ||
467 | _U->keepers.close(); | 492 | if (!_U->keepers.close()) { |
493 | raise_luaL_error(L_, "INTERNAL ERROR: Keepers closed more than once"); | ||
494 | } | ||
468 | 495 | ||
469 | // remove the protected allocator, if any | 496 | // remove the protected allocator, if any |
470 | _U->protectedAllocator.removeFrom(L_); | 497 | _U->protectedAllocator.removeFrom(L_); |
diff --git a/src/universe.hpp b/src/universe.hpp index 42a3d83..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 |
@@ -99,6 +95,8 @@ class Universe final | |||
99 | 95 | ||
100 | Keepers keepers; | 96 | Keepers keepers; |
101 | 97 | ||
98 | lua_Duration lindaWakePeriod{}; | ||
99 | |||
102 | // Initialized by 'init_once_LOCKED()': the deep userdata Linda object | 100 | // Initialized by 'init_once_LOCKED()': the deep userdata Linda object |
103 | // used for timers (each lane will get a proxy to this) | 101 | // used for timers (each lane will get a proxy to this) |
104 | Linda* timerLinda{ nullptr }; | 102 | Linda* timerLinda{ nullptr }; |
@@ -130,7 +128,7 @@ class Universe final | |||
130 | 128 | ||
131 | public: | 129 | public: |
132 | [[nodiscard]] | 130 | [[nodiscard]] |
133 | 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 }); }; |
134 | // 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 |
135 | 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 |
136 | 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()") |
51 | a,b,c = t[1],t[2],t[3] -- Need to explicitly wait for the thread, since 'ipairs()' does not | 51 | a,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 | ||
55 | print(a,b,c) | 55 | print(a,b,c) |
diff --git a/tests/basic.lua b/tests/basic.lua index 068dc25..f393175 100644 --- a/tests/basic.lua +++ b/tests/basic.lua | |||
@@ -163,7 +163,7 @@ PRINT(" "..st) | |||
163 | assert(st == "cancelled", "st is '" .. st .. "' instead of 'cancelled'") | 163 | assert(st == "cancelled", "st is '" .. st .. "' instead of 'cancelled'") |
164 | 164 | ||
165 | -- cancellation of lanes waiting on a linda | 165 | -- cancellation of lanes waiting on a linda |
166 | local limited = lanes_linda("limited") | 166 | local limited = lanes_linda{name = "limited"} |
167 | assert.fails(function() limited:limit("key", -1) end) | 167 | assert.fails(function() limited:limit("key", -1) end) |
168 | assert.failsnot(function() limited:limit("key", 1) end) | 168 | assert.failsnot(function() limited:limit("key", 1) end) |
169 | -- [[################################################ | 169 | -- [[################################################ |
@@ -173,42 +173,51 @@ for k, v in pairs(limited:dump()) do | |||
173 | end | 173 | end |
174 | local wait_send = function() | 174 | local wait_send = function() |
175 | local a,b | 175 | local a,b |
176 | set_finalizer(function() print("wait_send", a, b) end) | 176 | set_finalizer(function(err, stack_tbl) print("wait_send", a, b, " -> ", tostring(err)) end) |
177 | print("in wait_send") | ||
177 | a,b = limited:send("key", "bybye") -- infinite timeout, returns only when lane is cancelled | 178 | a,b = limited:send("key", "bybye") -- infinite timeout, returns only when lane is cancelled |
178 | end | 179 | end |
179 | 180 | ||
180 | local wait_send_lane = lanes.gen("*", { name = 'auto' }, wait_send)() | 181 | local wait_send_lane = lanes.gen("*", { name = 'auto' }, wait_send)() |
181 | repeat until wait_send_lane.status == "waiting" | 182 | repeat |
182 | print "wait_send_lane is waiting" | 183 | io.stderr:write('!') |
184 | -- currently mingw64 builds can deadlock if we cancel the lane too early (before the linda blocks, at it causes the linda condvar not to be signalled) | ||
185 | lanes.sleep(0.1) | ||
186 | until wait_send_lane.status == "waiting" | ||
187 | PRINT "wait_send_lane is waiting" | ||
183 | wait_send_lane:cancel() -- hard cancel, 0 timeout | 188 | wait_send_lane:cancel() -- hard cancel, 0 timeout |
184 | repeat until wait_send_lane.status == "cancelled" | 189 | repeat until wait_send_lane.status == "cancelled" |
185 | print "wait_send_lane is cancelled" | 190 | PRINT "wait_send_lane is cancelled" |
186 | --################################################]] | 191 | --################################################]] |
187 | local wait_receive = function() | 192 | local wait_receive = function() |
188 | local k, v | 193 | local k, v |
189 | set_finalizer(function() print("wait_receive", k, v) end) | 194 | set_finalizer(function(err, stack_tbl) print("wait_receive", k, v, " -> ", tostring(err)) end) |
190 | k, v = limited:receive("dummy") -- infinite timeout, returns only when lane is cancelled | 195 | k, v = limited:receive("dummy") -- infinite timeout, returns only when lane is cancelled |
191 | end | 196 | end |
192 | 197 | ||
193 | local wait_receive_lane = lanes.gen("*", { name = 'auto' }, wait_receive)() | 198 | local wait_receive_lane = lanes.gen("*", { name = 'auto' }, wait_receive)() |
194 | repeat until wait_receive_lane.status == "waiting" | 199 | repeat |
195 | print "wait_receive_lane is waiting" | 200 | io.stderr:write('!') |
201 | -- currently mingw64 builds can deadlock if we cancel the lane too early (before the linda blocks, at it causes the linda condvar not to be signalled) | ||
202 | lanes.sleep(0.1) | ||
203 | until wait_receive_lane.status == "waiting" | ||
204 | PRINT "wait_receive_lane is waiting" | ||
196 | wait_receive_lane:cancel() -- hard cancel, 0 timeout | 205 | wait_receive_lane:cancel() -- hard cancel, 0 timeout |
197 | repeat until wait_receive_lane.status == "cancelled" | 206 | repeat until wait_receive_lane.status == "cancelled" |
198 | print "wait_receive_lane is cancelled" | 207 | PRINT "wait_receive_lane is cancelled" |
199 | --################################################]] | 208 | --################################################]] |
200 | local wait_receive_batched = function() | 209 | local wait_receive_batched = function() |
201 | local k, v1, v2 | 210 | local k, v1, v2 |
202 | set_finalizer(function() print("wait_receive_batched", k, v1, v2) end) | 211 | set_finalizer(function() print("wait_receive_batched", k, v1, v2) end) |
203 | k, v1, v2 = limited:receive(limited.batched, "dummy", 2) -- infinite timeout, returns only when lane is cancelled | 212 | k, v1, v2 = limited:receive_batched("dummy", 2) -- infinite timeout, returns only when lane is cancelled |
204 | end | 213 | end |
205 | 214 | ||
206 | local wait_receive_batched_lane = lanes.gen("*", { name = 'auto' }, wait_receive_batched)() | 215 | local wait_receive_batched_lane = lanes.gen("*", { name = 'auto' }, wait_receive_batched)() |
207 | repeat until wait_receive_batched_lane.status == "waiting" | 216 | repeat until wait_receive_batched_lane.status == "waiting" |
208 | print "wait_receive_batched_lane is waiting" | 217 | PRINT "wait_receive_batched_lane is waiting" |
209 | wait_receive_batched_lane:cancel() -- hard cancel, 0 timeout | 218 | wait_receive_batched_lane:cancel() -- hard cancel, 0 timeout |
210 | repeat until wait_receive_batched_lane.status == "cancelled" | 219 | repeat until wait_receive_batched_lane.status == "cancelled" |
211 | print "wait_receive_batched_lane is cancelled" | 220 | PRINT "wait_receive_batched_lane is cancelled" |
212 | --################################################]] | 221 | --################################################]] |
213 | 222 | ||
214 | -- ################################################################################################## | 223 | -- ################################################################################################## |
@@ -246,7 +255,7 @@ local chunk= function(linda) | |||
246 | WR("chunk ", "Lane ends!\n") | 255 | WR("chunk ", "Lane ends!\n") |
247 | end | 256 | end |
248 | 257 | ||
249 | local linda = lanes_linda("communications") | 258 | local linda = lanes_linda{name = "communications"} |
250 | assert(type(linda) == "userdata" and tostring(linda) == "Linda: communications") | 259 | assert(type(linda) == "userdata" and tostring(linda) == "Linda: communications") |
251 | -- | 260 | -- |
252 | -- ["->"] master -> slave | 261 | -- ["->"] master -> slave |
@@ -264,7 +273,7 @@ local b,x,y,z,w = linda:get("<->", 4) | |||
264 | assert(b == 3 and x == "x" and y == "y" and z == "z" and w == nil) | 273 | assert(b == 3 and x == "x" and y == "y" and z == "z" and w == nil) |
265 | local k, x = linda:receive("<->") | 274 | local k, x = linda:receive("<->") |
266 | assert(k == "<->" and x == "x") | 275 | assert(k == "<->" and x == "x") |
267 | local k,y,z = linda:receive(linda.batched, "<->", 2) | 276 | local k,y,z = linda:receive_batched("<->", 2) |
268 | assert(k == "<->" and y == "y" and z == "z") | 277 | assert(k == "<->" and y == "y" and z == "z") |
269 | linda:set("<->") | 278 | linda:set("<->") |
270 | local b,x,y,z,w = linda:get("<->", 4) | 279 | local b,x,y,z,w = linda:get("<->", 4) |
@@ -401,7 +410,7 @@ local tc = lanes.gen("io", { name = 'auto', gc_cb = gc_cb }, | |||
401 | end | 410 | end |
402 | ) | 411 | ) |
403 | 412 | ||
404 | local linda= lanes_linda("criss cross") | 413 | local linda= lanes_linda{name = "criss cross"} |
405 | 414 | ||
406 | local a,b= tc(linda, "A","B"), tc(linda, "B","A") -- launching two lanes, twisted comms | 415 | local a,b= tc(linda, "A","B"), tc(linda, "B","A") -- launching two lanes, twisted comms |
407 | 416 | ||
@@ -437,7 +446,7 @@ local function chunk2(linda) | |||
437 | assert(config.strip_functions and info.short_src=="?" or string.match(info.short_src, "^.*basic.lua$"), "bad info.short_src") | 446 | assert(config.strip_functions and info.short_src=="?" or string.match(info.short_src, "^.*basic.lua$"), "bad info.short_src") |
438 | -- These vary so let's not be picky (they're there..) | 447 | -- These vary so let's not be picky (they're there..) |
439 | -- | 448 | -- |
440 | assert(info.linedefined == 422, "bad linedefined") -- start of 'chunk2' | 449 | assert(info.linedefined == 431, "bad linedefined") -- start of 'chunk2' |
441 | assert(config.strip_functions and info.currentline==-1 or info.currentline > info.linedefined, "bad currentline") -- line of 'debug.getinfo' | 450 | assert(config.strip_functions and info.currentline==-1 or info.currentline > info.linedefined, "bad currentline") -- line of 'debug.getinfo' |
442 | assert(info.lastlinedefined > info.currentline, "bad lastlinedefined") -- end of 'chunk2' | 451 | assert(info.lastlinedefined > info.currentline, "bad lastlinedefined") -- end of 'chunk2' |
443 | local k,func= linda:receive("down") | 452 | local k,func= linda:receive("down") |
@@ -452,7 +461,7 @@ local function chunk2(linda) | |||
452 | linda:send("up", function() return ":)" end, "ok2") | 461 | linda:send("up", function() return ":)" end, "ok2") |
453 | end | 462 | end |
454 | 463 | ||
455 | local linda = lanes_linda("auto") | 464 | local linda = lanes_linda{name = "auto"} |
456 | local t2 = lanes.gen("debug,string,io", { name = 'auto', gc_cb = gc_cb }, chunk2)(linda) -- prepare & launch | 465 | local t2 = lanes.gen("debug,string,io", { name = 'auto', gc_cb = gc_cb }, chunk2)(linda) -- prepare & launch |
457 | linda:send("down", function(linda) linda:send("up", "ready!") end, | 466 | linda:send("down", function(linda) linda:send("up", "ready!") end, |
458 | "ok") | 467 | "ok") |
@@ -460,7 +469,7 @@ linda:send("down", function(linda) linda:send("up", "ready!") end, | |||
460 | -- | 469 | -- |
461 | local k,s= linda:receive(1, "up") | 470 | local k,s= linda:receive(1, "up") |
462 | if t2.status == "error" then | 471 | if t2.status == "error" then |
463 | print("t2 error: " , t2:join()) | 472 | PRINT("t2 error: " , t2:join()) |
464 | end | 473 | end |
465 | PRINT(s) | 474 | PRINT(s) |
466 | assert(s=="ready!") | 475 | assert(s=="ready!") |
@@ -498,19 +507,20 @@ local S = lanes.gen("table", { name = 'auto', gc_cb = gc_cb }, | |||
498 | return (unpack or table.unpack)(aux) | 507 | return (unpack or table.unpack)(aux) |
499 | end) | 508 | end) |
500 | 509 | ||
501 | h= S { 12, 13, 14 } -- execution starts, h[1..3] will get the return values | 510 | h = S { 12, 13, 14 } -- execution starts, h[1..3] will get the return values |
502 | -- 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 |
503 | SLEEP(0.5) | 512 | SLEEP(0.5) |
504 | print("joining with '" .. h:get_threadname() .. "'") | 513 | print("joining with '" .. h:get_threadname() .. "'") |
505 | local a,b,c,d= h:join() | 514 | local r,a,b,c,d= h:join() |
506 | if h.status == "error" then | 515 | if h.status == "error" then |
507 | print(h:get_threadname(), "error: " , a, b, c, d) | 516 | print(h:get_threadname(), "error: " , r, a, b, c, d) |
508 | else | 517 | else |
509 | print(h:get_threadname(), a,b,c,d) | 518 | print(h:get_threadname(), r,a,b,c,d) |
510 | assert(a==14) | 519 | assert(r == true) |
511 | assert(b==13) | 520 | assert(a == 14) |
512 | assert(c==12) | 521 | assert(b == 13) |
513 | assert(d==nil) | 522 | assert(c == 12) |
523 | assert(d == nil) | ||
514 | end | 524 | end |
515 | 525 | ||
516 | local nameof_type, nameof_name = lanes.nameof(print) | 526 | local nameof_type, nameof_name = lanes.nameof(print) |
diff --git a/tests/cancel.lua b/tests/cancel.lua index 80e6c6a..66957c3 100644 --- a/tests/cancel.lua +++ b/tests/cancel.lua | |||
@@ -148,7 +148,7 @@ local protectedBody = function(...) | |||
148 | local paramLessClosure = function() laneBody(unpack(params)) end | 148 | local paramLessClosure = function() laneBody(unpack(params)) end |
149 | local status, message = xpcall(paramLessClosure, errorHandler) | 149 | local status, message = xpcall(paramLessClosure, errorHandler) |
150 | if status == false then | 150 | if status == false then |
151 | print(" error handler rethrowing '" .. (ce == message and "cancel_error"or tostring(message)) .. "'") | 151 | print(" protectedBody rethrowing '" .. (ce == message and "cancel_error" or tostring(message)) .. "'") |
152 | -- if the error isn't rethrown, the lane's finalizer won't get it | 152 | -- if the error isn't rethrown, the lane's finalizer won't get it |
153 | error(message) | 153 | error(message) |
154 | end | 154 | end |
diff --git a/tests/deadlock.lua b/tests/deadlock.lua index d028e83..9b93e3b 100644 --- a/tests/deadlock.lua +++ b/tests/deadlock.lua | |||
@@ -16,7 +16,7 @@ print "let's begin" | |||
16 | local do_extra_stuff = true | 16 | local do_extra_stuff = true |
17 | 17 | ||
18 | if do_extra_stuff then | 18 | if do_extra_stuff then |
19 | local linda = lanes.linda "deadlock_linda" | 19 | local linda = lanes.linda{name = "deadlock_linda"} |
20 | -- just something to make send() succeed and receive() fail | 20 | -- just something to make send() succeed and receive() fail |
21 | local payload = { io.flush } | 21 | local payload = { io.flush } |
22 | 22 | ||
diff --git a/tests/errhangtest.lua b/tests/errhangtest.lua index fff0dee..5b3f0c0 100644 --- a/tests/errhangtest.lua +++ b/tests/errhangtest.lua | |||
@@ -19,7 +19,6 @@ end | |||
19 | if true then | 19 | if true then |
20 | print "\n#### reserved sentinels" | 20 | print "\n#### reserved sentinels" |
21 | print(pcall(linda.set, linda, lanes.cancel_error)) | 21 | print(pcall(linda.set, linda, lanes.cancel_error)) |
22 | print(pcall(linda.set, linda, linda.batched)) | ||
23 | local _count, _val = linda:get("test") | 22 | local _count, _val = linda:get("test") |
24 | assert(_count == 0 and _val == nil) | 23 | assert(_count == 0 and _val == nil) |
25 | print "OK" | 24 | print "OK" |
@@ -28,13 +27,13 @@ end | |||
28 | -- get/set a few values | 27 | -- get/set a few values |
29 | if true then | 28 | if true then |
30 | print "\n#### set 3 -> receive batched" | 29 | print "\n#### set 3 -> receive batched" |
31 | assert.fails(function() linda:receive(linda.batched, "some key", -1, 1) end) | 30 | assert.fails(function() linda:receive_batched("some key", -1, 1) end) |
32 | assert.fails(function() linda:receive(linda.batched, "some key", 2, 1) end) | 31 | assert.fails(function() linda:receive_batched("some key", 2, 1) end) |
33 | assert.failsnot(function() linda:receive(0, linda.batched, "some key", 1, 3) end) | 32 | assert.failsnot(function() linda:receive_batched(0, "some key", 1, 3) end) |
34 | local fun = function() print "function test ok" end | 33 | local fun = function() print "function test ok" end |
35 | print(pcall(linda.set, linda, 'test', true, nil, fun)) | 34 | print(pcall(linda.set, linda, 'test', true, nil, fun)) |
36 | -- read back the contents | 35 | -- read back the contents |
37 | local k,b,n,f = linda:receive(linda.batched, 'test', 3) | 36 | local k,b,n,f = linda:receive_batched('test', 3) |
38 | local _count, _val = linda:get("test") | 37 | local _count, _val = linda:get("test") |
39 | assert(_count == 0 and _val == nil) | 38 | assert(_count == 0 and _val == nil) |
40 | -- check they are ok | 39 | -- check they are ok |
diff --git a/tests/error.lua b/tests/error.lua index 306c51d..76ceea4 100644 --- a/tests/error.lua +++ b/tests/error.lua | |||
@@ -106,11 +106,11 @@ end | |||
106 | 106 | ||
107 | local lane_error_as_string = "'lane error as string'" | 107 | local lane_error_as_string = "'lane error as string'" |
108 | local lane_error_as_table = setmetatable({"lane error as table"}, make_table_error_mt()) | 108 | local lane_error_as_table = setmetatable({"lane error as table"}, make_table_error_mt()) |
109 | local lane_error_as_linda = lanes.linda("'lane error'") | 109 | local lane_error_as_linda = lanes.linda{name = "'lane error'"} |
110 | 110 | ||
111 | local finalizer_error_as_string = "'finalizer error as string'" | 111 | local finalizer_error_as_string = "'finalizer error as string'" |
112 | local finalizer_error_as_table = setmetatable({"finalizer error as table"}, make_table_error_mt()) | 112 | local finalizer_error_as_table = setmetatable({"finalizer error as table"}, make_table_error_mt()) |
113 | local finalizer_error_as_linda = lanes.linda("'finalizer error'") | 113 | local finalizer_error_as_linda = lanes.linda{name = "'finalizer error'"} |
114 | 114 | ||
115 | local test_settings = {} | 115 | local test_settings = {} |
116 | local configure_tests = function() | 116 | local configure_tests = function() |
@@ -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" |
205 | end | 204 | end |
diff --git a/tests/fifo.lua b/tests/fifo.lua index 9efcbd9..1317a9f 100644 --- a/tests/fifo.lua +++ b/tests/fifo.lua | |||
@@ -6,10 +6,10 @@ | |||
6 | 6 | ||
7 | local lanes = require "lanes".configure{shutdown_timeout=3,with_timers=true} | 7 | local lanes = require "lanes".configure{shutdown_timeout=3,with_timers=true} |
8 | 8 | ||
9 | local atomic_linda = lanes.linda( "atom") | 9 | local atomic_linda = lanes.linda{name = "atom"} |
10 | local atomic_inc= lanes.genatomic( atomic_linda, "FIFO_n") | 10 | local atomic_inc= lanes.genatomic( atomic_linda, "FIFO_n") |
11 | 11 | ||
12 | local fifo_linda = lanes.linda( "fifo") | 12 | local fifo_linda = lanes.linda{name = "fifo"} |
13 | 13 | ||
14 | -- Lua 5.1 support | 14 | -- Lua 5.1 support |
15 | local table_unpack = table.unpack or unpack | 15 | local table_unpack = table.unpack or unpack |
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 | ||
22 | local options = {globals = { b = 666 }} | 22 | local options = {globals = { b = 666 }} |
23 | 23 | ||
24 | local gen1 = lanes.gen("*", { name = 'auto' }, "return true, dofile('fibonacci.lua')") | 24 | local gen1 = lanes.gen("*", { name = 'auto' }, "return true, error('bob')") |
25 | local gen2 = lanes.gen(options, { name = 'auto' }, "return b") | ||
26 | 25 | ||
27 | fibLane = gen1() | 26 | fibLane = gen1() |
28 | lanes.sleep(0.1) | 27 | lanes.sleep(0.1) |
29 | print(fibLane, fibLane.status) | 28 | print(fibLane, fibLane.status) |
30 | local _status, _err = fibLane:join() | 29 | local _r, _err, _stk = fibLane:join() |
31 | print(_status, _err) | 30 | assert(_r == nil, "got " .. tostring(_r) .. " " .. tostring(_err) .. " " .. tostring(_stk)) |
32 | 31 | ||
33 | retLane1, retLane2 = gen2(), gen2() | 32 | local gen2 = lanes.gen(options, { name = 'auto' }, "return b") |
33 | local retLane1, retLane2 = gen2(), gen2() | ||
34 | 34 | ||
35 | print( retLane1[1], retLane2[1]) | 35 | print( retLane1[1], retLane2[1]) |
36 | print "TEST OK" \ No newline at end of file | 36 | assert(retLane1[1] == 666 and retLane2[1] == 666) |
37 | print "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 |
6 | that uses closures in it as a global variable into a new lane. This | 6 | that uses closures in it as a global variable into a new lane. This |
7 | causes a segmentation fault and it appears to be related to the | 7 | causes a segmentation fault and it appears to be related to the |
8 | luaG_inter_move function near line 835-836 or so in lanes.c, but I | 8 | luaW_inter_move function near line 835-836 or so in lanes.c, but I |
9 | haven't investigated further. | 9 | haven't investigated further. |
10 | e.g. { globals = { data = 1, func = function() useclosurehere() end } }" | 10 | e.g. { globals = { data = 1, func = function() useclosurehere() end } }" |
11 | ]] | 11 | ]] |
diff --git a/tests/keeper.lua b/tests/keeper.lua index f566927..4742732 100644 --- a/tests/keeper.lua +++ b/tests/keeper.lua | |||
@@ -40,14 +40,14 @@ if true then | |||
40 | end | 40 | end |
41 | 41 | ||
42 | -- should succeed | 42 | -- should succeed |
43 | assert.failsnot(function() createLinda("zero", 0) end) | 43 | assert.failsnot(function() createLinda{name = "zero", group = 0} end) |
44 | assert.failsnot(function() createLinda("one", 1) end) | 44 | assert.failsnot(function() createLinda{name = "one", group = 1} end) |
45 | assert.failsnot(function() createLinda("two", 2) end) | 45 | assert.failsnot(function() createLinda{name = "two", group = 2} end) |
46 | assert.failsnot(function() createLinda("three", 3) end) | 46 | assert.failsnot(function() createLinda{name = "three", group = 3} end) |
47 | -- should fail (and not create the lindas) | 47 | -- should fail (and not create the lindas) |
48 | assert.fails(function() createLinda("minus 1", -1) end) | 48 | assert.fails(function() createLinda{name = "minus 1", group = -1} end) |
49 | assert.fails(function() createLinda("none") end) | 49 | assert.fails(function() createLinda{name = "none"} end) |
50 | assert.fails(function() createLinda("four", 4) end) | 50 | assert.fails(function() createLinda{name = "four", group = 4} end) |
51 | 51 | ||
52 | end | 52 | end |
53 | -- should only collect the 4 successfully created lindas | 53 | -- should only collect the 4 successfully created lindas |
@@ -58,11 +58,11 @@ DONE() | |||
58 | if true then | 58 | if true then |
59 | PRINT "=========================================================================================" | 59 | PRINT "=========================================================================================" |
60 | PRINT "Linda names test:" | 60 | PRINT "Linda names test:" |
61 | local unnamedLinda1 = lanes.linda(1) | 61 | local unnamedLinda1 = lanes.linda{group = 1} |
62 | local unnamedLinda2 = lanes.linda("", 2) | 62 | local unnamedLinda2 = lanes.linda{name = "", group = 2} |
63 | local veeeerrrryyyylooongNamedLinda3 = lanes.linda( "veeeerrrryyyylooongNamedLinda", 3) | 63 | local veeeerrrryyyylooongNamedLinda3 = lanes.linda{ name = "veeeerrrryyyylooongNamedLinda", group = 3} |
64 | assert(tostring(veeeerrrryyyylooongNamedLinda3) == "Linda: veeeerrrryyyylooongNamedLinda") | 64 | assert(tostring(veeeerrrryyyylooongNamedLinda3) == "Linda: veeeerrrryyyylooongNamedLinda") |
65 | local shortNamedLinda0 = lanes.linda( "short", 0) | 65 | local shortNamedLinda0 = lanes.linda{name = "short", group = 0} |
66 | assert(tostring(shortNamedLinda0) == "Linda: short") | 66 | assert(tostring(shortNamedLinda0) == "Linda: short") |
67 | PRINT(shortNamedLinda0, unnamedLinda1, unnamedLinda2, veeeerrrryyyylooongNamedLinda3) | 67 | PRINT(shortNamedLinda0, unnamedLinda1, unnamedLinda2, veeeerrrryyyylooongNamedLinda3) |
68 | end | 68 | end |
@@ -74,12 +74,12 @@ DONE() | |||
74 | if true then | 74 | if true then |
75 | PRINT "=========================================================================================" | 75 | PRINT "=========================================================================================" |
76 | PRINT "Linda GC test:" | 76 | PRINT "Linda GC test:" |
77 | local a = lanes.linda("A", 1) | 77 | local a = lanes.linda{name = "A", group = 1} |
78 | local b = lanes.linda("B", 2) | 78 | local b = lanes.linda{name = "B", group = 2} |
79 | local c = lanes.linda("C", 3) | 79 | local c = lanes.linda{name = "C", group = 3} |
80 | 80 | ||
81 | -- store lindas in each other and in themselves | 81 | -- store lindas in each other and in themselves |
82 | a:set("here", lanes.linda("temporary linda", 0)) | 82 | a:set("here", lanes.linda{name = "temporary linda", group = 0}) |
83 | b:set("here", a, b, c) | 83 | b:set("here", a, b, c) |
84 | c:set("here", a, b, c) | 84 | c:set("here", a, b, c) |
85 | 85 | ||
@@ -120,13 +120,13 @@ if true then | |||
120 | end | 120 | end |
121 | 121 | ||
122 | -- | 122 | -- |
123 | local lindaA= lanes.linda( "A", 1) | 123 | local lindaA= lanes.linda{name = "A", group = 1} |
124 | local A= keeper( lindaA ) | 124 | local A= keeper( lindaA ) |
125 | 125 | ||
126 | local lindaB= lanes.linda( "B", 2) | 126 | local lindaB= lanes.linda{name = "B", group = 2} |
127 | local B= keeper( lindaB ) | 127 | local B= keeper( lindaB ) |
128 | 128 | ||
129 | local lindaC= lanes.linda( "C", 3) | 129 | local lindaC= lanes.linda{name = "C", group = 3} |
130 | local C= keeper( lindaC ) | 130 | local C= keeper( lindaC ) |
131 | PRINT("Created", lindaA, lindaB, lindaC) | 131 | PRINT("Created", lindaA, lindaB, lindaC) |
132 | 132 | ||
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 bba1408..e68d552 100644 --- a/tests/linda_perf.lua +++ b/tests/linda_perf.lua | |||
@@ -22,7 +22,7 @@ if true then | |||
22 | do | 22 | do |
23 | print "############################################ tests get/set" | 23 | print "############################################ tests get/set" |
24 | -- linda:get throughput | 24 | -- linda:get throughput |
25 | local l = lanes.linda("get/set", 1) | 25 | local l = lanes.linda{name = "get/set", group = 1} |
26 | local batch = {} | 26 | local batch = {} |
27 | for i = 1,1000 do | 27 | for i = 1,1000 do |
28 | table.insert(batch, i) | 28 | table.insert(batch, i) |
@@ -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" |
60 | end | 60 | end |
61 | 61 | ||
62 | -- ################################################################################################# | 62 | -- ################################################################################################# |
@@ -68,13 +68,13 @@ local gobbler = function( l, loop, batch) | |||
68 | l:receive( "go") | 68 | l:receive( "go") |
69 | -- eat data in batches | 69 | -- eat data in batches |
70 | for i = 1, loop/batch do | 70 | for i = 1, loop/batch do |
71 | l:receive( l.batched, "key", batch) | 71 | l:receive_batched("key", batch) |
72 | -- print("gobbler:", batch) | 72 | -- print("gobbler:", batch) |
73 | end | 73 | end |
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" |
78 | end | 78 | end |
79 | 79 | ||
80 | -- ################################################################################################# | 80 | -- ################################################################################################# |
@@ -90,7 +90,7 @@ local group_uid = 1 | |||
90 | local function ziva1( preloop, loop, batch) | 90 | local function ziva1( preloop, loop, batch) |
91 | -- prefill the linda a bit to increase fifo stress | 91 | -- prefill the linda a bit to increase fifo stress |
92 | local top = math.max( preloop, loop) | 92 | local top = math.max( preloop, loop) |
93 | local l = lanes.linda("ziva1("..preloop..":"..loop..":"..batch..")", group_uid) | 93 | local l = lanes.linda{name = "ziva1("..preloop..":"..loop..":"..batch..")", group = group_uid} |
94 | group_uid = (group_uid % config.nb_user_keepers) + 1 | 94 | group_uid = (group_uid % config.nb_user_keepers) + 1 |
95 | local t1 = lanes.now_secs() | 95 | local t1 = lanes.now_secs() |
96 | for i = 1, preloop do | 96 | for i = 1, preloop do |
@@ -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 |
128 | end | 129 | end |
129 | 130 | ||
@@ -165,12 +166,12 @@ end | |||
165 | 166 | ||
166 | -- sequential write/read (no parallelization involved) | 167 | -- sequential write/read (no parallelization involved) |
167 | local function ziva2( preloop, loop, batch) | 168 | local function ziva2( preloop, loop, batch) |
168 | local l = lanes.linda("ziva2("..preloop..":"..loop..":"..tostring(batch)..")", group_uid) | 169 | local l = lanes.linda{name = "ziva2("..preloop..":"..loop..":"..tostring(batch)..")", group = group_uid} |
169 | group_uid = (group_uid % config.nb_user_keepers) + 1 | 170 | group_uid = (group_uid % config.nb_user_keepers) + 1 |
170 | -- prefill the linda a bit to increase fifo stress | 171 | -- prefill the linda a bit to increase fifo stress |
171 | local top, step = math.max( preloop, loop), (l.batched and batch) and batch or 1 | 172 | local top, step = math.max( preloop, loop), batch or 1 |
172 | local batch_send, batch_read | 173 | local batch_send, batch_read |
173 | if l.batched and batch then | 174 | if batch then |
174 | local batch_values = {} | 175 | local batch_values = {} |
175 | for i = 1, batch do | 176 | for i = 1, batch do |
176 | table.insert( batch_values, i) | 177 | table.insert( batch_values, i) |
@@ -180,7 +181,7 @@ local function ziva2( preloop, loop, batch) | |||
180 | l:send( "key", table_unpack( batch_values)) | 181 | l:send( "key", table_unpack( batch_values)) |
181 | end | 182 | end |
182 | batch_read = function() | 183 | batch_read = function() |
183 | l:receive( l.batched, "key", batch) | 184 | l:receive_batched("key", batch) |
184 | end | 185 | end |
185 | else -- not batched | 186 | else -- not batched |
186 | batch_send = function() | 187 | batch_send = function() |
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 |
182 | end | 182 | end |
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!" |
25 | end | 25 | end |
26 | 26 | ||
27 | -- pingpong("L1", '0', '1', true) | 27 | -- pingpong("L1", '0', '1', true) |
28 | local t1, err1 = lanes.gen("*", { name = 'auto' }, pingpong)("L1", 'a', 'b', true) | 28 | local t1, err1 = lanes.gen("*", { name = 'auto' }, pingpong)("L1", 'a', 'b', true) |
29 | local t2, err2 = lanes.gen("*", { name = 'auto' }, pingpong)("L2", 'b', 'a', false) | 29 | local t2, err2 = lanes.gen("*", { name = 'auto' }, pingpong)("L2", 'b', 'a', false) |
30 | 30 | ||
31 | t1:join() | 31 | local r1, ret1 = t1:join() |
32 | t2:join() | 32 | assert(r1 == true and ret1 == "ping!") |
33 | local r2, ret2 = t2:join() | ||
34 | assert(r2 == true and ret2 == "ping!") | ||
33 | print "TEST OK" | 35 | print "TEST OK" |
diff --git a/tests/protect_allocator.lua b/tests/protect_allocator.lua index e13a57c..325726a 100644 --- a/tests/protect_allocator.lua +++ b/tests/protect_allocator.lua | |||
@@ -52,7 +52,7 @@ end | |||
52 | 52 | ||
53 | -- wait for completion | 53 | -- wait for completion |
54 | print "wait for completion" | 54 | print "wait for completion" |
55 | linda:receive( linda.batched, "key", COUNT) | 55 | linda:receive_batched("key", COUNT) |
56 | print "waiting a bit more ..." | 56 | print "waiting a bit more ..." |
57 | SLEEP(1) | 57 | SLEEP(1) |
58 | print "SUCCESS" | 58 | print "SUCCESS" |
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 | |||
26 | local g = lanes.gen( "base", { name = 'auto' }, a) | 26 | local g = lanes.gen( "base", { name = 'auto' }, a) |
27 | 27 | ||
28 | local l = g(7) | 28 | local l = g(7) |
29 | local r = l:join() | 29 | local _, r = l:join() |
30 | assert(r == y) | 30 | assert(r == y) |
31 | print(r) | 31 | print(r) |
32 | 32 | ||
33 | local l = g(8) | 33 | local l = g(8) |
34 | local r = l:join() | 34 | local _, r = l:join() |
35 | assert(r == z) | 35 | assert(r == z) |
36 | print(r) | 36 | print(r) |
37 | 37 | ||
38 | local l = g(9) | 38 | local l = g(9) |
39 | local r = l:join() | 39 | local _, r = l:join() |
40 | assert(r == x) | 40 | assert(r == x) |
41 | print(r) | 41 | print(r) |
42 | 42 | ||
diff --git a/tests/tobeclosed.lua b/tests/tobeclosed.lua index ef09df3..fd157e2 100644 --- a/tests/tobeclosed.lua +++ b/tests/tobeclosed.lua | |||
@@ -36,7 +36,7 @@ do | |||
36 | WR("f closing ", linda_) | 36 | WR("f closing ", linda_) |
37 | closed_by_f = true | 37 | closed_by_f = true |
38 | end | 38 | end |
39 | local lf <close> = lanes.linda("closed by f", close_handler_f) | 39 | local lf <close> = lanes.linda{name = "closed by f", close_handler = close_handler_f} |
40 | 40 | ||
41 | local close_handler_t = setmetatable({}, | 41 | local close_handler_t = setmetatable({}, |
42 | { | 42 | { |
@@ -46,7 +46,7 @@ do | |||
46 | end | 46 | end |
47 | } | 47 | } |
48 | ) | 48 | ) |
49 | local lt <close> = lanes.linda("closed by t", close_handler_t) | 49 | local lt <close> = lanes.linda{name = "closed by t", close_handler = close_handler_t} |
50 | end | 50 | end |
51 | assert(closed_by_f == true) | 51 | assert(closed_by_f == true) |
52 | assert(closed_by_t == true) | 52 | assert(closed_by_t == true) |
@@ -58,13 +58,13 @@ end | |||
58 | WR "================================================================================================" | 58 | WR "================================================================================================" |
59 | WR "Through Linda" | 59 | WR "Through Linda" |
60 | do | 60 | do |
61 | local l = lanes.linda("channel") | 61 | local l = lanes.linda{name = "channel"} |
62 | 62 | ||
63 | local close_handler_f = function(linda_, err_) | 63 | local close_handler_f = function(linda_, err_) |
64 | WR("f closing ", linda_) | 64 | WR("f closing ", linda_) |
65 | linda_:set("closed", true) | 65 | linda_:set("closed", true) |
66 | end | 66 | end |
67 | local l_in = lanes.linda("voyager", close_handler_f) | 67 | local l_in = lanes.linda{name = "voyager", close_handler = close_handler_f} |
68 | l:set("trip", l_in) | 68 | l:set("trip", l_in) |
69 | 69 | ||
70 | do | 70 | do |
@@ -99,14 +99,14 @@ end | |||
99 | WR "================================================================================================" | 99 | WR "================================================================================================" |
100 | WR "Linda closing through Lane" | 100 | WR "Linda closing through Lane" |
101 | do | 101 | do |
102 | local l = lanes.linda("channel") | 102 | local l = lanes.linda{name = "channel"} |
103 | local lane_body = function(l_arg_) | 103 | local lane_body = function(l_arg_) |
104 | WR "In lane body" | 104 | WR "In lane body" |
105 | -- linda obtained through a linda | 105 | -- linda obtained through a linda |
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_) |
@@ -114,11 +114,12 @@ do | |||
114 | local _count, _closed = linda_:get("closed") | 114 | local _count, _closed = linda_:get("closed") |
115 | linda_:set("closed", (_closed or 0) + 1) | 115 | linda_:set("closed", (_closed or 0) + 1) |
116 | end | 116 | end |
117 | local l_in = lanes.linda("voyager", close_handler_f) | 117 | local l_in = lanes.linda{name = "voyager", close_handler = close_handler_f} |
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/tests/track_lanes.lua b/tests/track_lanes.lua index d1670ae..ef2ca06 100644 --- a/tests/track_lanes.lua +++ b/tests/track_lanes.lua | |||
@@ -59,8 +59,10 @@ local threads = track( "============= START", 2) | |||
59 | -- two_seconds forever | 59 | -- two_seconds forever |
60 | assert(threads[1].status == 'waiting' and threads[2].status == 'waiting') | 60 | assert(threads[1].status == 'waiting' and threads[2].status == 'waiting') |
61 | 61 | ||
62 | -- wait until ephemeral1 has completed | 62 | -- wait until ephemeral1 has completed, should take about 2 seconds |
63 | SLEEP(2.1) | 63 | repeat |
64 | SLEEP(0.1) | ||
65 | until ephemeral1.status == "done" | ||
64 | 66 | ||
65 | local threads = track( "============= two_seconds dead", 2) | 67 | local threads = track( "============= two_seconds dead", 2) |
66 | -- two_seconds forever | 68 | -- two_seconds forever |
diff --git a/unit_tests/UnitTests.vcxproj b/unit_tests/UnitTests.vcxproj index 6ff1eb1..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> |
@@ -155,103 +182,123 @@ | |||
155 | <ImportGroup Label="PropertySheets" /> | 182 | <ImportGroup Label="PropertySheets" /> |
156 | <PropertyGroup Label="UserMacros" /> | 183 | <PropertyGroup Label="UserMacros" /> |
157 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'"> | 184 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|Win32'"> |
158 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 185 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
186 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | ||
187 | <LinkIncremental>false</LinkIncremental> | ||
188 | </PropertyGroup> | ||
189 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|Win32'"> | ||
190 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> | ||
159 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 191 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
160 | <LinkIncremental>false</LinkIncremental> | 192 | <LinkIncremental>false</LinkIncremental> |
161 | </PropertyGroup> | 193 | </PropertyGroup> |
162 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'"> | 194 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.3|Win32'"> |
163 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(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> |
165 | <LinkIncremental>false</LinkIncremental> | 197 | <LinkIncremental>false</LinkIncremental> |
166 | </PropertyGroup> | 198 | </PropertyGroup> |
167 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'"> | 199 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.3|Win32'"> |
168 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 200 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
169 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 201 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
170 | <LinkIncremental>false</LinkIncremental> | 202 | <LinkIncremental>false</LinkIncremental> |
171 | </PropertyGroup> | 203 | </PropertyGroup> |
172 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'"> | 204 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|Win32'"> |
173 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 205 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
174 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 206 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
175 | <LinkIncremental>false</LinkIncremental> | 207 | <LinkIncremental>false</LinkIncremental> |
176 | </PropertyGroup> | 208 | </PropertyGroup> |
177 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Win32'"> | 209 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.2|Win32'"> |
178 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 210 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
179 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 211 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
180 | <LinkIncremental>false</LinkIncremental> | 212 | <LinkIncremental>false</LinkIncremental> |
181 | </PropertyGroup> | 213 | </PropertyGroup> |
182 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'"> | 214 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|Win32'"> |
183 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 215 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
184 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 216 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
185 | <LinkIncremental>false</LinkIncremental> | 217 | <LinkIncremental>false</LinkIncremental> |
186 | </PropertyGroup> | 218 | </PropertyGroup> |
187 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'"> | 219 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.1|Win32'"> |
188 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 220 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
189 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 221 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
190 | <LinkIncremental>false</LinkIncremental> | 222 | <LinkIncremental>false</LinkIncremental> |
191 | </PropertyGroup> | 223 | </PropertyGroup> |
192 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'"> | 224 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|Win32'"> |
193 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 225 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
194 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 226 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
195 | <LinkIncremental>false</LinkIncremental> | 227 | <LinkIncremental>false</LinkIncremental> |
196 | </PropertyGroup> | 228 | </PropertyGroup> |
197 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'"> | 229 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|Win32'"> |
198 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 230 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
199 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 231 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
200 | <LinkIncremental>false</LinkIncremental> | 232 | <LinkIncremental>false</LinkIncremental> |
201 | </PropertyGroup> | 233 | </PropertyGroup> |
202 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'"> | 234 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|Win32'"> |
203 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 235 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
236 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | ||
237 | <LinkIncremental>false</LinkIncremental> | ||
238 | </PropertyGroup> | ||
239 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|Win32'"> | ||
240 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> | ||
204 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 241 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
205 | <LinkIncremental>false</LinkIncremental> | 242 | <LinkIncremental>false</LinkIncremental> |
206 | </PropertyGroup> | 243 | </PropertyGroup> |
207 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'"> | 244 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.4|x64'"> |
208 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 245 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
246 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | ||
247 | <LinkIncremental>false</LinkIncremental> | ||
248 | </PropertyGroup> | ||
249 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.5|x64'"> | ||
250 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> | ||
209 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 251 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
210 | <LinkIncremental>false</LinkIncremental> | 252 | <LinkIncremental>false</LinkIncremental> |
211 | </PropertyGroup> | 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)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 256 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
215 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 257 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
216 | <LinkIncremental>false</LinkIncremental> | 258 | <LinkIncremental>false</LinkIncremental> |
217 | </PropertyGroup> | 259 | </PropertyGroup> |
218 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'"> | 260 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.3|x64'"> |
219 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 261 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
220 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 262 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
221 | <LinkIncremental>false</LinkIncremental> | 263 | <LinkIncremental>false</LinkIncremental> |
222 | </PropertyGroup> | 264 | </PropertyGroup> |
223 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'"> | 265 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.2|x64'"> |
224 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 266 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
225 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 267 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
226 | <LinkIncremental>false</LinkIncremental> | 268 | <LinkIncremental>false</LinkIncremental> |
227 | </PropertyGroup> | 269 | </PropertyGroup> |
228 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.2|x64'"> | 270 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.2|x64'"> |
229 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 271 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
230 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 272 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
231 | <LinkIncremental>false</LinkIncremental> | 273 | <LinkIncremental>false</LinkIncremental> |
232 | </PropertyGroup> | 274 | </PropertyGroup> |
233 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'"> | 275 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug 5.1|x64'"> |
234 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 276 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
235 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 277 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
236 | <LinkIncremental>false</LinkIncremental> | 278 | <LinkIncremental>false</LinkIncremental> |
237 | </PropertyGroup> | 279 | </PropertyGroup> |
238 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.1|x64'"> | 280 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.1|x64'"> |
239 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 281 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
240 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 282 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
241 | <LinkIncremental>false</LinkIncremental> | 283 | <LinkIncremental>false</LinkIncremental> |
242 | </PropertyGroup> | 284 | </PropertyGroup> |
243 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'"> | 285 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release LuaJIT|x64'"> |
244 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 286 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
245 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 287 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
246 | <LinkIncremental>false</LinkIncremental> | 288 | <LinkIncremental>false</LinkIncremental> |
247 | </PropertyGroup> | 289 | </PropertyGroup> |
248 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'"> | 290 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release MoonJIT|x64'"> |
249 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 291 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
250 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 292 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
251 | <LinkIncremental>false</LinkIncremental> | 293 | <LinkIncremental>false</LinkIncremental> |
252 | </PropertyGroup> | 294 | </PropertyGroup> |
253 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'"> | 295 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.4|x64'"> |
254 | <OutDir>$(SolutionDir)_Output\$(ProjectName)\$(PlatformName)\$(Configuration)\</OutDir> | 296 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> |
297 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | ||
298 | <LinkIncremental>false</LinkIncremental> | ||
299 | </PropertyGroup> | ||
300 | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release 5.5|x64'"> | ||
301 | <OutDir>$(SolutionDir)_LuaVersions\$(PlatformName)\$(Configuration)\</OutDir> | ||
255 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> | 302 | <IntDir>$(SolutionDir)_Tmp\$(ProjectName)\$(PlatformName)\$(Configuration)\</IntDir> |
256 | <LinkIncremental>false</LinkIncremental> | 303 | <LinkIncremental>false</LinkIncremental> |
257 | </PropertyGroup> | 304 | </PropertyGroup> |
@@ -261,7 +308,26 @@ | |||
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,13 +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" /> | ||
1160 | <None Include="scripts\lane\tasking_cancelling_with_hook.lua" /> | ||
1161 | <None Include="scripts\linda\send_receive_func_and_string.lua" /> | ||
1162 | <None Include="scripts\linda\wake_period.lua" /> | ||
1163 | <None Include="scripts\misc\deeptest.lua" /> | ||
1164 | <None Include="scripts\_utils54.lua" /> | ||
970 | <None Include="UnitTests.makefile" /> | 1165 | <None Include="UnitTests.makefile" /> |
971 | <None Include="scripts\coro\basics.lua" /> | 1166 | <None Include="scripts\coro\index_suspended.lua" /> |
972 | <None Include="scripts\coro\error_handling.lua" /> | 1167 | <None Include="scripts\coro\error_handling.lua" /> |
973 | <None Include="scripts\lane\cooperative_shutdown.lua" /> | 1168 | <None Include="scripts\lane\cooperative_shutdown.lua" /> |
974 | <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 3b45009..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"> |
@@ -113,5 +116,44 @@ | |||
113 | <None Include="..\.runsettings"> | 116 | <None Include="..\.runsettings"> |
114 | <Filter>Catch2</Filter> | 117 | <Filter>Catch2</Filter> |
115 | </None> | 118 | </None> |
119 | <None Include="scripts\lane\tasking_cancelling_with_hook.lua"> | ||
120 | <Filter>Scripts\lane</Filter> | ||
121 | </None> | ||
122 | <None Include="scripts\linda\wake_period.lua"> | ||
123 | <Filter>Scripts\linda</Filter> | ||
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> | ||
116 | </ItemGroup> | 158 | </ItemGroup> |
117 | </Project> \ No newline at end of file | 159 | </Project> \ No newline at end of file |
diff --git a/unit_tests/_pch.hpp b/unit_tests/_pch.hpp index 1e98c5a..f6e5fff 100644 --- a/unit_tests/_pch.hpp +++ b/unit_tests/_pch.hpp | |||
@@ -1,5 +1,3 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <atomic> | 1 | #include <atomic> |
4 | #include <cassert> | 2 | #include <cassert> |
5 | #include <filesystem> | 3 | #include <filesystem> |
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 | |||
104 | MAKE_TEST_CASE(misc, deeptest, AssertNoLuaError) | ||
diff --git a/unit_tests/embedded_tests.cpp b/unit_tests/embedded_tests.cpp index 9a262d5..388548d 100644 --- a/unit_tests/embedded_tests.cpp +++ b/unit_tests/embedded_tests.cpp | |||
@@ -2,6 +2,7 @@ | |||
2 | #include "shared.h" | 2 | #include "shared.h" |
3 | #include "lanes/src/lanes.hpp" | 3 | #include "lanes/src/lanes.hpp" |
4 | 4 | ||
5 | #if defined __has_include && __has_include(<windows.h>) | ||
5 | #include <windows.h> | 6 | #include <windows.h> |
6 | 7 | ||
7 | // ################################################################################################# | 8 | // ################################################################################################# |
@@ -138,13 +139,13 @@ namespace | |||
138 | 139 | ||
139 | // ################################################################################################# | 140 | // ################################################################################################# |
140 | 141 | ||
141 | TEST_CASE("lanes.embedding.with default allocator") | 142 | TEST_CASE("lanes.embedding.with_default_allocator") |
142 | { | 143 | { |
143 | local::EmbeddedLuaState S; | 144 | local::EmbeddedLuaState S; |
144 | 145 | ||
145 | // --------------------------------------------------------------------------------------------- | 146 | // --------------------------------------------------------------------------------------------- |
146 | 147 | ||
147 | SECTION("single state") | 148 | SECTION("single_state") |
148 | { | 149 | { |
149 | // this sends data in a linda. current contents: | 150 | // this sends data in a linda. current contents: |
150 | // key: short string | 151 | // key: short string |
@@ -157,7 +158,7 @@ TEST_CASE("lanes.embedding.with default allocator") | |||
157 | // function with an upvalue | 158 | // function with an upvalue |
158 | std::string_view const _script{ | 159 | std::string_view const _script{ |
159 | " local lanes = require 'lanes'.configure{with_timers = false}" | 160 | " local lanes = require 'lanes'.configure{with_timers = false}" |
160 | " local l = lanes.linda'gleh'" | 161 | " local l = lanes.linda{name = 'gleh'}" |
161 | " local upvalue = 'oeauaoeuoeuaoeuaoeujaoefubycfjbycfybcfjybcfjybcfjbcf'" | 162 | " local upvalue = 'oeauaoeuoeuaoeuaoeujaoefubycfjbycfybcfjybcfjybcfjbcf'" |
162 | " local upvalued = function()" | 163 | " local upvalued = function()" |
163 | " return upvalue" | 164 | " return upvalue" |
@@ -171,7 +172,7 @@ TEST_CASE("lanes.embedding.with default allocator") | |||
171 | 172 | ||
172 | // --------------------------------------------------------------------------------------------- | 173 | // --------------------------------------------------------------------------------------------- |
173 | 174 | ||
174 | SECTION("manual registration") | 175 | SECTION("manual_registration") |
175 | { | 176 | { |
176 | S.requireSuccess("require 'lanes'.configure{with_timers = false}"); | 177 | S.requireSuccess("require 'lanes'.configure{with_timers = false}"); |
177 | 178 | ||
@@ -183,7 +184,7 @@ TEST_CASE("lanes.embedding.with default allocator") | |||
183 | // try to send io.open into a linda, which fails if io base library is not loaded | 184 | // try to send io.open into a linda, which fails if io base library is not loaded |
184 | std::string_view const _script{ | 185 | std::string_view const _script{ |
185 | " local lanes = require 'lanes'" | 186 | " local lanes = require 'lanes'" |
186 | " local l = lanes.linda'gleh'" | 187 | " local l = lanes.linda{name = 'gleh'}" |
187 | " l:set('yo', io.open)" | 188 | " l:set('yo', io.open)" |
188 | " return 'SUCCESS'" | 189 | " return 'SUCCESS'" |
189 | }; | 190 | }; |
@@ -191,7 +192,7 @@ TEST_CASE("lanes.embedding.with default allocator") | |||
191 | 192 | ||
192 | // try again after manual registration | 193 | // try again after manual registration |
193 | lua_pushcfunction(S, S.get_lanes_register()); // S: lanes_register | 194 | lua_pushcfunction(S, S.get_lanes_register()); // S: lanes_register |
194 | luaG_pushstring(S, LUA_IOLIBNAME); // S: lanes_register "io" | 195 | luaW_pushstring(S, LUA_IOLIBNAME); // S: lanes_register "io" |
195 | 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 |
196 | lua_call(S, 2, 0); // S: | 197 | lua_call(S, 2, 0); // S: |
197 | S.stackCheck(0); | 198 | S.stackCheck(0); |
@@ -202,7 +203,8 @@ TEST_CASE("lanes.embedding.with default allocator") | |||
202 | // ################################################################################################# | 203 | // ################################################################################################# |
203 | 204 | ||
204 | // 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 |
205 | TEST_CASE("lanes.embedding.with custom allocator") | 206 | // currently it crashes with moonjit (but maybe I just need a more recent moonjit version) |
207 | TEST_CASE("lanes.embedding.with_custom_allocator") | ||
206 | { | 208 | { |
207 | static constexpr auto logPrint = +[](lua_State* L) { | 209 | static constexpr auto logPrint = +[](lua_State* L) { |
208 | lua_getglobal(L, "ID"); // ID | 210 | lua_getglobal(L, "ID"); // ID |
@@ -218,7 +220,7 @@ TEST_CASE("lanes.embedding.with custom allocator") | |||
218 | 220 | ||
219 | 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_) { |
220 | char script[500]; | 222 | char script[500]; |
221 | lua_State* L = lua_newstate(local::allocf, nullptr); | 223 | lua_State* L = luaW_newstate(local::allocf, nullptr, luaL_makeseed(nullptr)); |
222 | // _G.ID = id_ | 224 | // _G.ID = id_ |
223 | luaL_openlibs(L); | 225 | luaL_openlibs(L); |
224 | luaL_dostring(L, "lanes = require 'lanes'"); | 226 | luaL_dostring(L, "lanes = require 'lanes'"); |
@@ -264,4 +266,6 @@ TEST_CASE("lanes.embedding.with custom allocator") | |||
264 | lua_close(L3); | 266 | lua_close(L3); |
265 | lua_close(L2); | 267 | lua_close(L2); |
266 | lua_close(L1); | 268 | lua_close(L1); |
267 | } \ No newline at end of file | 269 | } |
270 | |||
271 | #endif // windows.h | ||
diff --git a/unit_tests/init_and_shutdown.cpp b/unit_tests/init_and_shutdown.cpp index b8174fd..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 | ||
6 | TEST_CASE("lanes.require 'lanes'") | 6 | TEST_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 |
61 | TEST_CASE("lanes.configure.allocator") | 61 | TEST_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 | |||
102 | TEST_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 | ||
178 | TEST_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 | ||
200 | TEST_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 | |||
194 | TEST_CASE("lanes.configure.internal_allocator") | 211 | TEST_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 } }; |
@@ -289,388 +306,467 @@ TEST_CASE("lanes.configure.keepers_gc_threshold") | |||
289 | 306 | ||
290 | // ################################################################################################# | 307 | // ################################################################################################# |
291 | 308 | ||
292 | TEST_CASE("lanes.configure.the rest") | 309 | TEST_CASE("lanes.configure.linda_wake_period") |
293 | { | 310 | { |
294 | LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; | 311 | LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; |
295 | 312 | ||
313 | // linda_wake_period should be a number > 0, or 'never' | ||
314 | |||
315 | SECTION("linda_wake_period = <table>") | ||
316 | { | ||
317 | L.requireFailure("require 'lanes'.configure{linda_wake_period = {}}"); | ||
318 | } | ||
296 | 319 | ||
297 | // --------------------------------------------------------------------------------------------- | 320 | // --------------------------------------------------------------------------------------------- |
298 | // nb_user_keepers should be a number in [0, 100] | ||
299 | 321 | ||
300 | SECTION("nb_user_keepers") | 322 | SECTION("linda_wake_period = <string>") |
301 | { | 323 | { |
302 | SECTION("nb_user_keepers = <table>") | 324 | L.requireFailure("require 'lanes'.configure{linda_wake_period = 'gluh'}"); |
303 | { | 325 | } |
304 | L.requireFailure("require 'lanes'.configure{nb_user_keepers = {}}"); | ||
305 | } | ||
306 | 326 | ||
307 | // ----------------------------------------------------------------------------------------- | 327 | // --------------------------------------------------------------------------------------------- |
308 | 328 | ||
309 | SECTION("nb_user_keepers = <string>") | 329 | SECTION("linda_wake_period = 'never'") |
310 | { | 330 | { |
311 | L.requireFailure("require 'lanes'.configure{nb_user_keepers = 'gluh'}"); | 331 | L.requireSuccess("require 'lanes'.configure{linda_wake_period = 'never'}"); |
312 | } | 332 | } |
313 | 333 | ||
314 | // ----------------------------------------------------------------------------------------- | 334 | // --------------------------------------------------------------------------------------------- |
315 | 335 | ||
316 | SECTION("nb_user_keepers = -1") | 336 | SECTION("linda_wake_period = <negative number>") |
317 | { | 337 | { |
318 | L.requireFailure("require 'lanes'.configure{nb_user_keepers = -1}"); | 338 | L.requireFailure("require 'lanes'.configure{linda_wake_period = -0.001}"); |
319 | } | 339 | } |
320 | 340 | ||
321 | // ----------------------------------------------------------------------------------------- | 341 | // --------------------------------------------------------------------------------------------- |
322 | 342 | ||
323 | SECTION("nb_user_keepers = 0") | 343 | SECTION("linda_wake_period = 0") |
324 | { | 344 | { |
325 | L.requireSuccess("require 'lanes'.configure{nb_user_keepers = 0}"); | 345 | L.requireFailure("require 'lanes'.configure{linda_wake_period = 0}"); |
326 | } | 346 | } |
327 | 347 | ||
328 | // ----------------------------------------------------------------------------------------- | 348 | // --------------------------------------------------------------------------------------------- |
329 | 349 | ||
330 | SECTION("nb_user_keepers = 100") | 350 | SECTION("linda_wake_period = 0.0001s") |
331 | { | 351 | { |
332 | L.requireSuccess("require 'lanes'.configure{nb_user_keepers = 100}"); | 352 | L.requireSuccess("require 'lanes'.configure{linda_wake_period = 0.0001}"); |
333 | } | 353 | } |
334 | 354 | ||
335 | // ----------------------------------------------------------------------------------------- | 355 | // --------------------------------------------------------------------------------------------- |
336 | 356 | ||
337 | SECTION("nb_user_keepers = 101") | 357 | SECTION("linda_wake_period = 1e30") |
338 | { | 358 | { |
339 | L.requireFailure("require 'lanes'.configure{nb_user_keepers = 101}"); | 359 | L.requireSuccess("require 'lanes'.configure{linda_wake_period = 1e30}"); |
340 | } | 360 | } |
361 | } | ||
362 | |||
363 | // ################################################################################################# | ||
364 | |||
365 | TEST_CASE("lanes.configure.nb_user_keepers") | ||
366 | { | ||
367 | LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; | ||
368 | |||
369 | // nb_user_keepers should be a number in [0, 100] | ||
370 | |||
371 | SECTION("nb_user_keepers = <table>") | ||
372 | { | ||
373 | L.requireFailure("require 'lanes'.configure{nb_user_keepers = {}}"); | ||
341 | } | 374 | } |
342 | 375 | ||
343 | // --------------------------------------------------------------------------------------------- | 376 | // --------------------------------------------------------------------------------------------- |
344 | // on_state_create should be a function, either C or Lua, without upvalues | ||
345 | 377 | ||
346 | SECTION("on_state_create") | 378 | SECTION("nb_user_keepers = <string>") |
347 | { | 379 | { |
348 | SECTION("on_state_create = <table>") | 380 | L.requireFailure("require 'lanes'.configure{nb_user_keepers = 'gluh'}"); |
349 | { | 381 | } |
350 | L.requireFailure("require 'lanes'.configure{on_state_create = {}}"); | ||
351 | } | ||
352 | 382 | ||
353 | // ----------------------------------------------------------------------------------------- | 383 | // --------------------------------------------------------------------------------------------- |
354 | 384 | ||
355 | SECTION("on_state_create = <string>") | 385 | SECTION("nb_user_keepers = -1") |
356 | { | 386 | { |
357 | L.requireFailure("require 'lanes'.configure{on_state_create = 'gluh'}"); | 387 | L.requireFailure("require 'lanes'.configure{nb_user_keepers = -1}"); |
358 | } | 388 | } |
359 | 389 | ||
360 | // ----------------------------------------------------------------------------------------- | 390 | // --------------------------------------------------------------------------------------------- |
361 | 391 | ||
362 | SECTION("on_state_create = <number>") | 392 | SECTION("nb_user_keepers = 0") |
363 | { | 393 | { |
364 | L.requireFailure("require 'lanes'.configure{on_state_create = 1}"); | 394 | L.requireSuccess("require 'lanes'.configure{nb_user_keepers = 0}"); |
365 | } | 395 | } |
366 | 396 | ||
367 | // ----------------------------------------------------------------------------------------- | 397 | // --------------------------------------------------------------------------------------------- |
368 | 398 | ||
369 | SECTION("on_state_create = false") | 399 | SECTION("nb_user_keepers = 1") |
370 | { | 400 | { |
371 | L.requireFailure("require 'lanes'.configure{on_state_create = false}"); | 401 | L.requireSuccess("require 'lanes'.configure{nb_user_keepers = 1}"); |
372 | } | 402 | } |
373 | 403 | ||
374 | // ----------------------------------------------------------------------------------------- | 404 | // --------------------------------------------------------------------------------------------- |
375 | 405 | ||
376 | SECTION("on_state_create = true") | 406 | SECTION("nb_user_keepers = 100") |
377 | { | 407 | { |
378 | L.requireFailure("require 'lanes'.configure{on_state_create = true}"); | 408 | L.requireSuccess("require 'lanes'.configure{nb_user_keepers = 100}"); |
379 | } | 409 | } |
380 | 410 | ||
381 | // ----------------------------------------------------------------------------------------- | 411 | // ----------------------------------------------------------------------------------------- |
382 | 412 | ||
383 | SECTION("on_state_create = <Lua function>") | 413 | SECTION("nb_user_keepers = 101") |
384 | { | 414 | { |
385 | // on_state_create isn't called inside a Keeper state if it's a Lua function (which is good as print() doesn't exist there!) | 415 | L.requireFailure("require 'lanes'.configure{nb_user_keepers = 101}"); |
386 | L.requireSuccess("local print = print; require 'lanes'.configure{on_state_create = function() print 'hello' end}"); | 416 | } |
387 | } | 417 | } |
388 | 418 | ||
389 | // ----------------------------------------------------------------------------------------- | 419 | // ################################################################################################# |
390 | 420 | ||
391 | SECTION("on_state_create = <C function>") | 421 | TEST_CASE("lanes.configure.on_state_create/configuration") |
392 | { | 422 | { |
393 | // funnily enough, in Lua 5.3, print() uses global tostring(), that doesn't exist in a keeper since we didn't open libs -> "attempt to call a nil value" | 423 | LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; |
394 | // conclusion, don't use print() as a fake on_state_create() callback! | 424 | |
395 | // assert() should be fine since we pass a non-false argument to on_state_create | 425 | // on_state_create should be a function, either C or Lua, without upvalues |
396 | L.requireSuccess("require 'lanes'.configure{on_state_create = assert}"); | 426 | |
397 | } | 427 | SECTION("on_state_create = <table>") |
428 | { | ||
429 | L.requireFailure("require 'lanes'.configure{on_state_create = {}}"); | ||
398 | } | 430 | } |
399 | 431 | ||
400 | // --------------------------------------------------------------------------------------------- | 432 | // --------------------------------------------------------------------------------------------- |
401 | // shutdown_timeout should be a number in [0,3600] | ||
402 | 433 | ||
403 | SECTION("shutdown_timeout") | 434 | SECTION("on_state_create = <string>") |
404 | { | 435 | { |
405 | SECTION("shutdown_timeout = <table>") | 436 | L.requireFailure("require 'lanes'.configure{on_state_create = 'gluh'}"); |
406 | { | 437 | } |
407 | L.requireFailure("require 'lanes'.configure{shutdown_timeout = {}}"); | ||
408 | } | ||
409 | 438 | ||
410 | // ----------------------------------------------------------------------------------------- | 439 | // --------------------------------------------------------------------------------------------- |
411 | 440 | ||
412 | SECTION("shutdown_timeout = <string>") | 441 | SECTION("on_state_create = <number>") |
413 | { | 442 | { |
414 | L.requireFailure("require 'lanes'.configure{shutdown_timeout = 'gluh'}"); | 443 | L.requireFailure("require 'lanes'.configure{on_state_create = 1}"); |
415 | } | 444 | } |
416 | 445 | ||
417 | // ----------------------------------------------------------------------------------------- | 446 | // --------------------------------------------------------------------------------------------- |
418 | 447 | ||
419 | SECTION("shutdown_timeout = <negative number>") | 448 | SECTION("on_state_create = false") |
420 | { | 449 | { |
421 | L.requireFailure("require 'lanes'.configure{shutdown_timeout = -0.001}"); | 450 | L.requireFailure("require 'lanes'.configure{on_state_create = false}"); |
422 | } | 451 | } |
423 | 452 | ||
424 | // ----------------------------------------------------------------------------------------- | 453 | // --------------------------------------------------------------------------------------------- |
425 | 454 | ||
426 | SECTION("shutdown_timeout = 0") | 455 | SECTION("on_state_create = true") |
427 | { | 456 | { |
428 | L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 0}"); | 457 | L.requireFailure("require 'lanes'.configure{on_state_create = true}"); |
429 | } | 458 | } |
430 | 459 | ||
431 | // ----------------------------------------------------------------------------------------- | 460 | // --------------------------------------------------------------------------------------------- |
432 | 461 | ||
433 | SECTION("shutdown_timeout = 1s") | 462 | SECTION("on_state_create = <Lua function>") |
434 | { | 463 | { |
435 | L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 1}"); | 464 | // on_state_create isn't called inside a Keeper state if it's a Lua function (which is good as print() doesn't exist there!) |
436 | } | 465 | L.requireSuccess("local print = print; require 'lanes'.configure{on_state_create = function() print 'hello' end}"); |
466 | } | ||
437 | 467 | ||
438 | // ----------------------------------------------------------------------------------------- | 468 | // --------------------------------------------------------------------------------------------- |
439 | 469 | ||
440 | SECTION("shutdown_timeout = 3600s") | 470 | SECTION("on_state_create = <C function>") |
441 | { | 471 | { |
442 | L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 3600}"); | 472 | // funnily enough, in Lua 5.3, print() uses global tostring(), that doesn't exist in a keeper since we didn't open libs -> "attempt to call a nil value" |
443 | } | 473 | // conclusion, don't use print() as a fake on_state_create() callback! |
474 | // assert() should be fine since we pass a non-false argument to on_state_create | ||
475 | L.requireSuccess("require 'lanes'.configure{on_state_create = assert}"); | ||
476 | } | ||
477 | } | ||
444 | 478 | ||
445 | // ----------------------------------------------------------------------------------------- | 479 | // ################################################################################################# |
446 | 480 | ||
447 | SECTION("shutdown_timeout = <too long>") | 481 | TEST_CASE("lanes.configure.shutdown_timeout") |
448 | { | 482 | { |
449 | L.requireFailure("require 'lanes'.configure{shutdown_timeout = 3600.001}"); | 483 | LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; |
450 | } | 484 | |
485 | // shutdown_timeout should be a number in [0,3600] | ||
486 | |||
487 | SECTION("shutdown_timeout = <table>") | ||
488 | { | ||
489 | L.requireFailure("require 'lanes'.configure{shutdown_timeout = {}}"); | ||
451 | } | 490 | } |
452 | 491 | ||
453 | // --------------------------------------------------------------------------------------------- | 492 | // --------------------------------------------------------------------------------------------- |
454 | // strip_functions should be a boolean | ||
455 | 493 | ||
456 | SECTION("strip_functions") | 494 | SECTION("shutdown_timeout = <string>") |
457 | { | 495 | { |
458 | SECTION("strip_functions = <table>") | 496 | L.requireFailure("require 'lanes'.configure{shutdown_timeout = 'gluh'}"); |
459 | { | 497 | } |
460 | L.requireFailure("require 'lanes'.configure{strip_functions = {}}"); | ||
461 | } | ||
462 | 498 | ||
463 | // ----------------------------------------------------------------------------------------- | 499 | // --------------------------------------------------------------------------------------------- |
464 | 500 | ||
465 | SECTION("strip_functions = <string>") | 501 | SECTION("shutdown_timeout = <negative number>") |
466 | { | 502 | { |
467 | L.requireFailure("require 'lanes'.configure{strip_functions = 'gluh'}"); | 503 | L.requireFailure("require 'lanes'.configure{shutdown_timeout = -0.001}"); |
468 | } | 504 | } |
469 | 505 | ||
470 | // ----------------------------------------------------------------------------------------- | 506 | // --------------------------------------------------------------------------------------------- |
471 | 507 | ||
472 | SECTION("strip_functions = <number>") | 508 | SECTION("shutdown_timeout = 0") |
473 | { | 509 | { |
474 | L.requireFailure("require 'lanes'.configure{strip_functions = 1}"); | 510 | L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 0}"); |
475 | } | 511 | } |
476 | 512 | ||
477 | // ----------------------------------------------------------------------------------------- | 513 | // --------------------------------------------------------------------------------------------- |
478 | 514 | ||
479 | SECTION("strip_functions = <C function>") | 515 | SECTION("shutdown_timeout = 1s") |
480 | { | 516 | { |
481 | L.requireFailure("require 'lanes'.configure{strip_functions = print}"); | 517 | L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 1}"); |
482 | } | 518 | } |
483 | 519 | ||
484 | // ----------------------------------------------------------------------------------------- | 520 | // --------------------------------------------------------------------------------------------- |
485 | 521 | ||
486 | SECTION("strip_functions = false") | 522 | SECTION("shutdown_timeout = 3600s") |
487 | { | 523 | { |
488 | L.requireSuccess("require 'lanes'.configure{strip_functions = false}"); | 524 | L.requireSuccess("require 'lanes'.configure{shutdown_timeout = 3600}"); |
489 | } | 525 | } |
490 | 526 | ||
491 | // ----------------------------------------------------------------------------------------- | 527 | // --------------------------------------------------------------------------------------------- |
492 | 528 | ||
493 | SECTION("strip_functions = true") | 529 | SECTION("shutdown_timeout = <too long>") |
494 | { | 530 | { |
495 | L.requireSuccess("require 'lanes'.configure{strip_functions = true}"); | 531 | L.requireFailure("require 'lanes'.configure{shutdown_timeout = 3600.001}"); |
496 | } | 532 | } |
533 | } | ||
534 | |||
535 | // ################################################################################################# | ||
536 | |||
537 | TEST_CASE("lanes.configure.strip_functions") | ||
538 | { | ||
539 | LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; | ||
540 | |||
541 | // strip_functions should be a boolean | ||
542 | |||
543 | SECTION("strip_functions = <table>") | ||
544 | { | ||
545 | L.requireFailure("require 'lanes'.configure{strip_functions = {}}"); | ||
497 | } | 546 | } |
498 | 547 | ||
499 | // --------------------------------------------------------------------------------------------- | 548 | // --------------------------------------------------------------------------------------------- |
500 | // track_lanes should be a boolean | ||
501 | 549 | ||
502 | SECTION("track_lanes") | 550 | SECTION("strip_functions = <string>") |
503 | { | 551 | { |
504 | SECTION("track_lanes = <table>") | 552 | L.requireFailure("require 'lanes'.configure{strip_functions = 'gluh'}"); |
505 | { | 553 | } |
506 | L.requireFailure("require 'lanes'.configure{track_lanes = {}}"); | ||
507 | } | ||
508 | 554 | ||
509 | // ----------------------------------------------------------------------------------------- | 555 | // --------------------------------------------------------------------------------------------- |
510 | 556 | ||
511 | SECTION("track_lanes = <string>") | 557 | SECTION("strip_functions = <number>") |
512 | { | 558 | { |
513 | L.requireFailure("require 'lanes'.configure{track_lanes = 'gluh'}"); | 559 | L.requireFailure("require 'lanes'.configure{strip_functions = 1}"); |
514 | } | 560 | } |
515 | 561 | ||
516 | // ----------------------------------------------------------------------------------------- | 562 | // --------------------------------------------------------------------------------------------- |
517 | 563 | ||
518 | SECTION("track_lanes = <number>") | 564 | SECTION("strip_functions = <C function>") |
519 | { | 565 | { |
520 | L.requireFailure("require 'lanes'.configure{track_lanes = 1}"); | 566 | L.requireFailure("require 'lanes'.configure{strip_functions = print}"); |
521 | } | 567 | } |
522 | 568 | ||
523 | // ----------------------------------------------------------------------------------------- | 569 | // --------------------------------------------------------------------------------------------- |
524 | 570 | ||
525 | SECTION("track_lanes = <C function>") | 571 | SECTION("strip_functions = false") |
526 | { | 572 | { |
527 | L.requireFailure("require 'lanes'.configure{track_lanes = print}"); | 573 | L.requireSuccess("require 'lanes'.configure{strip_functions = false}"); |
528 | } | 574 | } |
529 | 575 | ||
530 | // ----------------------------------------------------------------------------------------- | 576 | // --------------------------------------------------------------------------------------------- |
531 | 577 | ||
532 | SECTION("track_lanes = false") | 578 | SECTION("strip_functions = true") |
533 | { | 579 | { |
534 | L.requireSuccess("require 'lanes'.configure{track_lanes = false}"); | 580 | L.requireSuccess("require 'lanes'.configure{strip_functions = true}"); |
535 | } | 581 | } |
582 | } | ||
536 | 583 | ||
537 | // ----------------------------------------------------------------------------------------- | 584 | // ################################################################################################# |
538 | 585 | ||
539 | SECTION("track_lanes = true") | 586 | TEST_CASE("lanes.configure.track_lanes") |
540 | { | 587 | { |
541 | L.requireSuccess("require 'lanes'.configure{track_lanes = true}"); | 588 | LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; |
542 | } | 589 | |
590 | // track_lanes should be a boolean | ||
591 | |||
592 | SECTION("track_lanes = <table>") | ||
593 | { | ||
594 | L.requireFailure("require 'lanes'.configure{track_lanes = {}}"); | ||
543 | } | 595 | } |
544 | 596 | ||
545 | // --------------------------------------------------------------------------------------------- | 597 | // --------------------------------------------------------------------------------------------- |
546 | // verbose_errors should be a boolean | ||
547 | 598 | ||
548 | SECTION("verbose_errors") | 599 | SECTION("track_lanes = <string>") |
549 | { | 600 | { |
550 | SECTION("verbose_errors = <table>") | 601 | L.requireFailure("require 'lanes'.configure{track_lanes = 'gluh'}"); |
551 | { | 602 | } |
552 | L.requireFailure("require 'lanes'.configure{verbose_errors = {}}"); | ||
553 | } | ||
554 | 603 | ||
555 | // ----------------------------------------------------------------------------------------- | 604 | // --------------------------------------------------------------------------------------------- |
556 | 605 | ||
557 | SECTION("verbose_errors = <string>") | 606 | SECTION("track_lanes = <number>") |
558 | { | 607 | { |
559 | L.requireFailure("require 'lanes'.configure{verbose_errors = 'gluh'}"); | 608 | L.requireFailure("require 'lanes'.configure{track_lanes = 1}"); |
560 | } | 609 | } |
561 | 610 | ||
562 | // ----------------------------------------------------------------------------------------- | 611 | // --------------------------------------------------------------------------------------------- |
563 | 612 | ||
564 | SECTION("verbose_errors = <number>") | 613 | SECTION("track_lanes = <C function>") |
565 | { | 614 | { |
566 | L.requireFailure("require 'lanes'.configure{verbose_errors = 1}"); | 615 | L.requireFailure("require 'lanes'.configure{track_lanes = print}"); |
567 | } | 616 | } |
568 | 617 | ||
569 | // ----------------------------------------------------------------------------------------- | 618 | // --------------------------------------------------------------------------------------------- |
570 | 619 | ||
571 | SECTION("verbose_errors = <C function>") | 620 | SECTION("track_lanes = false") |
572 | { | 621 | { |
573 | L.requireFailure("require 'lanes'.configure{verbose_errors = print}"); | 622 | L.requireSuccess("require 'lanes'.configure{track_lanes = false}"); |
574 | } | 623 | } |
575 | 624 | ||
576 | // ----------------------------------------------------------------------------------------- | 625 | // --------------------------------------------------------------------------------------------- |
577 | 626 | ||
578 | SECTION("verbose_errors = false") | 627 | SECTION("track_lanes = true") |
579 | { | 628 | { |
580 | L.requireSuccess("require 'lanes'.configure{verbose_errors = false}"); | 629 | L.requireSuccess("require 'lanes'.configure{track_lanes = true}"); |
581 | } | 630 | } |
631 | } | ||
582 | 632 | ||
583 | // ----------------------------------------------------------------------------------------- | 633 | // ################################################################################################# |
584 | 634 | ||
585 | SECTION("verbose_errors = true") | 635 | TEST_CASE("lanes.configure.verbose_errors") |
586 | { | 636 | { |
587 | L.requireSuccess("require 'lanes'.configure{verbose_errors = true}"); | 637 | LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; |
588 | } | 638 | |
639 | // verbose_errors should be a boolean | ||
640 | |||
641 | SECTION("verbose_errors = <table>") | ||
642 | { | ||
643 | L.requireFailure("require 'lanes'.configure{verbose_errors = {}}"); | ||
589 | } | 644 | } |
590 | 645 | ||
591 | // --------------------------------------------------------------------------------------------- | 646 | // --------------------------------------------------------------------------------------------- |
592 | // with_timers should be a boolean | ||
593 | 647 | ||
594 | SECTION("with_timers") | 648 | SECTION("verbose_errors = <string>") |
595 | { | 649 | { |
596 | SECTION("with_timers = <table>") | 650 | L.requireFailure("require 'lanes'.configure{verbose_errors = 'gluh'}"); |
597 | { | 651 | } |
598 | L.requireFailure("require 'lanes'.configure{with_timers = {}}"); | ||
599 | } | ||
600 | 652 | ||
601 | // ----------------------------------------------------------------------------------------- | 653 | // --------------------------------------------------------------------------------------------- |
602 | 654 | ||
603 | SECTION("with_timers = <string>") | 655 | SECTION("verbose_errors = <number>") |
604 | { | 656 | { |
605 | L.requireFailure("require 'lanes'.configure{with_timers = 'gluh'}"); | 657 | L.requireFailure("require 'lanes'.configure{verbose_errors = 1}"); |
606 | } | 658 | } |
607 | 659 | ||
608 | // ----------------------------------------------------------------------------------------- | 660 | // --------------------------------------------------------------------------------------------- |
609 | 661 | ||
610 | SECTION("with_timers = <number>") | 662 | SECTION("verbose_errors = <C function>") |
611 | { | 663 | { |
612 | L.requireFailure("require 'lanes'.configure{with_timers = 1}"); | 664 | L.requireFailure("require 'lanes'.configure{verbose_errors = print}"); |
613 | } | 665 | } |
614 | 666 | ||
615 | // ----------------------------------------------------------------------------------------- | 667 | // --------------------------------------------------------------------------------------------- |
616 | 668 | ||
617 | SECTION("with_timers = <C function>") | 669 | SECTION("verbose_errors = false") |
618 | { | 670 | { |
619 | L.requireFailure("require 'lanes'.configure{with_timers = print}"); | 671 | L.requireSuccess("require 'lanes'.configure{verbose_errors = false}"); |
620 | } | 672 | } |
621 | 673 | ||
622 | // ----------------------------------------------------------------------------------------- | 674 | // --------------------------------------------------------------------------------------------- |
623 | 675 | ||
624 | SECTION("with_timers = false") | 676 | SECTION("verbose_errors = true") |
625 | { | 677 | { |
626 | L.requireSuccess("require 'lanes'.configure{with_timers = false}"); | 678 | L.requireSuccess("require 'lanes'.configure{verbose_errors = true}"); |
627 | } | 679 | } |
680 | } | ||
628 | 681 | ||
629 | // ----------------------------------------------------------------------------------------- | 682 | // ################################################################################################# |
630 | 683 | ||
631 | SECTION("with_timers = true") | 684 | TEST_CASE("lanes.configure.with_timers") |
632 | { | 685 | { |
633 | L.requireSuccess("require 'lanes'.configure{with_timers = true}"); | 686 | LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; |
634 | } | 687 | |
688 | // with_timers should be a boolean | ||
689 | |||
690 | SECTION("with_timers = <table>") | ||
691 | { | ||
692 | L.requireFailure("require 'lanes'.configure{with_timers = {}}"); | ||
693 | } | ||
694 | |||
695 | // --------------------------------------------------------------------------------------------- | ||
696 | |||
697 | SECTION("with_timers = <string>") | ||
698 | { | ||
699 | L.requireFailure("require 'lanes'.configure{with_timers = 'gluh'}"); | ||
635 | } | 700 | } |
636 | 701 | ||
637 | // --------------------------------------------------------------------------------------------- | 702 | // --------------------------------------------------------------------------------------------- |
703 | |||
704 | SECTION("with_timers = <number>") | ||
705 | { | ||
706 | L.requireFailure("require 'lanes'.configure{with_timers = 1}"); | ||
707 | } | ||
708 | |||
709 | // --------------------------------------------------------------------------------------------- | ||
710 | |||
711 | SECTION("with_timers = <C function>") | ||
712 | { | ||
713 | L.requireFailure("require 'lanes'.configure{with_timers = print}"); | ||
714 | } | ||
715 | |||
716 | // --------------------------------------------------------------------------------------------- | ||
717 | |||
718 | SECTION("with_timers = false") | ||
719 | { | ||
720 | L.requireSuccess("require 'lanes'.configure{with_timers = false}"); | ||
721 | } | ||
722 | |||
723 | // --------------------------------------------------------------------------------------------- | ||
724 | |||
725 | SECTION("with_timers = true") | ||
726 | { | ||
727 | L.requireSuccess("require 'lanes'.configure{with_timers = true}"); | ||
728 | } | ||
729 | } | ||
730 | |||
731 | // ################################################################################################# | ||
732 | |||
733 | TEST_CASE("lanes.configure.unknown_setting") | ||
734 | { | ||
735 | LuaState L{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; | ||
736 | |||
638 | // any unknown setting should be rejected | 737 | // any unknown setting should be rejected |
639 | 738 | ||
640 | SECTION("unknown_setting") | 739 | SECTION("table setting") |
641 | { | 740 | { |
642 | SECTION("table setting") | 741 | L.requireFailure("require 'lanes'.configure{[{}] = {}}"); |
643 | { | 742 | } |
644 | L.requireFailure("require 'lanes'.configure{[{}] = {}}"); | ||
645 | } | ||
646 | 743 | ||
647 | // ----------------------------------------------------------------------------------------- | 744 | // --------------------------------------------------------------------------------------------- |
648 | 745 | ||
649 | SECTION("boolean setting") | 746 | SECTION("boolean setting") |
650 | { | 747 | { |
651 | L.requireFailure("require 'lanes'.configure{[true] = 'gluh'}"); | 748 | L.requireFailure("require 'lanes'.configure{[true] = 'gluh'}"); |
652 | } | 749 | } |
653 | 750 | ||
654 | // ----------------------------------------------------------------------------------------- | 751 | // --------------------------------------------------------------------------------------------- |
655 | 752 | ||
656 | SECTION("function setting") | 753 | SECTION("function setting") |
657 | { | 754 | { |
658 | L.requireFailure("require 'lanes'.configure{[function() end] = 1}"); | 755 | L.requireFailure("require 'lanes'.configure{[function() end] = 1}"); |
659 | } | 756 | } |
660 | 757 | ||
661 | // ----------------------------------------------------------------------------------------- | 758 | // --------------------------------------------------------------------------------------------- |
662 | 759 | ||
663 | SECTION("number setting") | 760 | SECTION("number setting") |
664 | { | 761 | { |
665 | L.requireFailure("require 'lanes'.configure{[1] = function() end}"); | 762 | L.requireFailure("require 'lanes'.configure{[1] = function() end}"); |
666 | } | 763 | } |
667 | 764 | ||
668 | // ----------------------------------------------------------------------------------------- | 765 | // --------------------------------------------------------------------------------------------- |
669 | 766 | ||
670 | SECTION("unknown string setting") | 767 | SECTION("unknown string setting") |
671 | { | 768 | { |
672 | L.requireFailure("require 'lanes'.configure{['gluh'] = false}"); | 769 | L.requireFailure("require 'lanes'.configure{['gluh'] = false}"); |
673 | } | ||
674 | } | 770 | } |
675 | } | 771 | } |
676 | 772 | ||
@@ -679,7 +775,7 @@ TEST_CASE("lanes.configure.the rest") | |||
679 | 775 | ||
680 | #if LUAJIT_FLAVOR() == 0 | 776 | #if LUAJIT_FLAVOR() == 0 |
681 | // 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 |
682 | TEST_CASE("lanes.finally.no fixture") | 778 | TEST_CASE("lanes.finally.no_fixture") |
683 | { | 779 | { |
684 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; | 780 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; |
685 | // 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 |
@@ -700,7 +796,7 @@ TEST_CASE("lanes.finally.no fixture") | |||
700 | 796 | ||
701 | // ################################################################################################# | 797 | // ################################################################################################# |
702 | 798 | ||
703 | TEST_CASE("lanes.finally.with fixture") | 799 | TEST_CASE("lanes.finally.with_fixture") |
704 | { | 800 | { |
705 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | 801 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; |
706 | 802 | ||
@@ -718,7 +814,7 @@ TEST_CASE("lanes.finally.with fixture") | |||
718 | 814 | ||
719 | // ################################################################################################# | 815 | // ################################################################################################# |
720 | 816 | ||
721 | TEST_CASE("lanes.finally.shutdown with an uncooperative lane") | 817 | TEST_CASE("lanes.finally.shutdown_with_an_uncooperative_lane") |
722 | { | 818 | { |
723 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | 819 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; |
724 | S.requireSuccess("lanes = require 'lanes'.configure()"); | 820 | S.requireSuccess("lanes = require 'lanes'.configure()"); |
@@ -767,7 +863,7 @@ namespace | |||
767 | 863 | ||
768 | // ################################################################################################# | 864 | // ################################################################################################# |
769 | 865 | ||
770 | TEST_CASE("lanes.on_state_create setting") | 866 | TEST_CASE("lanes.configure.on_state_create/details") |
771 | { | 867 | { |
772 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; | 868 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ false } }; |
773 | 869 | ||
diff --git a/unit_tests/lane_tests.cpp b/unit_tests/lane_tests.cpp index d6ef2e0..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 | ||
36 | TEST_CASE("lanes.sleep.argument validation") | 38 | TEST_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 | |||
58 | TEST_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 | |||
108 | TEST_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 | |||
123 | TEST_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 | ||
100 | TEST_CASE("lanes.gen") | 180 | TEST_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 | |||
264 | TEST_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 | |||
279 | TEST_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,19 +420,24 @@ 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) \ |
323 | TEST_CASE("scripted tests." #DIR "." #FILE) \ | 424 | TEST_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 | ||
329 | MAKE_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 |
332 | MAKE_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 | |||
436 | MAKE_TEST_CASE(lane, body_is_a_c_function, AssertNoLuaError) | ||
437 | MAKE_TEST_CASE(lane, cooperative_shutdown, AssertNoLuaError) | ||
438 | MAKE_TEST_CASE_54(lane, uncooperative_shutdown, AssertWarns) // NOTE: when this test ends, there are resource leaks and a dangling thread | ||
334 | MAKE_TEST_CASE(lane, tasking_basic, AssertNoLuaError) | 439 | MAKE_TEST_CASE(lane, tasking_basic, AssertNoLuaError) |
440 | MAKE_TEST_CASE(lane, tasking_cancelling_with_hook, AssertNoLuaError) | ||
335 | MAKE_TEST_CASE(lane, tasking_cancelling, AssertNoLuaError) | 441 | MAKE_TEST_CASE(lane, tasking_cancelling, AssertNoLuaError) |
336 | MAKE_TEST_CASE(lane, tasking_comms_criss_cross, AssertNoLuaError) | 442 | MAKE_TEST_CASE(lane, tasking_comms_criss_cross, AssertNoLuaError) |
337 | MAKE_TEST_CASE(lane, tasking_communications, AssertNoLuaError) | 443 | MAKE_TEST_CASE(lane, tasking_communications, AssertNoLuaError) |
@@ -339,19 +445,27 @@ MAKE_TEST_CASE(lane, tasking_error, AssertNoLuaError) | |||
339 | MAKE_TEST_CASE(lane, tasking_join_test, AssertNoLuaError) | 445 | MAKE_TEST_CASE(lane, tasking_join_test, AssertNoLuaError) |
340 | MAKE_TEST_CASE(lane, tasking_send_receive_code, AssertNoLuaError) | 446 | MAKE_TEST_CASE(lane, tasking_send_receive_code, AssertNoLuaError) |
341 | MAKE_TEST_CASE(lane, stdlib_naming, AssertNoLuaError) | 447 | MAKE_TEST_CASE(lane, stdlib_naming, AssertNoLuaError) |
342 | MAKE_TEST_CASE(coro, basics, AssertNoLuaError) | 448 | MAKE_TEST_CASE(coro, cancelling_suspended, AssertNoLuaError) |
449 | MAKE_TEST_CASE_54(coro, collect_yielded_lane, AssertNoLuaError) | ||
343 | #if LUAJIT_FLAVOR() == 0 | 450 | #if LUAJIT_FLAVOR() == 0 |
344 | // 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 |
345 | MAKE_TEST_CASE(coro, error_handling, AssertNoLuaError) | 452 | MAKE_TEST_CASE(coro, error_handling, AssertNoLuaError) |
346 | #endif // LUAJIT_FLAVOR() | 453 | #endif // LUAJIT_FLAVOR() |
454 | MAKE_TEST_CASE(coro, index_suspended, AssertNoLuaError) | ||
455 | MAKE_TEST_CASE(coro, join_suspended, AssertNoLuaError) | ||
456 | MAKE_TEST_CASE_54(coro, linda_in_close_handler, AssertNoLuaError) | ||
457 | MAKE_TEST_CASE(coro, regular_function, AssertNoLuaError) | ||
458 | MAKE_TEST_CASE(coro, resume_basics, AssertNoLuaError) | ||
459 | MAKE_TEST_CASE(coro, yielding_in_non_coro_errors, AssertNoLuaError) | ||
347 | 460 | ||
348 | /* | 461 | /* |
349 | TEST_CASE("lanes.scripted tests") | 462 | TEST_CASE("lanes.scripted_tests") |
350 | { | 463 | { |
351 | auto const& _testParam = GENERATE( | 464 | auto const& _testParam = GENERATE( |
352 | FileRunnerParam{ PUC_LUA_ONLY("lane/cooperative_shutdown"), TestType::AssertNoLuaError }, // 0 | 465 | FileRunnerParam{ PUC_LUA_ONLY("lane/cooperative_shutdown"), TestType::AssertNoLuaError }, // 0 |
353 | FileRunnerParam{ "lane/uncooperative_shutdown", TestType::AssertWarns }, | 466 | FileRunnerParam{ "lane/uncooperative_shutdown", TestType::AssertWarns }, |
354 | FileRunnerParam{ "lane/tasking_basic", TestType::AssertNoLuaError }, // 2 | 467 | FileRunnerParam{ "lane/tasking_basic", TestType::AssertNoLuaError }, // 2 |
468 | FileRunnerParam{ "lane/tasking_cancelling_with_hook", TestType::AssertNoLuaError }, // 3 | ||
355 | FileRunnerParam{ "lane/tasking_cancelling", TestType::AssertNoLuaError }, // 3 | 469 | FileRunnerParam{ "lane/tasking_cancelling", TestType::AssertNoLuaError }, // 3 |
356 | FileRunnerParam{ "lane/tasking_comms_criss_cross", TestType::AssertNoLuaError }, // 4 | 470 | FileRunnerParam{ "lane/tasking_comms_criss_cross", TestType::AssertNoLuaError }, // 4 |
357 | FileRunnerParam{ "lane/tasking_communications", TestType::AssertNoLuaError }, | 471 | FileRunnerParam{ "lane/tasking_communications", TestType::AssertNoLuaError }, |
diff --git a/unit_tests/legacy_tests.cpp b/unit_tests/legacy_tests.cpp index 7f2f31d..84581d2 100644 --- a/unit_tests/legacy_tests.cpp +++ b/unit_tests/legacy_tests.cpp | |||
@@ -11,7 +11,7 @@ | |||
11 | // so let's create a separate test case for each file with an ugly macro... | 11 | // so let's create a separate test case for each file with an ugly macro... |
12 | 12 | ||
13 | #define MAKE_TEST_CASE(FILE) \ | 13 | #define MAKE_TEST_CASE(FILE) \ |
14 | TEST_CASE("scripted tests.legacy." #FILE) \ | 14 | TEST_CASE("scripted_tests.legacy." #FILE) \ |
15 | { \ | 15 | { \ |
16 | FileRunner _runner(R"(.\tests\)"); \ | 16 | FileRunner _runner(R"(.\tests\)"); \ |
17 | _runner.performTest(FileRunnerParam{ #FILE, TestType::AssertNoLuaError }); \ | 17 | _runner.performTest(FileRunnerParam{ #FILE, TestType::AssertNoLuaError }); \ |
@@ -49,7 +49,7 @@ MAKE_TEST_CASE(tobeclosed) | |||
49 | MAKE_TEST_CASE(track_lanes) | 49 | MAKE_TEST_CASE(track_lanes) |
50 | 50 | ||
51 | /* | 51 | /* |
52 | TEST_CASE("lanes.legacy scripted tests") | 52 | TEST_CASE("lanes.legacy_scripted_tests") |
53 | { | 53 | { |
54 | auto const& _testParam = GENERATE( | 54 | auto const& _testParam = GENERATE( |
55 | FileRunnerParam{ "appendud", TestType::AssertNoLuaError } // 0 | 55 | FileRunnerParam{ "appendud", TestType::AssertNoLuaError } // 0 |
diff --git a/unit_tests/linda_tests.cpp b/unit_tests/linda_tests.cpp index efdb8a5..90630a7 100644 --- a/unit_tests/linda_tests.cpp +++ b/unit_tests/linda_tests.cpp | |||
@@ -3,154 +3,216 @@ | |||
3 | 3 | ||
4 | // ################################################################################################# | 4 | // ################################################################################################# |
5 | 5 | ||
6 | TEST_CASE("linda.single Keeper") | 6 | TEST_CASE("linda.single_keeper.creation/no_argument") |
7 | { | 7 | { |
8 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | 8 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; |
9 | S.requireSuccess("lanes = require 'lanes'"); | 9 | S.requireSuccess("lanes = require 'lanes'"); |
10 | 10 | ||
11 | SECTION("Linda creation") | 11 | // no argument is ok |
12 | { | 12 | S.requireSuccess("lanes.linda()"); |
13 | // no parameters is ok | 13 | S.requireNotReturnedString("return tostring(lanes.linda())", R"===(Linda: <not a string>)==="); // unspecified name should not result in <not a string> |
14 | S.requireSuccess("lanes.linda()"); | 14 | } |
15 | S.requireNotReturnedString("return tostring(lanes.linda())", R"===(Linda: <not a string>)==="); // unspecified name should not result in <not a string> | ||
16 | |||
17 | // since we have only one keeper, only group 0 is authorized | ||
18 | S.requireFailure("lanes.linda(-1)"); | ||
19 | S.requireSuccess("lanes.linda(0)"); | ||
20 | S.requireFailure("lanes.linda(1)"); | ||
21 | |||
22 | // any name is ok | ||
23 | S.requireSuccess("lanes.linda('')"); // an empty name results in a string conversion of the form "Linda: <some hex value>" that we can't test (but it works) | ||
24 | S.requireReturnedString("return tostring(lanes.linda('short name'))", R"===(Linda: short name)==="); | ||
25 | S.requireReturnedString("return tostring(lanes.linda('very very very very very very long name'))", R"===(Linda: very very very very very very long name)==="); | ||
26 | S.requireReturnedString("return tostring(lanes.linda('auto'))", R"===(Linda: [string "return tostring(lanes.linda('auto'))"]:1)==="); | ||
27 | |||
28 | if constexpr (LUA_VERSION_NUM == 504) { | ||
29 | // a function is acceptable as a __close handler | ||
30 | S.requireSuccess("local l <close> = lanes.linda(function() end)"); | ||
31 | // a callable table too (a callable full userdata as well, but I have none here) | ||
32 | S.requireSuccess("local l <close> = lanes.linda(setmetatable({}, {__call = function() end}))"); | ||
33 | // if the function raises an error, we should get it | ||
34 | S.requireFailure("local l <close> = lanes.linda(function() error 'gluh' end)"); | ||
35 | } else { | ||
36 | // no __close support before Lua 5.4 | ||
37 | S.requireFailure("lanes.linda(function() end)"); | ||
38 | S.requireFailure("lanes.linda(setmetatable({}, {__call = function() end}))"); | ||
39 | } | ||
40 | 15 | ||
41 | // mixing parameters in any order is ok: 2 out of 3 | 16 | // ################################################################################################# |
42 | S.requireSuccess("lanes.linda(0, 'name')"); | ||
43 | S.requireSuccess("lanes.linda('name', 0)"); | ||
44 | if constexpr (LUA_VERSION_NUM == 504) { | ||
45 | S.requireSuccess("lanes.linda(0, function() end)"); | ||
46 | S.requireSuccess("lanes.linda(function() end, 0)"); | ||
47 | S.requireSuccess("lanes.linda('name', function() end)"); | ||
48 | S.requireSuccess("lanes.linda(function() end, 'name')"); | ||
49 | } | ||
50 | 17 | ||
51 | // mixing parameters in any order is ok: 3 out of 3 | 18 | TEST_CASE("linda.single_keeper.creation/non_table_arguments") |
52 | if constexpr (LUA_VERSION_NUM == 504) { | 19 | { |
53 | S.requireSuccess("lanes.linda(0, 'name', function() end)"); | 20 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; |
54 | S.requireSuccess("lanes.linda(0, function() end, 'name')"); | 21 | S.requireSuccess("lanes = require 'lanes'"); |
55 | S.requireSuccess("lanes.linda('name', 0, function() end)"); | 22 | |
56 | S.requireSuccess("lanes.linda('name', function() end, 0)"); | 23 | // any argument that is not a table is not ok |
57 | S.requireSuccess("lanes.linda(function() end, 0, 'name')"); | 24 | S.requireFailure("lanes.linda(0)"); |
58 | S.requireSuccess("lanes.linda(function() end, 'name', 0)"); | 25 | S.requireFailure("lanes.linda('bob')"); |
59 | } | 26 | S.requireFailure("lanes.linda(false)"); |
27 | S.requireFailure("lanes.linda(function() end)"); | ||
28 | S.requireFailure("lanes.linda(lanes.cancel_error)"); | ||
29 | } | ||
30 | |||
31 | // ################################################################################################# | ||
60 | 32 | ||
61 | // unsupported parameters should fail | 33 | TEST_CASE("linda.single_keeper.creation/close_handler") |
62 | S.requireFailure("lanes.linda(true)"); | 34 | { |
63 | S.requireFailure("lanes.linda(false)"); | 35 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; |
64 | // uncallable table or full userdata | 36 | S.requireSuccess("lanes = require 'lanes'"); |
65 | S.requireFailure("lanes.linda({})"); | 37 | |
66 | S.requireFailure("lanes.linda(lanes.linda())"); | 38 | if constexpr (LUA_VERSION_NUM >= 504) { |
39 | // a function is acceptable as a __close handler | ||
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) | ||
42 | S.requireSuccess("local l <close> = lanes.linda{close_handler = setmetatable({}, {__call = function() end})}"); | ||
43 | } else { | ||
44 | // no __close support before Lua 5.4, field is ignored (therefore invalid values are accepted too!) | ||
45 | S.requireSuccess("lanes.linda{close_handler = 'a string'}"); | ||
46 | S.requireSuccess("lanes.linda{close_handler = function() end}"); | ||
47 | S.requireSuccess("lanes.linda{close_handler = setmetatable({}, {__call = function() end})}"); | ||
67 | } | 48 | } |
49 | } | ||
68 | 50 | ||
69 | // --------------------------------------------------------------------------------------------- | 51 | // ################################################################################################# |
52 | |||
53 | TEST_CASE("linda.single_keeper.creation/table_argument") | ||
54 | { | ||
55 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | ||
56 | S.requireSuccess("lanes = require 'lanes'"); | ||
57 | |||
58 | // one table is fine | ||
59 | S.requireSuccess("lanes.linda{}"); | ||
60 | // anything beyond that is not | ||
61 | S.requireFailure("lanes.linda({},{})"); | ||
62 | S.requireFailure("lanes.linda({},'bob')"); | ||
63 | S.requireFailure("lanes.linda({},42)"); | ||
64 | } | ||
65 | |||
66 | // ################################################################################################# | ||
67 | |||
68 | TEST_CASE("linda.single_keeper.creation/group") | ||
69 | { | ||
70 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | ||
71 | S.requireSuccess("lanes = require 'lanes'"); | ||
72 | |||
73 | // since we have only one keeper, only group 0 is authorized | ||
74 | S.requireFailure("lanes.linda{group = -1}"); | ||
75 | S.requireSuccess("lanes.linda{group = 0}"); | ||
76 | S.requireFailure("lanes.linda{group = 1}"); | ||
77 | } | ||
78 | |||
79 | // ################################################################################################# | ||
80 | |||
81 | TEST_CASE("linda.single_keeper.creation/name") | ||
82 | { | ||
83 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | ||
84 | S.requireSuccess("lanes = require 'lanes'"); | ||
85 | |||
86 | // any name is ok | ||
87 | S.requireSuccess("lanes.linda{name = ''}"); // an empty name results in a string conversion of the form "Linda: <some hex value>" that we can't test (but it works) | ||
88 | S.requireReturnedString("return tostring(lanes.linda{name = 'short name'})", R"===(Linda: short name)==="); | ||
89 | S.requireReturnedString("return tostring(lanes.linda{name = 'very very very very very very long name'})", R"===(Linda: very very very very very very long name)==="); | ||
90 | S.requireReturnedString("return tostring(lanes.linda{name = 'auto'})", R"===(Linda: [string "return tostring(lanes.linda{name = 'auto'})"]:1)==="); | ||
91 | } | ||
92 | |||
93 | // ################################################################################################# | ||
94 | |||
95 | TEST_CASE("linda.single_keeper.creation/wake_period") | ||
96 | { | ||
97 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | ||
98 | S.requireSuccess("lanes = require 'lanes'"); | ||
99 | |||
100 | // wake_period should be a number > 0 | ||
101 | S.requireFailure("lanes.linda{wake_period = false}"); | ||
102 | S.requireFailure("lanes.linda{wake_period = 'bob'}"); | ||
103 | S.requireFailure("lanes.linda{wake_period = {}}"); | ||
104 | S.requireFailure("lanes.linda{wake_period = -1}"); | ||
105 | S.requireFailure("lanes.linda{wake_period = 0}"); | ||
106 | S.requireSuccess("lanes.linda{wake_period = 0.0001}"); | ||
107 | S.requireSuccess("lanes.linda{wake_period = 'never'}"); | ||
108 | } | ||
109 | |||
110 | // ################################################################################################# | ||
70 | 111 | ||
71 | SECTION("Linda indexing") | 112 | TEST_CASE("linda.single_keeper.indexing") |
113 | { | ||
114 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; | ||
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 | } | ||
125 | |||
126 | // ################################################################################################# | ||
127 | |||
128 | TEST_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") | ||
72 | { | 134 | { |
73 | // indexing the linda with an unknown string key should fail | 135 | // timeout checks |
74 | S.requireFailure("return lanes.linda().gouikra"); | 136 | // linda:send() should fail if the timeout is bad |
75 | // indexing the linda with an unsupported key type should fail | 137 | S.requireFailure("lanes.linda():send(-1, 'k', 'v')"); |
76 | S.requireFailure("return lanes.linda()[5]"); | 138 | // any positive value is ok |
77 | S.requireFailure("return lanes.linda()[false]"); | 139 | S.requireSuccess("lanes.linda():send(0, 'k', 'v')"); |
78 | S.requireFailure("return lanes.linda()[{}]"); | 140 | S.requireSuccess("lanes.linda():send(1e20, 'k', 'v')"); |
79 | S.requireFailure("return lanes.linda()[function() end]"); | 141 | // nil too (same as 'forever') |
142 | S.requireSuccess("lanes.linda():send(nil, 'k', 'v')"); | ||
80 | } | 143 | } |
81 | 144 | ||
82 | // --------------------------------------------------------------------------------------------- | 145 | // ----------------------------------------------------------------------------------------- |
83 | SECTION("linda:send()") | 146 | |
147 | SECTION("fails on bad keys") | ||
84 | { | 148 | { |
85 | SECTION("timeout") | 149 | // key checks |
86 | { | 150 | // linda:send() should fail if the key is unsupported (nil, table, function, full userdata, reserved light userdata) |
87 | // timeout checks | 151 | S.requireFailure("lanes.linda():send(0, nil, 'v')"); |
88 | // linda:send() should fail if the timeout is bad | 152 | S.requireFailure("lanes.linda():send(0, {}, 'v')"); |
89 | S.requireFailure("lanes.linda():send(-1, 'k', 'v')"); | 153 | S.requireFailure("lanes.linda():send(0, function() end, 'v')"); |
90 | // any positive value is ok | 154 | S.requireFailure("lanes.linda():send(0, io.stdin, 'v')"); |
91 | S.requireSuccess("lanes.linda():send(0, 'k', 'v')"); | 155 | S.requireFailure("lanes.linda():send(0, lanes.null, 'v')"); |
92 | S.requireSuccess("lanes.linda():send(1e20, 'k', 'v')"); | 156 | S.requireFailure("lanes.linda():send(0, lanes.cancel_error, 'v')"); |
93 | // nil too (same as 'forever') | 157 | } |
94 | S.requireSuccess("lanes.linda():send(nil, 'k', 'v')"); | ||
95 | } | ||
96 | 158 | ||
97 | // ----------------------------------------------------------------------------------------- | 159 | // ----------------------------------------------------------------------------------------- |
98 | 160 | ||
99 | SECTION("fails on bad keys") | 161 | SECTION("succeeds on supported keys") |
100 | { | 162 | { |
101 | // key checks | 163 | // supported keys are ok: boolean, number, string, light userdata, deep userdata |
102 | // linda:send() should fail if the key is unsupported (nil, table, function, full userdata, reserved light userdata) | 164 | S.requireSuccess("lanes.linda():send(0, true, 'v')"); |
103 | S.requireFailure("lanes.linda():send(0, nil, 'v')"); | 165 | S.requireSuccess("lanes.linda():send(0, false, 'v')"); |
104 | S.requireFailure("lanes.linda():send(0, {}, 'v')"); | 166 | S.requireSuccess("lanes.linda():send(0, 99, 'v')"); |
105 | S.requireFailure("lanes.linda():send(0, function() end, 'v')"); | 167 | S.requireSuccess("local l = lanes.linda(); l:send(0, l:deep(), 'v')"); |
106 | S.requireFailure("lanes.linda():send(0, io.stdin, 'v')"); | 168 | } |
107 | S.requireFailure("lanes.linda():send(0, lanes.null, 'v')"); | ||
108 | S.requireFailure("lanes.linda():send(0, lanes.cancel_error, 'v')"); | ||
109 | S.requireFailure("local l = lanes.linda(); l:send(0, l.batched, 'v')"); | ||
110 | } | ||
111 | 169 | ||
112 | // ----------------------------------------------------------------------------------------- | 170 | // ----------------------------------------------------------------------------------------- |
113 | 171 | ||
114 | SECTION("succeeds on supported keys") | 172 | SECTION("succeeds on deep userdata key") |
115 | { | 173 | { |
116 | // supported keys are ok: boolean, number, string, light userdata, deep userdata | 174 | S.requireSuccess("local l = lanes.linda(); l:send(0, l, 'v')"); |
117 | S.requireSuccess("lanes.linda():send(0, true, 'v')"); | 175 | } |
118 | S.requireSuccess("lanes.linda():send(0, false, 'v')"); | ||
119 | S.requireSuccess("lanes.linda():send(0, 99, 'v')"); | ||
120 | S.requireSuccess("local l = lanes.linda(); l:send(0, l:deep(), 'v')"); | ||
121 | } | ||
122 | 176 | ||
123 | // ----------------------------------------------------------------------------------------- | 177 | // ----------------------------------------------------------------------------------------- |
124 | 178 | ||
125 | SECTION("succeeds on deep userdata key") | 179 | SECTION(". fails") |
126 | { | 180 | { |
127 | S.requireSuccess("local l = lanes.linda(); l:send(0, l, 'v')"); | 181 | // misuse checks, . instead of : |
128 | } | 182 | S.requireFailure("lanes.linda().send(nil, 'k', 'v')"); |
183 | } | ||
129 | 184 | ||
130 | // ----------------------------------------------------------------------------------------- | 185 | // ----------------------------------------------------------------------------------------- |
131 | 186 | ||
132 | SECTION(". fails") | 187 | SECTION("unsupported values fail") |
133 | { | 188 | { |
134 | // misuse checks, . instead of : | 189 | // value checks |
135 | S.requireFailure("lanes.linda().send(nil, 'k', 'v')"); | 190 | // linda:send() should fail if we don't send anything |
136 | } | 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 | } | ||
137 | 202 | ||
138 | // ----------------------------------------------------------------------------------------- | 203 | // ################################################################################################# |
139 | 204 | ||
140 | SECTION("unsupported values fail") | 205 | TEST_CASE("linda.single_keeper.the_rest") |
141 | { | 206 | { |
142 | // value checks | 207 | LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; |
143 | // linda:send() should fail if we don't send anything | 208 | S.requireSuccess("lanes = require 'lanes'"); |
144 | S.requireFailure("lanes.linda():send()"); | 209 | |
145 | S.requireFailure("lanes.linda():send(0)"); | 210 | // --------------------------------------------------------------------------------------------- |
146 | S.requireFailure("lanes.linda():send(0, 'k')"); | 211 | |
147 | // or non-deep userdata | 212 | SECTION("error in close handler is propagated") |
148 | S.requireFailure("lanes.linda():send(0, 'k', fixture.newuserdata())"); | 213 | { |
149 | // or something with a converter that raises an error (maybe that should go to a dedicated __lanesconvert test!) | 214 | // if the function raises an error, we should get it |
150 | S.requireFailure("lanes.linda():send(0, 'k', setmetatable({}, {__lanesconvert = function(where_) error (where_ .. ': should not send me' end}))"); | 215 | S.requireFailure("local l <close> = lanes.linda{close_handler = function() error 'gluh' end}"); |
151 | // but a registered non-deep userdata should work | ||
152 | S.requireSuccess("lanes.linda():send(0, 'k', io.stdin)"); | ||
153 | } | ||
154 | } | 216 | } |
155 | 217 | ||
156 | // --------------------------------------------------------------------------------------------- | 218 | // --------------------------------------------------------------------------------------------- |
@@ -312,12 +374,12 @@ TEST_CASE("linda.multi Keeper") | |||
312 | 374 | ||
313 | S.requireSuccess("lanes = require 'lanes'.configure{nb_user_keepers = 3}"); | 375 | S.requireSuccess("lanes = require 'lanes'.configure{nb_user_keepers = 3}"); |
314 | 376 | ||
315 | S.requireFailure("lanes.linda(-1)"); | 377 | S.requireFailure("lanes.linda{group = -1}"); |
316 | S.requireSuccess("lanes.linda(0)"); | 378 | S.requireSuccess("lanes.linda{group = 0}"); |
317 | S.requireSuccess("lanes.linda(1)"); | 379 | S.requireSuccess("lanes.linda{group = 1}"); |
318 | S.requireSuccess("lanes.linda(2)"); | 380 | S.requireSuccess("lanes.linda{group = 2}"); |
319 | S.requireSuccess("lanes.linda(3)"); | 381 | S.requireSuccess("lanes.linda{group = 3}"); |
320 | S.requireFailure("lanes.linda(4)"); | 382 | S.requireFailure("lanes.linda{group = 4}"); |
321 | } | 383 | } |
322 | 384 | ||
323 | // ################################################################################################# | 385 | // ################################################################################################# |
@@ -327,23 +389,26 @@ TEST_CASE("linda.multi Keeper") | |||
327 | // so let's create a separate test case for each file with an ugly macro... | 389 | // so let's create a separate test case for each file with an ugly macro... |
328 | 390 | ||
329 | #define MAKE_TEST_CASE(DIR, FILE) \ | 391 | #define MAKE_TEST_CASE(DIR, FILE) \ |
330 | TEST_CASE("scripted tests." #DIR "." #FILE) \ | 392 | TEST_CASE("scripted_tests." #DIR "." #FILE) \ |
331 | { \ | 393 | { \ |
332 | FileRunner _runner(R"(.\unit_tests\scripts)"); \ | 394 | FileRunner _runner(R"(.\unit_tests\scripts)"); \ |
333 | _runner.performTest(FileRunnerParam{ #DIR "/" #FILE, TestType::AssertNoLuaError }); \ | 395 | _runner.performTest(FileRunnerParam{ #DIR "/" #FILE, TestType::AssertNoLuaError }); \ |
334 | } | 396 | } |
335 | 397 | ||
398 | MAKE_TEST_CASE(linda, multiple_keepers) | ||
336 | MAKE_TEST_CASE(linda, send_receive) | 399 | MAKE_TEST_CASE(linda, send_receive) |
400 | MAKE_TEST_CASE(linda, send_receive_func_and_string) | ||
337 | MAKE_TEST_CASE(linda, send_registered_userdata) | 401 | MAKE_TEST_CASE(linda, send_registered_userdata) |
338 | MAKE_TEST_CASE(linda, multiple_keepers) | 402 | MAKE_TEST_CASE(linda, wake_period) |
339 | 403 | ||
340 | /* | 404 | /* |
341 | TEST_CASE("linda.scripted tests") | 405 | TEST_CASE("linda.scripted_tests") |
342 | { | 406 | { |
343 | auto const& _testParam = GENERATE( | 407 | auto const& _testParam = GENERATE( |
408 | FileRunnerParam{ "linda/multiple_keepers", TestType::AssertNoLuaError }, | ||
344 | FileRunnerParam{ "linda/send_receive", TestType::AssertNoLuaError }, | 409 | FileRunnerParam{ "linda/send_receive", TestType::AssertNoLuaError }, |
345 | FileRunnerParam{ "linda/send_registered_userdata", TestType::AssertNoLuaError }, | 410 | FileRunnerParam{ "linda/send_registered_userdata", TestType::AssertNoLuaError }, |
346 | FileRunnerParam{ "linda/multiple_keepers", TestType::AssertNoLuaError } | 411 | FileRunnerParam{ "linda/wake_period", TestType::AssertNoLuaError } |
347 | ); | 412 | ); |
348 | 413 | ||
349 | FileRunner _runner(R"(.\unit_tests\scripts)"); | 414 | FileRunner _runner(R"(.\unit_tests\scripts)"); |
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 |
69 | end | 69 | end |
70 | 70 | ||
71 | -- a function that yields back what got in, one element at a time | ||
72 | local 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!" | ||
86 | end | ||
87 | |||
71 | return { | 88 | return { |
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 @@ | |||
1 | local utils = require "_utils" | ||
2 | |||
3 | -- expand _utils module with Lua5.4 specific stuff | ||
4 | |||
5 | -- a lane body that yields stuff | ||
6 | utils.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 | ||
28 | end | ||
29 | |||
30 | return 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 @@ | |||
1 | local lanes = require "lanes" | ||
2 | |||
3 | local fixture = require "fixture" | ||
4 | lanes.finally(fixture.throwing_finalizer) | ||
5 | |||
6 | local utils = lanes.require "_utils" | ||
7 | local PRINT = utils.MAKE_PRINT() | ||
8 | |||
9 | if 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") | ||
27 | end | ||
28 | |||
29 | -- a lane coroutine that yields back what got in, one element at a time | ||
30 | local 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!" | ||
41 | end | ||
42 | |||
43 | if 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) | ||
61 | end | ||
62 | |||
63 | -- the generator | ||
64 | local coro_g = lanes.coro("*", {name = "auto"}, yielder) | ||
65 | |||
66 | if 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!") | ||
76 | end | ||
77 | |||
78 | if 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") | ||
97 | end | ||
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 @@ | |||
1 | local fixture = require "fixture" | ||
2 | local lanes = require "lanes".configure{on_state_create = fixture.on_state_create} | ||
3 | |||
4 | local fixture = require "fixture" | ||
5 | lanes.finally(fixture.throwing_finalizer) | ||
6 | |||
7 | local utils = lanes.require "_utils" | ||
8 | local PRINT = utils.MAKE_PRINT() | ||
9 | |||
10 | -------------------------------------------------- | ||
11 | -- TEST: cancelling a suspended Lane should end it | ||
12 | -------------------------------------------------- | ||
13 | if 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) | ||
31 | end | ||
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 @@ | |||
1 | local fixture = require "fixture" | ||
2 | local lanes = require "lanes".configure{on_state_create = fixture.on_state_create} | ||
3 | |||
4 | local fixture = require "fixture" | ||
5 | lanes.finally(fixture.throwing_finalizer) | ||
6 | |||
7 | -- this test is only for Lua 5.4+ | ||
8 | local utils = lanes.require "_utils54" | ||
9 | local PRINT = utils.MAKE_PRINT() | ||
10 | |||
11 | local out_linda = lanes.linda() | ||
12 | |||
13 | ------------------------------------------------------------------------------ | ||
14 | -- TEST: to-be-closed variables are properly closed when the lane is collected | ||
15 | ------------------------------------------------------------------------------ | ||
16 | if 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 | ||
35 | end | ||
36 | |||
37 | --------------------------------------------------------------------------------------------------- | ||
38 | -- TEST: if a to-be-closed handler takes longer than the join timeout, everything works as expected | ||
39 | --------------------------------------------------------------------------------------------------- | ||
40 | if 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 | ||
64 | end | ||
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) |
39 | end | 39 | end |
40 | 40 | ||
41 | if false then | 41 | if true then |
42 | force_error_test("minimal") | 42 | force_error_test("minimal") |
43 | end | 43 | end |
44 | 44 | ||
45 | if false then | 45 | if true then |
46 | force_error_test("basic") | 46 | force_error_test("basic") |
47 | end | 47 | end |
48 | 48 | ||
49 | if false then | 49 | if true then |
50 | force_error_test("extended") | 50 | force_error_test("extended") |
51 | end | 51 | end |
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 @@ | |||
1 | local lanes = require "lanes" | ||
2 | |||
3 | local fixture = require "fixture" | ||
4 | lanes.finally(fixture.throwing_finalizer) | ||
5 | |||
6 | local utils = lanes.require "_utils" | ||
7 | local PRINT = utils.MAKE_PRINT() | ||
8 | |||
9 | -- the coroutine generator | ||
10 | local 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 | ------------------------------------------------------------------------- | ||
15 | if 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") | ||
28 | end | ||
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 @@ | |||
1 | local lanes = require "lanes" | ||
2 | |||
3 | local fixture = require "fixture" | ||
4 | lanes.finally(fixture.throwing_finalizer) | ||
5 | |||
6 | local utils = lanes.require "_utils" | ||
7 | local PRINT = utils.MAKE_PRINT() | ||
8 | |||
9 | -- the coroutine generator | ||
10 | local 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 | --------------------------------------------------- | ||
15 | if 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)) | ||
24 | end | ||
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 @@ | |||
1 | local fixture = require "fixture" | ||
2 | local lanes = require "lanes".configure{on_state_create = fixture.on_state_create} | ||
3 | |||
4 | local fixture = require "fixture" | ||
5 | lanes.finally(fixture.throwing_finalizer) | ||
6 | |||
7 | -- this test is only for Lua 5.4+ | ||
8 | local utils = lanes.require "_utils54" | ||
9 | local PRINT = utils.MAKE_PRINT() | ||
10 | |||
11 | local out_linda = lanes.linda() | ||
12 | |||
13 | local 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)) | ||
26 | end | ||
27 | |||
28 | --------------------------------------------------------- | ||
29 | -- TEST: first, try the close mechanism outside of a lane | ||
30 | --------------------------------------------------------- | ||
31 | if true then | ||
32 | assert(type(utils.yielder_with_to_be_closed) == "function") | ||
33 | test_close("base", utils.yielder_with_to_be_closed) | ||
34 | end | ||
35 | |||
36 | --------------------------------------------------------------- | ||
37 | -- TEST: try again with a function obtained through dump/undump | ||
38 | --------------------------------------------------------------- | ||
39 | if 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))) | ||
42 | end | ||
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 @@ | |||
1 | local lanes = require "lanes".configure() | ||
2 | |||
3 | local utils = lanes.require "_utils" | ||
4 | local PRINT = utils.MAKE_PRINT() | ||
5 | |||
6 | -- a lane body that just returns some value | ||
7 | local 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" | ||
13 | end | ||
14 | |||
15 | -- a function that returns some value can run in a coroutine | ||
16 | if 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") | ||
25 | end | ||
26 | |||
27 | -- can't resume a coro after the lane body has returned | ||
28 | if 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") | ||
38 | end | ||
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 @@ | |||
1 | local lanes = require "lanes" | ||
2 | |||
3 | local fixture = require "fixture" | ||
4 | lanes.finally(fixture.throwing_finalizer) | ||
5 | |||
6 | local utils = lanes.require "_utils" | ||
7 | local PRINT = utils.MAKE_PRINT() | ||
8 | |||
9 | -- the coroutine generator | ||
10 | local 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 | ------------------------------------------------------------------------------------------------- | ||
15 | if 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!") | ||
25 | end | ||
26 | |||
27 | --------------------------------------------------------------------------------------------- | ||
28 | -- TEST: we can resume as many times as the lane yields, then read the returned value on join | ||
29 | --------------------------------------------------------------------------------------------- | ||
30 | if 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!") | ||
40 | end | ||
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 @@ | |||
1 | local lanes = require "lanes" | ||
2 | |||
3 | local fixture = require "fixture" | ||
4 | lanes.finally(fixture.throwing_finalizer) | ||
5 | |||
6 | local utils = lanes.require "_utils" | ||
7 | local 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 | -------------------------------------------------------------------------------------------------- | ||
12 | local fun_g = lanes.gen("*", { name = 'auto' }, utils.yield_one_by_one) | ||
13 | local h = fun_g("hello", "world", "!") | ||
14 | local err, status, stack = h:join() | ||
15 | PRINT(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. | ||
19 | local 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 | } | ||
26 | local expected_msg = msgs[_VERSION] | ||
27 | PRINT("expected_msg = " .. expected_msg) | ||
28 | assert(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 @@ | |||
1 | local lanes = require "lanes".configure() | ||
2 | |||
3 | -- ################################################################################################## | ||
4 | -- ################################################################################################## | ||
5 | -- ################################################################################################## | ||
6 | |||
7 | -- we can create a generator where the lane body is a C function | ||
8 | do | ||
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") | ||
16 | end | ||
17 | |||
18 | -- we can create a generator where the lane body is a C function that raises an error | ||
19 | do | ||
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) | ||
28 | end | ||
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 @@ | |||
1 | local lanes = require "lanes" | 1 | local 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 | ||
5 | local lane1 = function() | 5 | local 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 | |||
23 | local lane3 = function() | 23 | local 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) |
29 | end | 28 | end |
@@ -43,7 +42,14 @@ local h2 = g2(linda) | |||
43 | 42 | ||
44 | local h3 = g3() | 43 | local h3 = g3() |
45 | 44 | ||
46 | -- wait until they are both started | 45 | lanes.sleep(0.1) |
47 | repeat until h1.status == "running" and h2.status == "waiting" and h3.status == "running" | 46 | |
47 | local is_running = function(lane_h) | ||
48 | local status = lane_h.status | ||
49 | return status == "running" or status == "waiting" | ||
50 | end | ||
51 | |||
52 | -- wait until they are all started | ||
53 | repeat 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 85600ab..d153ffa 100644 --- a/unit_tests/scripts/lane/tasking_cancelling.lua +++ b/unit_tests/scripts/lane/tasking_cancelling.lua | |||
@@ -1,4 +1,7 @@ | |||
1 | local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure(config).configure() | 1 | local require_fixture_result_1, require_fixture_result_2 = require "fixture" |
2 | local fixture = assert(require_fixture_result_1) | ||
3 | |||
4 | local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure{on_state_create = fixture.on_state_create}.configure() | ||
2 | print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2) | 5 | print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2) |
3 | local lanes = require_lanes_result_1 | 6 | local lanes = require_lanes_result_1 |
4 | 7 | ||
@@ -15,69 +18,34 @@ local lanes_linda = assert(lanes.linda) | |||
15 | -- ################################################################################################## | 18 | -- ################################################################################################## |
16 | -- ################################################################################################## | 19 | -- ################################################################################################## |
17 | 20 | ||
18 | local function task(a, b, c) | 21 | -- cancellation of cooperating lanes |
19 | lane_threadname("task("..a..","..b..","..c..")") | 22 | local cooperative = function() |
20 | --error "111" -- testing error messages | 23 | local fixture = assert(require "fixture") |
21 | assert(hey) | 24 | local which_cancel |
22 | local v=0 | 25 | repeat |
23 | for i=a,b,c do | 26 | fixture.block_for(0.2) |
24 | v= v+i | 27 | which_cancel = cancel_test() |
25 | end | 28 | until which_cancel |
26 | return v, hey | 29 | return which_cancel |
27 | end | ||
28 | |||
29 | local gc_cb = function(name_, status_) | ||
30 | PRINT(" ---> lane '" .. name_ .. "' collected with status '" .. status_ .. "'") | ||
31 | end | 30 | end |
31 | -- soft and hard are behaviorally equivalent when no blocking linda operation is involved | ||
32 | local cooperative_lane_soft = lanes_gen("*", { name = 'auto' }, cooperative)() | ||
33 | local a, b = cooperative_lane_soft:cancel("soft", 0) -- issue request, do not wait for lane to terminate | ||
34 | assert(a == false and b == "timeout", "got " .. tostring(a) .. " " .. tostring(b)) | ||
35 | assert(cooperative_lane_soft[1] == "soft") -- return value of the lane body is the value returned by cancel_test() | ||
36 | local cooperative_lane_hard = lanes_gen("*", { name = 'auto' }, cooperative)() | ||
37 | local c, d = cooperative_lane_hard:cancel("hard", 0) -- issue request, do not wait for lane to terminate | ||
38 | assert(a == false and b == "timeout", "got " .. tostring(c) .. " " .. tostring(d)) | ||
39 | assert(cooperative_lane_hard[1] == "hard") -- return value of the lane body is the value returned by cancel_test() | ||
32 | 40 | ||
33 | -- ################################################################################################## | 41 | -- ################################################################################################## |
34 | -- ################################################################################################## | ||
35 | -- ################################################################################################## | ||
36 | |||
37 | PRINT("\n\n", "---=== Tasking (cancelling) ===---", "\n\n") | ||
38 | |||
39 | local task_launch2 = lanes_gen("", { name = 'auto', globals={hey=true}, gc_cb = gc_cb }, task) | ||
40 | |||
41 | local N=999999999 | ||
42 | local lane9= task_launch2(1,N,1) -- huuuuuuge... | ||
43 | |||
44 | -- Wait until state changes "pending"->"running" | ||
45 | -- | ||
46 | local st | ||
47 | local t0= os.time() | ||
48 | while os.time()-t0 < 5 do | ||
49 | st= lane9.status | ||
50 | io.stderr:write((i==1) and st.." " or '.') | ||
51 | if st~="pending" then break end | ||
52 | end | ||
53 | PRINT(" "..st) | ||
54 | |||
55 | if st=="error" then | ||
56 | local _= lane9[0] -- propagate the error here | ||
57 | end | ||
58 | if st=="done" then | ||
59 | error("Looping to "..N.." was not long enough (cannot test cancellation)") | ||
60 | end | ||
61 | assert(st=="running", "st == " .. st) | ||
62 | |||
63 | -- when running under luajit, the function is JIT-ed, and the instruction count isn't hit, so we need a different hook | ||
64 | lane9:cancel(jit and "line" or "count", 100) -- 0 timeout, hook triggers cancelslation when reaching the specified count | ||
65 | |||
66 | local t0= os.time() | ||
67 | while os.time()-t0 < 5 do | ||
68 | st= lane9.status | ||
69 | io.stderr:write((i==1) and st.." " or '.') | ||
70 | if st~="running" then break end | ||
71 | end | ||
72 | PRINT(" "..st) | ||
73 | assert(st == "cancelled", "st is '" .. st .. "' instead of 'cancelled'") | ||
74 | 42 | ||
75 | -- cancellation of lanes waiting on a linda | 43 | -- cancellation of lanes waiting on a linda |
76 | local limited = lanes_linda("limited") | 44 | local limited = lanes_linda{name = "limited"} |
77 | assert.fails(function() limited:limit("key", -1) end) | 45 | assert.fails(function() limited:limit("key", -1) end) |
78 | assert.failsnot(function() limited:limit("key", 1) end) | 46 | assert.failsnot(function() limited:limit("key", 1) end) |
79 | -- [[################################################ | 47 | -- [[################################################ |
80 | limited:send("key", "hello") -- saturate linda | 48 | limited:send("key", "hello") -- saturate linda, so that subsequent sends will block |
81 | for k, v in pairs(limited:dump()) do | 49 | for k, v in pairs(limited:dump()) do |
82 | PRINT("limited[" .. tostring(k) .. "] = " .. tostring(v)) | 50 | PRINT("limited[" .. tostring(k) .. "] = " .. tostring(v)) |
83 | end | 51 | end |
@@ -88,11 +56,15 @@ local wait_send = function() | |||
88 | end | 56 | end |
89 | 57 | ||
90 | local wait_send_lane = lanes_gen("*", { name = 'auto' }, wait_send)() | 58 | local wait_send_lane = lanes_gen("*", { name = 'auto' }, wait_send)() |
91 | repeat until wait_send_lane.status == "waiting" | 59 | repeat |
92 | print "wait_send_lane is waiting" | 60 | io.stderr:write('!') |
61 | -- currently mingw64 builds can deadlock if we cancel the lane too early (before the linda blocks, at it causes the linda condvar not to be signalled) | ||
62 | lanes.sleep(0.1) | ||
63 | until wait_send_lane.status == "waiting" | ||
64 | PRINT "wait_send_lane is waiting" | ||
93 | wait_send_lane:cancel() -- hard cancel, 0 timeout | 65 | wait_send_lane:cancel() -- hard cancel, 0 timeout |
94 | repeat until wait_send_lane.status == "cancelled" | 66 | repeat until wait_send_lane.status == "cancelled" |
95 | print "wait_send_lane is cancelled" | 67 | PRINT "wait_send_lane is cancelled" |
96 | --################################################]] | 68 | --################################################]] |
97 | local wait_receive = function() | 69 | local wait_receive = function() |
98 | local k, v | 70 | local k, v |
@@ -101,22 +73,30 @@ local wait_receive = function() | |||
101 | end | 73 | end |
102 | 74 | ||
103 | local wait_receive_lane = lanes_gen("*", { name = 'auto' }, wait_receive)() | 75 | local wait_receive_lane = lanes_gen("*", { name = 'auto' }, wait_receive)() |
104 | repeat until wait_receive_lane.status == "waiting" | 76 | repeat |
105 | print "wait_receive_lane is waiting" | 77 | io.stderr:write('!') |
78 | -- currently mingw64 builds can deadlock if we cancel the lane too early (before the linda blocks, at it causes the linda condvar not to be signalled) | ||
79 | lanes.sleep(0.1) | ||
80 | until wait_receive_lane.status == "waiting" | ||
81 | PRINT "wait_receive_lane is waiting" | ||
106 | wait_receive_lane:cancel() -- hard cancel, 0 timeout | 82 | wait_receive_lane:cancel() -- hard cancel, 0 timeout |
107 | repeat until wait_receive_lane.status == "cancelled" | 83 | repeat until wait_receive_lane.status == "cancelled" |
108 | print "wait_receive_lane is cancelled" | 84 | PRINT "wait_receive_lane is cancelled" |
109 | --################################################]] | 85 | --################################################]] |
110 | local wait_receive_batched = function() | 86 | local wait_receive_batched = function() |
111 | local k, v1, v2 | 87 | local k, v1, v2 |
112 | set_finalizer(function() print("wait_receive_batched", k, v1, v2) end) | 88 | set_finalizer(function() print("wait_receive_batched", k, v1, v2) end) |
113 | k, v1, v2 = limited:receive(limited.batched, "dummy", 2) -- infinite timeout, returns only when lane is cancelled | 89 | k, v1, v2 = limited:receive_batched("dummy", 2) -- infinite timeout, returns only when lane is cancelled |
114 | end | 90 | end |
115 | 91 | ||
116 | local wait_receive_batched_lane = lanes_gen("*", { name = 'auto' }, wait_receive_batched)() | 92 | local wait_receive_batched_lane = lanes_gen("*", { name = 'auto' }, wait_receive_batched)() |
117 | repeat until wait_receive_batched_lane.status == "waiting" | 93 | repeat |
118 | print "wait_receive_batched_lane is waiting" | 94 | io.stderr:write('!') |
95 | -- currently mingw64 builds can deadlock if we cancel the lane too early (before the linda blocks, at it causes the linda condvar not to be signalled) | ||
96 | lanes.sleep(0.1) | ||
97 | until wait_receive_batched_lane.status == "waiting" | ||
98 | PRINT "wait_receive_batched_lane is waiting" | ||
119 | wait_receive_batched_lane:cancel() -- hard cancel, 0 timeout | 99 | wait_receive_batched_lane:cancel() -- hard cancel, 0 timeout |
120 | repeat until wait_receive_batched_lane.status == "cancelled" | 100 | repeat until wait_receive_batched_lane.status == "cancelled" |
121 | print "wait_receive_batched_lane is cancelled" | 101 | PRINT "wait_receive_batched_lane is cancelled" |
122 | --################################################]] | 102 | --################################################]] |
diff --git a/unit_tests/scripts/lane/tasking_cancelling_with_hook.lua b/unit_tests/scripts/lane/tasking_cancelling_with_hook.lua new file mode 100644 index 0000000..56b934f --- /dev/null +++ b/unit_tests/scripts/lane/tasking_cancelling_with_hook.lua | |||
@@ -0,0 +1,68 @@ | |||
1 | local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure(config).configure() | ||
2 | print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2) | ||
3 | local lanes = require_lanes_result_1 | ||
4 | |||
5 | local require_assert_result_1, require_assert_result_2 = require "_assert" | ||
6 | print("require_assert_result:", require_assert_result_1, require_assert_result_2) | ||
7 | |||
8 | local utils = lanes.require "_utils" | ||
9 | local PRINT = utils.MAKE_PRINT() | ||
10 | |||
11 | -- ################################################################################################## | ||
12 | -- ################################################################################################## | ||
13 | -- ################################################################################################## | ||
14 | |||
15 | local function task(a, b, c) | ||
16 | lane_threadname("task("..a..","..b..","..c..")") | ||
17 | --error "111" -- testing error messages | ||
18 | assert(hey) | ||
19 | local v=0 | ||
20 | for i=a,b,c do | ||
21 | v= v+i | ||
22 | end | ||
23 | return v, hey | ||
24 | end | ||
25 | |||
26 | local gc_cb = function(name_, status_) | ||
27 | PRINT(" ---> lane '" .. name_ .. "' collected with status '" .. status_ .. "'") | ||
28 | end | ||
29 | |||
30 | -- ################################################################################################## | ||
31 | -- ################################################################################################## | ||
32 | -- ################################################################################################## | ||
33 | |||
34 | local generator = lanes.gen("", { name = 'auto', globals={hey=true}, gc_cb = gc_cb }, task) | ||
35 | |||
36 | local N = 999999999 | ||
37 | local lane_h = generator(1,N,1) -- huuuuuuge... | ||
38 | |||
39 | -- Wait until state changes "pending"->"running" | ||
40 | -- | ||
41 | local st | ||
42 | local t0 = os.time() | ||
43 | while os.time()-t0 < 5 do | ||
44 | st = lane_h.status | ||
45 | io.stderr:write((i==1) and st.." " or '.') | ||
46 | if st~="pending" then break end | ||
47 | end | ||
48 | PRINT(" "..st) | ||
49 | |||
50 | if st == "error" then | ||
51 | local _ = lane_h[0] -- propagate the error here | ||
52 | end | ||
53 | if st == "done" then | ||
54 | error("Looping to "..N.." was not long enough (cannot test cancellation)") | ||
55 | end | ||
56 | assert(st == "running", "st == " .. st) | ||
57 | |||
58 | -- when running under luajit, the function is JIT-ed, and the instruction count isn't hit, so we need a different hook | ||
59 | lane_h:cancel(jit and "line" or "count", 100) -- 0 timeout, hook triggers cancelslation when reaching the specified count | ||
60 | |||
61 | local t0 = os.time() | ||
62 | while os.time()-t0 < 5 do | ||
63 | st = lane_h.status | ||
64 | io.stderr:write((i==1) and st.." " or '.') | ||
65 | if st~="running" then break end | ||
66 | end | ||
67 | PRINT(" "..st) | ||
68 | assert(st == "cancelled", "st is '" .. st .. "' instead of 'cancelled'") | ||
diff --git a/unit_tests/scripts/lane/tasking_comms_criss_cross.lua b/unit_tests/scripts/lane/tasking_comms_criss_cross.lua index 497e81d..610da8b 100644 --- a/unit_tests/scripts/lane/tasking_comms_criss_cross.lua +++ b/unit_tests/scripts/lane/tasking_comms_criss_cross.lua | |||
@@ -42,7 +42,7 @@ local tc = lanes_gen("io", { name = 'auto', gc_cb = gc_cb }, | |||
42 | end | 42 | end |
43 | ) | 43 | ) |
44 | 44 | ||
45 | local linda= lanes_linda("criss cross") | 45 | local linda= lanes_linda{name = "criss cross"} |
46 | 46 | ||
47 | local a,b= tc(linda, "A","B"), tc(linda, "B","A") -- launching two lanes, twisted comms | 47 | local a,b= tc(linda, "A","B"), tc(linda, "B","A") -- launching two lanes, twisted comms |
48 | 48 | ||
diff --git a/unit_tests/scripts/lane/tasking_communications.lua b/unit_tests/scripts/lane/tasking_communications.lua index 1fd43b0..01842b4 100644 --- a/unit_tests/scripts/lane/tasking_communications.lua +++ b/unit_tests/scripts/lane/tasking_communications.lua | |||
@@ -72,7 +72,7 @@ local chunk= function(linda) | |||
72 | WR("chunk ", "Lane ends!\n") | 72 | WR("chunk ", "Lane ends!\n") |
73 | end | 73 | end |
74 | 74 | ||
75 | local linda = lanes_linda("communications") | 75 | local linda = lanes_linda{name = "communications"} |
76 | assert(type(linda) == "userdata" and tostring(linda) == "Linda: communications") | 76 | assert(type(linda) == "userdata" and tostring(linda) == "Linda: communications") |
77 | -- | 77 | -- |
78 | -- ["->"] master -> slave | 78 | -- ["->"] master -> slave |
@@ -90,7 +90,7 @@ local b,x,y,z,w = linda:get("<->", 4) | |||
90 | assert(b == 3 and x == "x" and y == "y" and z == "z" and w == nil) | 90 | assert(b == 3 and x == "x" and y == "y" and z == "z" and w == nil) |
91 | local k, x = linda:receive("<->") | 91 | local k, x = linda:receive("<->") |
92 | assert(k == "<->" and x == "x") | 92 | assert(k == "<->" and x == "x") |
93 | local k,y,z = linda:receive(linda.batched, "<->", 2) | 93 | local k,y,z = linda:receive_batched("<->", 2) |
94 | assert(k == "<->" and y == "y" and z == "z") | 94 | assert(k == "<->" and y == "y" and z == "z") |
95 | linda:set("<->") | 95 | linda:set("<->") |
96 | local b,x,y,z,w = linda:get("<->", 4) | 96 | local b,x,y,z,w = linda:get("<->", 4) |
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 | ||
31 | PRINT("---=== :join test ===---", "\n\n") | 31 | PRINT("---=== :join test ===---", "\n\n") |
32 | 32 | ||
33 | -- a lane body that returns nothing is successfully joined with true, nil | ||
34 | local r, ret = lanes_gen(function() end)():join() | ||
35 | assert(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 | ||
37 | local S= lanes_gen("table", { name = 'auto', gc_cb = gc_cb }, | 41 | local 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) |
47 | end) | 52 | end) |
48 | 53 | ||
49 | h= S { 12, 13, 14 } -- execution starts, h[1..3] will get the return values | 54 | local 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 |
51 | SLEEP(0.5) | 56 | SLEEP(0.5) |
52 | print("joining with '" .. h:get_threadname() .. "'") | 57 | print("joining with '" .. h:get_threadname() .. "'") |
53 | local a,b,c,d= h:join() | 58 | local r, a, b, c, d = h:join() |
54 | if h.status == "error" then | 59 | if 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) |
56 | else | 61 | else |
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 e329a88..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") |
66 | end | 65 | end |
67 | 66 | ||
68 | local linda = lanes_linda("auto") | 67 | local linda = lanes_linda{name = "auto"} |
69 | local t2= lanes_gen("debug,package,string,io", { name = 'auto', gc_cb = gc_cb }, chunk2)(linda) -- prepare & launch | 68 | local t2= lanes_gen("debug,package,string,io", { name = 'auto', gc_cb = gc_cb }, chunk2)(linda) -- prepare & launch |
70 | linda:send("down", function(linda) linda:send("up", "ready!") end, | 69 | linda: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 | -- |
74 | local k,s= linda:receive(1, "up") | 72 | local k,s= linda:receive(1, "up") |
75 | if t2.status == "error" then | 73 | if 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) |
78 | end | 76 | end |
79 | PRINT(s) | 77 | PRINT(s) |
80 | assert(s=="ready!", s .. " is not 'ready!'") | 78 | assert(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 |
9 | local lane = function() | 9 | local lane = function() |
10 | local fixture = require "fixture" | 10 | local fixture = require "fixture" |
11 | fixture.sleep_for() | 11 | fixture.block_for() |
12 | end | 12 | end |
13 | 13 | ||
14 | -- the generator | 14 | -- the generator |
diff --git a/unit_tests/scripts/linda/multiple_keepers.lua b/unit_tests/scripts/linda/multiple_keepers.lua index 8733087..267d874 100644 --- a/unit_tests/scripts/linda/multiple_keepers.lua +++ b/unit_tests/scripts/linda/multiple_keepers.lua | |||
@@ -2,9 +2,9 @@ | |||
2 | local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure{nb_user_keepers = 3, keepers_gc_threshold = 500} | 2 | local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure{nb_user_keepers = 3, keepers_gc_threshold = 500} |
3 | local lanes = require_lanes_result_1 | 3 | local lanes = require_lanes_result_1 |
4 | 4 | ||
5 | local a = lanes.linda("A", 1) | 5 | local a = lanes.linda{name = "A", group = 1} |
6 | local b = lanes.linda("B", 2) | 6 | local b = lanes.linda{name = "B", group = 2} |
7 | local c = lanes.linda("C", 3) | 7 | local c = lanes.linda{name = "C", group = 3} |
8 | 8 | ||
9 | -- store each linda in the other 2 | 9 | -- store each linda in the other 2 |
10 | do | 10 | do |
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 @@ | |||
1 | local lanes = require "lanes" | ||
2 | |||
3 | -- a newly created linda doesn't contain anything | ||
4 | local l = lanes.linda() | ||
5 | |||
6 | -- send a function and a string, make sure that's what we read back | ||
7 | l:send("k", function() end, "str") | ||
8 | local c = l:count("k") | ||
9 | assert(c == 2, "got " .. c) | ||
10 | local k, v1, v2 = l:receive_batched("k", 2) | ||
11 | local tv1, tv2 = type(v1), type(v2) | ||
12 | assert(k == "k" and tv1 == "function" and tv2 == "string", "got " .. tv1 .. " " .. tv2) | ||
13 | assert(l:count("k") == 0) | ||
diff --git a/unit_tests/scripts/linda/send_registered_userdata.lua b/unit_tests/scripts/linda/send_registered_userdata.lua index 2c0195a..90c05c9 100644 --- a/unit_tests/scripts/linda/send_registered_userdata.lua +++ b/unit_tests/scripts/linda/send_registered_userdata.lua | |||
@@ -1,5 +1,5 @@ | |||
1 | local lanes = require 'lanes'.configure{with_timers = false} | 1 | local lanes = require 'lanes'.configure{with_timers = false} |
2 | local l = lanes.linda'gleh' | 2 | local l = lanes.linda{name = 'gleh'} |
3 | l:set('yo', io.stdin) | 3 | l:set('yo', io.stdin) |
4 | local n, stdin_out = l:get('yo') | 4 | local n, stdin_out = l:get('yo') |
5 | assert(n == 1 and stdin_out == io.stdin, tostring(stdin_out) .. " ~= " .. tostring(io.stdin)) | 5 | assert(n == 1 and stdin_out == io.stdin, tostring(stdin_out) .. " ~= " .. tostring(io.stdin)) |
diff --git a/unit_tests/scripts/linda/wake_period.lua b/unit_tests/scripts/linda/wake_period.lua new file mode 100644 index 0000000..d2dccc3 --- /dev/null +++ b/unit_tests/scripts/linda/wake_period.lua | |||
@@ -0,0 +1,42 @@ | |||
1 | -- default wake period is 0.5 seconds | ||
2 | local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure{linda_wake_period = 0.5} | ||
3 | local lanes = require_lanes_result_1 | ||
4 | |||
5 | -- a lane that performs a blocking operation for 2 seconds | ||
6 | local body = function(linda_) | ||
7 | -- a blocking read that lasts longer than the tested wake_period values | ||
8 | linda_:receive(2, "empty_slot") | ||
9 | return "done" | ||
10 | end | ||
11 | |||
12 | -- if we don't cancel the lane, we should wait the whole duration | ||
13 | local function check_wake_duration(linda_, expected_, do_cancel_) | ||
14 | local h = lanes.gen(body)(linda_) | ||
15 | -- wait until the linda is blocked | ||
16 | repeat until h.status == "waiting" | ||
17 | local t0 = lanes.now_secs() | ||
18 | -- soft cancel, no timeout, no waking | ||
19 | if do_cancel_ then | ||
20 | local result, reason = h:cancel('soft', 0, false) | ||
21 | -- should say there was a timeout, since the lane didn't actually cancel (normal since we did not wake it) | ||
22 | assert(result == false and reason == 'timeout', "unexpected cancel result") | ||
23 | end | ||
24 | -- this should wait until the linda wakes by itself before the actual receive timeout and sees the cancel request | ||
25 | local r, ret = h:join() | ||
26 | assert(r == true and ret == "done") | ||
27 | local t1 = lanes.now_secs() | ||
28 | local delta = t1 - t0 | ||
29 | -- the linda should check for cancellation at about the expected period, not earlier | ||
30 | assert(delta >= expected_, tostring(linda_) .. " woke too early:" .. delta) | ||
31 | -- the lane shouldn't terminate too long after cancellation was processed | ||
32 | assert(delta <= expected_ * 1.1, tostring(linda_) .. " woke too late: " .. delta) | ||
33 | end | ||
34 | |||
35 | -- legacy behavior: linda waits until operation timeout | ||
36 | check_wake_duration(lanes.linda{name = "A", wake_period = 'never'}, 2, true) | ||
37 | -- early wake behavior: linda wakes after the expected time, sees a cancellation requests, and aborts the operation early | ||
38 | check_wake_duration(lanes.linda{name = "B", wake_period = 0.25}, 0.25, true) | ||
39 | check_wake_duration(lanes.linda{name = "C"}, 0.5, true) -- wake_period defaults to 0.5 (see above) | ||
40 | check_wake_duration(lanes.linda{name = "D", wake_period = 1}, 1, true) | ||
41 | -- even when there is a wake_period, the operation should reach full timeout if not cancelled early | ||
42 | check_wake_duration(lanes.linda{name = "E", wake_period = 0.1}, 2, false) | ||
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 @@ | |||
1 | local fixture = require "fixture" | ||
2 | local lanes = require("lanes").configure{on_state_create = fixture.on_state_create} | ||
3 | local l = lanes.linda{name = "my linda"} | ||
4 | |||
5 | local 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 | ||
8 | local 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 | ||
11 | DEEP = DEEP or true | ||
12 | -- set CLONABLE to any non-false value to run the Clonable Userdata tests | ||
13 | CLONABLE = 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 | ||
17 | local test_uvtype = (_VERSION == "Lua 5.4") and "function" or (_VERSION == "Lua 5.3") and "string" or "table" | ||
18 | -- lua 5.4 supports multiple uservalues | ||
19 | local nupvals = _VERSION == "Lua 5.4" and 3 or 1 | ||
20 | |||
21 | local 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 | ||
33 | end | ||
34 | |||
35 | local 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() | ||
51 | end | ||
52 | |||
53 | local 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]) | ||
105 | end | ||
106 | |||
107 | if 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 | ||
152 | end | ||
153 | |||
154 | if CLONABLE then | ||
155 | print "================================================================" | ||
156 | print "CLONABLE" | ||
157 | performTest( dt.new_clonable(nupvals)) | ||
158 | end | ||
159 | |||
160 | print "================================================================" | ||
161 | print "TEST OK" \ No newline at end of file | ||
diff --git a/unit_tests/shared.cpp b/unit_tests/shared.cpp index 2e2af73..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 | } |
@@ -476,6 +476,7 @@ void FileRunner::performTest(FileRunnerParam const& testParam_) | |||
476 | INFO(testParam_.script); | 476 | INFO(testParam_.script); |
477 | switch (testParam_.test) { | 477 | switch (testParam_.test) { |
478 | case TestType::AssertNoLuaError: | 478 | case TestType::AssertNoLuaError: |
479 | lua_atpanic(L, _atPanic); | ||
479 | requireSuccess(root, testParam_.script); | 480 | requireSuccess(root, testParam_.script); |
480 | break; | 481 | break; |
481 | 482 | ||
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 | }; |