aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2019-04-22 17:17:03 +0200
committerBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2019-04-22 17:17:03 +0200
commit32f8cdfc73ed90dcf88ffcf4bfc1a3e4d5a69e6c (patch)
tree9f348cc5cf26f37b8801aaccd0e1d2647e4a3675 /src
parentb735db9ef342973deb628129fc04f0d295616164 (diff)
downloadlanes-32f8cdfc73ed90dcf88ffcf4bfc1a3e4d5a69e6c.tar.gz
lanes-32f8cdfc73ed90dcf88ffcf4bfc1a3e4d5a69e6c.tar.bz2
lanes-32f8cdfc73ed90dcf88ffcf4bfc1a3e4d5a69e6c.zip
Moved cancellation code in separate files
Diffstat (limited to 'src')
-rw-r--r--src/cancel.c252
-rw-r--r--src/cancel.h57
-rw-r--r--src/lanes.c203
-rw-r--r--src/lanes_private.h24
-rw-r--r--src/macros_and_utils.h2
-rw-r--r--src/tools.c4
-rw-r--r--src/tools.h2
7 files changed, 316 insertions, 228 deletions
diff --git a/src/cancel.c b/src/cancel.c
new file mode 100644
index 0000000..11e100d
--- /dev/null
+++ b/src/cancel.c
@@ -0,0 +1,252 @@
1/*
2--
3-- CANCEL.C
4--
5-- Lane cancellation support
6--
7-- Author: Benoit Germain <bnt.germain@gmail.com>
8--
9--[[
10===============================================================================
11
12Copyright (C) 2011-2019 Benoit Germain <bnt.germain@gmail.com>
13
14Permission is hereby granted, free of charge, to any person obtaining a copy
15of this software and associated documentation files (the "Software"), to deal
16in the Software without restriction, including without limitation the rights
17to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18copies of the Software, and to permit persons to whom the Software is
19furnished to do so, subject to the following conditions:
20
21The above copyright notice and this permission notice shall be included in
22all copies or substantial portions of the Software.
23
24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30THE SOFTWARE.
31
32===============================================================================
33]]--
34*/
35
36#include <assert.h>
37
38#include "threading.h"
39#include "cancel.h"
40#include "tools.h"
41#include "lanes_private.h"
42
43// ################################################################################################
44// ################################################################################################
45
46/*
47* Check if the thread in question ('L') has been signalled for cancel.
48*
49* Called by cancellation hooks and/or pending Linda operations (because then
50* the check won't affect performance).
51*
52* Returns TRUE if any locks are to be exited, and 'cancel_error()' called,
53* to make execution of the lane end.
54*/
55static inline enum e_cancel_request cancel_test( lua_State* L)
56{
57 Lane* const s = get_lane_from_registry( L);
58 // 's' is NULL for the original main state (and no-one can cancel that)
59 return s ? s->cancel_request : CANCEL_NONE;
60}
61
62// ################################################################################################
63
64//---
65// bool = cancel_test()
66//
67// Available inside the global namespace of lanes
68// returns a boolean saying if a cancel request is pending
69//
70LUAG_FUNC( cancel_test)
71{
72 enum e_cancel_request test = cancel_test( L);
73 lua_pushboolean( L, test != CANCEL_NONE);
74 return 1;
75}
76
77// ################################################################################################
78// ################################################################################################
79
80void cancel_hook( lua_State* L, lua_Debug* ar)
81{
82 (void)ar;
83 DEBUGSPEW_CODE( fprintf( stderr, "cancel_hook\n"));
84 if( cancel_test( L) != CANCEL_NONE)
85 {
86 cancel_error( L);
87 }
88}
89
90// ################################################################################################
91// ################################################################################################
92
93//---
94// = thread_cancel( lane_ud [,timeout_secs=0.0] [,force_kill_bool=false] )
95//
96// The originator thread asking us specifically to cancel the other thread.
97//
98// 'timeout': <0: wait forever, until the lane is finished
99// 0.0: just signal it to cancel, no time waited
100// >0: time to wait for the lane to detect cancellation
101//
102// 'force_kill': if true, and lane does not detect cancellation within timeout,
103// it is forcefully killed. Using this with 0.0 timeout means just kill
104// (unless the lane is already finished).
105//
106// Returns: true if the lane was already finished (DONE/ERROR_ST/CANCELLED) or if we
107// managed to cancel it.
108// false if the cancellation timed out, or a kill was needed.
109//
110
111// ################################################################################################
112
113static cancel_result thread_cancel_soft( Lane* s, bool_t wake_lindas_)
114{
115 s->cancel_request = CANCEL_SOFT; // it's now signaled to stop
116 // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own
117 if( wake_lindas_) // wake the thread so that execution returns from any pending linda operation if desired
118 {
119 SIGNAL_T *waiting_on = s->waiting_on;
120 if( s->status == WAITING && waiting_on != NULL)
121 {
122 SIGNAL_ALL( waiting_on);
123 }
124 }
125 // say we succeeded though
126 return CR_Cancelled;
127}
128
129// ################################################################################################
130
131static cancel_result thread_cancel_hard( lua_State* L, Lane* s, double secs_, bool_t force_, double waitkill_timeout_)
132{
133 cancel_result result;
134
135 s->cancel_request = CANCEL_HARD; // it's now signaled to stop
136 {
137 SIGNAL_T *waiting_on = s->waiting_on;
138 if( s->status == WAITING && waiting_on != NULL)
139 {
140 SIGNAL_ALL( waiting_on);
141 }
142 }
143
144 result = THREAD_WAIT( &s->thread, secs_, &s->done_signal, &s->done_lock, &s->status) ? CR_Cancelled : CR_Timeout;
145
146 if( (result == CR_Timeout) && force_)
147 {
148 // Killing is asynchronous; we _will_ wait for it to be done at
149 // GC, to make sure the data structure can be released (alternative
150 // would be use of "cancellation cleanup handlers" that at least
151 // PThread seems to have).
152 //
153 THREAD_KILL( &s->thread);
154#if THREADAPI == THREADAPI_PTHREAD
155 // pthread: make sure the thread is really stopped!
156 // note that this may block forever if the lane doesn't call a cancellation point and pthread doesn't honor PTHREAD_CANCEL_ASYNCHRONOUS
157 result = THREAD_WAIT( &s->thread, waitkill_timeout_, &s->done_signal, &s->done_lock, &s->status);
158 if( result == CR_Timeout)
159 {
160 return luaL_error( L, "force-killed lane failed to terminate within %f second%s", waitkill_timeout_, waitkill_timeout_ > 1 ? "s" : "");
161 }
162#else
163 (void) waitkill_timeout_; // unused
164 (void) L; // unused
165#endif // THREADAPI == THREADAPI_PTHREAD
166 s->mstatus = KILLED; // mark 'gc' to wait for it
167 // note that s->status value must remain to whatever it was at the time of the kill
168 // because we need to know if we can lua_close() the Lua State or not.
169 result = CR_Killed;
170 }
171 return result;
172}
173
174// ################################################################################################
175
176cancel_result thread_cancel( lua_State* L, Lane* s, double secs_, bool_t force_, double waitkill_timeout_)
177{
178 // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here
179 // We can read 's->status' without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN)
180 if( s->mstatus == KILLED)
181 {
182 return CR_Killed;
183 }
184
185 if( s->status >= DONE)
186 {
187 // say "ok" by default, including when lane is already done
188 return CR_Cancelled;
189 }
190
191 // signal the linda the wake up the thread so that it can react to the cancel query
192 // let us hope we never land here with a pointer on a linda that has been destroyed...
193 if( secs_ < 0.0)
194 {
195 return thread_cancel_soft( s, force_);
196 }
197
198 return thread_cancel_hard( L, s, secs_, force_, waitkill_timeout_);
199}
200
201// ################################################################################################
202// ################################################################################################
203
204// lane_h:cancel( [timeout] [, force [, forcekill_timeout]])
205LUAG_FUNC( thread_cancel)
206{
207 Lane* s = lua_toLane( L, 1);
208 double secs = 0.0;
209 int force_i = 2;
210 int forcekill_timeout_i = 3;
211
212 if( lua_isnumber( L, 2))
213 {
214 secs = lua_tonumber( L, 2);
215 if( secs < 0.0 && lua_gettop( L) > 3)
216 {
217 return luaL_error( L, "can't force_kill a soft cancel");
218 }
219 // negative timeout and force flag means we want to wake linda-waiting threads
220 ++ force_i;
221 ++ forcekill_timeout_i;
222 }
223 else if( lua_isnil( L, 2))
224 {
225 ++ force_i;
226 ++ forcekill_timeout_i;
227 }
228
229 {
230 bool_t force = lua_toboolean( L, force_i); // FALSE if nothing there
231 double forcekill_timeout = luaL_optnumber( L, forcekill_timeout_i, 0.0);
232
233 switch( thread_cancel( L, s, secs, force, forcekill_timeout))
234 {
235 case CR_Timeout:
236 lua_pushboolean( L, 0);
237 lua_pushstring( L, "timeout");
238 return 2;
239
240 case CR_Cancelled:
241 lua_pushboolean( L, 1);
242 return 1;
243
244 case CR_Killed:
245 lua_pushboolean( L, 0);
246 lua_pushstring( L, "killed");
247 return 2;
248 }
249 }
250 // should never happen, only here to prevent the compiler from complaining of "not all control paths returning a value"
251 return 0;
252}
diff --git a/src/cancel.h b/src/cancel.h
new file mode 100644
index 0000000..3112809
--- /dev/null
+++ b/src/cancel.h
@@ -0,0 +1,57 @@
1#if !defined( __LANES_CANCEL_H__)
2#define __LANES_CANCEL_H__ 1
3
4#include "lua.h"
5#include "lualib.h"
6#include "lauxlib.h"
7
8#include "uniquekey.h"
9#include "macros_and_utils.h"
10
11// ################################################################################################
12
13typedef struct s_Lane Lane; // forward
14
15/*
16 * Lane cancellation request modes
17 */
18enum e_cancel_request
19{
20 CANCEL_NONE, // no pending cancel request
21 CANCEL_SOFT, // user wants the lane to cancel itself manually on cancel_test()
22 CANCEL_HARD // user wants the lane to be interrupted (meaning code won't return from those functions) from inside linda:send/receive calls
23};
24
25typedef enum
26{
27 CR_Timeout,
28 CR_Cancelled,
29 CR_Killed
30} cancel_result;
31
32// crc64/we of string "CANCEL_ERROR" generated at http://www.nitrxgen.net/hashgen/
33static DECLARE_CONST_UNIQUE_KEY(CANCEL_ERROR, 0xe97d41626cc97577); // 'cancel_error' sentinel
34
35// crc64/we of string "CANCEL_TEST_KEY" generated at http://www.nitrxgen.net/hashgen/
36static DECLARE_CONST_UNIQUE_KEY(CANCEL_TEST_KEY, 0xe66f5960c57d133a); // used as registry key
37
38void cancel_hook( lua_State* L, lua_Debug* ar);
39
40cancel_result thread_cancel( lua_State* L, Lane* s, double secs_, bool_t force_, double waitkill_timeout_);
41
42static inline int cancel_error( lua_State* L)
43{
44 STACK_GROW( L, 1);
45 push_unique_key( L, CANCEL_ERROR); // special error value
46 return lua_error( L); // doesn't return
47}
48
49// ################################################################################################
50// ################################################################################################
51
52LUAG_FUNC( cancel_test);
53LUAG_FUNC( thread_cancel);
54
55// ################################################################################################
56
57#endif // __LANES_CANCEL_H__
diff --git a/src/lanes.c b/src/lanes.c
index 8762766..cbac6da 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * LANES.C Copyright (c) 2007-08, Asko Kauppi 2 * LANES.C Copyright (c) 2007-08, Asko Kauppi
3 * Copyright (C) 2009-17, Benoit Germain 3 * Copyright (C) 2009-19, Benoit Germain
4 * 4 *
5 * Multithreading in Lua. 5 * Multithreading in Lua.
6 * 6 *
@@ -56,7 +56,7 @@
56=============================================================================== 56===============================================================================
57 57
58Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com> 58Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com>
59 2011-17 Benoit Germain <bnt.germain@gmail.com> 59 2011-19 Benoit Germain <bnt.germain@gmail.com>
60 60
61Permission is hereby granted, free of charge, to any person obtaining a copy 61Permission is hereby granted, free of charge, to any person obtaining a copy
62of this software and associated documentation files (the "Software"), to deal 62of this software and associated documentation files (the "Software"), to deal
@@ -124,33 +124,6 @@ static void securize_debug_threadname( lua_State* L, Lane* s)
124 STACK_END( L, 0); 124 STACK_END( L, 0);
125} 125}
126 126
127/*
128* Check if the thread in question ('L') has been signalled for cancel.
129*
130* Called by cancellation hooks and/or pending Linda operations (because then
131* the check won't affect performance).
132*
133* Returns TRUE if any locks are to be exited, and 'cancel_error()' called,
134* to make execution of the lane end.
135*/
136static inline enum e_cancel_request cancel_test( lua_State* L)
137{
138 Lane* const s = get_lane_from_registry( L);
139 // 's' is NULL for the original main state (and no-one can cancel that)
140 return s ? s->cancel_request : CANCEL_NONE;
141}
142
143static void cancel_hook( lua_State* L, lua_Debug* ar)
144{
145 (void)ar;
146 DEBUGSPEW_CODE( fprintf( stderr, "cancel_hook\n"));
147 if( cancel_test( L) != CANCEL_NONE)
148 {
149 cancel_error( L);
150 }
151}
152
153
154#if ERROR_FULL_STACK 127#if ERROR_FULL_STACK
155static int lane_error( lua_State* L); 128static int lane_error( lua_State* L);
156// crc64/we of string "STACKTRACE_REGKEY" generated at http://www.nitrxgen.net/hashgen/ 129// crc64/we of string "STACKTRACE_REGKEY" generated at http://www.nitrxgen.net/hashgen/
@@ -404,115 +377,6 @@ static int run_finalizers( lua_State* L, int lua_rc)
404 * ############################################################################################### 377 * ###############################################################################################
405 */ 378 */
406 379
407//---
408// = thread_cancel( lane_ud [,timeout_secs=0.0] [,force_kill_bool=false] )
409//
410// The originator thread asking us specifically to cancel the other thread.
411//
412// 'timeout': <0: wait forever, until the lane is finished
413// 0.0: just signal it to cancel, no time waited
414// >0: time to wait for the lane to detect cancellation
415//
416// 'force_kill': if true, and lane does not detect cancellation within timeout,
417// it is forcefully killed. Using this with 0.0 timeout means just kill
418// (unless the lane is already finished).
419//
420// Returns: true if the lane was already finished (DONE/ERROR_ST/CANCELLED) or if we
421// managed to cancel it.
422// false if the cancellation timed out, or a kill was needed.
423//
424
425typedef enum
426{
427 CR_Timeout,
428 CR_Cancelled,
429 CR_Killed
430} cancel_result;
431
432static cancel_result thread_cancel_soft( lua_State* L, Lane* s, bool_t wake_lindas_)
433{
434 s->cancel_request = CANCEL_SOFT; // it's now signaled to stop
435 // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own
436 if( wake_lindas_) // wake the thread so that execution returns from any pending linda operation if desired
437 {
438 SIGNAL_T *waiting_on = s->waiting_on;
439 if( s->status == WAITING && waiting_on != NULL)
440 {
441 SIGNAL_ALL( waiting_on);
442 }
443 }
444 // say we succeeded though
445 return CR_Cancelled;
446}
447
448static cancel_result thread_cancel_hard( lua_State* L, Lane* s, double secs_, bool_t force_, double waitkill_timeout_)
449{
450 cancel_result result;
451
452 s->cancel_request = CANCEL_HARD; // it's now signaled to stop
453 {
454 SIGNAL_T *waiting_on = s->waiting_on;
455 if( s->status == WAITING && waiting_on != NULL)
456 {
457 SIGNAL_ALL( waiting_on);
458 }
459 }
460
461 result = THREAD_WAIT( &s->thread, secs_, &s->done_signal, &s->done_lock, &s->status) ? CR_Cancelled : CR_Timeout;
462
463 if( (result == CR_Timeout) && force_)
464 {
465 // Killing is asynchronous; we _will_ wait for it to be done at
466 // GC, to make sure the data structure can be released (alternative
467 // would be use of "cancellation cleanup handlers" that at least
468 // PThread seems to have).
469 //
470 THREAD_KILL( &s->thread);
471#if THREADAPI == THREADAPI_PTHREAD
472 // pthread: make sure the thread is really stopped!
473 // note that this may block forever if the lane doesn't call a cancellation point and pthread doesn't honor PTHREAD_CANCEL_ASYNCHRONOUS
474 result = THREAD_WAIT( &s->thread, waitkill_timeout_, &s->done_signal, &s->done_lock, &s->status);
475 if( result == CR_Timeout)
476 {
477 return luaL_error( L, "force-killed lane failed to terminate within %f second%s", waitkill_timeout_, waitkill_timeout_ > 1 ? "s" : "");
478 }
479#else
480 (void) waitkill_timeout_; // unused
481 (void) L; // unused
482#endif // THREADAPI == THREADAPI_PTHREAD
483 s->mstatus = KILLED; // mark 'gc' to wait for it
484 // note that s->status value must remain to whatever it was at the time of the kill
485 // because we need to know if we can lua_close() the Lua State or not.
486 result = CR_Killed;
487 }
488 return result;
489}
490
491static cancel_result thread_cancel( lua_State* L, Lane* s, double secs_, bool_t force_, double waitkill_timeout_)
492{
493 // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here
494 // We can read 's->status' without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN)
495 if( s->mstatus == KILLED)
496 {
497 return CR_Killed;
498 }
499
500 if( s->status >= DONE)
501 {
502 // say "ok" by default, including when lane is already done
503 return CR_Cancelled;
504 }
505
506 // signal the linda the wake up the thread so that it can react to the cancel query
507 // let us hope we never land here with a pointer on a linda that has been destroyed...
508 if( secs_ < 0.0)
509 {
510 return thread_cancel_soft( L, s, force_);
511 }
512
513 return thread_cancel_hard( L, s, secs_, force_, waitkill_timeout_);
514}
515
516// 380//
517// Protects modifying the selfdestruct chain 381// Protects modifying the selfdestruct chain
518 382
@@ -734,19 +598,6 @@ static int selfdestruct_gc( lua_State* L)
734 598
735 599
736//--- 600//---
737// bool = cancel_test()
738//
739// Available inside the global namespace of lanes
740// returns a boolean saying if a cancel request is pending
741//
742LUAG_FUNC( cancel_test)
743{
744 enum e_cancel_request test = cancel_test( L);
745 lua_pushboolean( L, test != CANCEL_NONE);
746 return 1;
747}
748
749//---
750// = _single( [cores_uint=1] ) 601// = _single( [cores_uint=1] )
751// 602//
752// Limits the process to use only 'cores' CPU cores. To be used for performance 603// Limits the process to use only 'cores' CPU cores. To be used for performance
@@ -1527,56 +1378,6 @@ LUAG_FUNC( thread_gc)
1527 return 0; 1378 return 0;
1528} 1379}
1529 1380
1530// lane_h:cancel( [timeout] [, force [, forcekill_timeout]])
1531LUAG_FUNC( thread_cancel)
1532{
1533 Lane* s = lua_toLane( L, 1);
1534 double secs = 0.0;
1535 int force_i = 2;
1536 int forcekill_timeout_i = 3;
1537
1538 if( lua_isnumber( L, 2))
1539 {
1540 secs = lua_tonumber( L, 2);
1541 if( secs < 0.0 && lua_gettop( L) > 3)
1542 {
1543 return luaL_error( L, "can't force_kill a soft cancel");
1544 }
1545 // negative timeout and force flag means we want to wake linda-waiting threads
1546 ++ force_i;
1547 ++ forcekill_timeout_i;
1548 }
1549 else if( lua_isnil( L, 2))
1550 {
1551 ++ force_i;
1552 ++ forcekill_timeout_i;
1553 }
1554
1555 {
1556 bool_t force = lua_toboolean( L, force_i); // FALSE if nothing there
1557 double forcekill_timeout = luaL_optnumber( L, forcekill_timeout_i, 0.0);
1558
1559 switch( thread_cancel( L, s, secs, force, forcekill_timeout))
1560 {
1561 case CR_Timeout:
1562 lua_pushboolean( L, 0);
1563 lua_pushstring( L, "timeout");
1564 return 2;
1565
1566 case CR_Cancelled:
1567 lua_pushboolean( L, 1);
1568 return 1;
1569
1570 case CR_Killed:
1571 lua_pushboolean( L, 0);
1572 lua_pushstring( L, "killed");
1573 return 2;
1574 }
1575 }
1576 // should never happen, only here to prevent the compiler from complaining of "not all control paths returning a value"
1577 return 0;
1578}
1579
1580//--- 1381//---
1581// str= thread_status( lane ) 1382// str= thread_status( lane )
1582// 1383//
diff --git a/src/lanes_private.h b/src/lanes_private.h
index 16c178d..ac05129 100644
--- a/src/lanes_private.h
+++ b/src/lanes_private.h
@@ -2,16 +2,7 @@
2#define __lanes_private_h__ 1 2#define __lanes_private_h__ 1
3 3
4#include "uniquekey.h" 4#include "uniquekey.h"
5 5#include "cancel.h"
6/*
7 * Lane cancellation request modes
8 */
9enum e_cancel_request
10{
11 CANCEL_NONE, // no pending cancel request
12 CANCEL_SOFT, // user wants the lane to cancel itself manually on cancel_test()
13 CANCEL_HARD // user wants the lane to be interrupted (meaning code won't return from those functions) from inside linda:send/receive calls
14};
15 6
16// NOTE: values to be changed by either thread, during execution, without 7// NOTE: values to be changed by either thread, during execution, without
17// locking, are marked "volatile" 8// locking, are marked "volatile"
@@ -86,12 +77,6 @@ typedef struct s_Lane Lane;
86// 77//
87#define lua_toLane( L, i) (*((Lane**) luaL_checkudata( L, i, "Lane"))) 78#define lua_toLane( L, i) (*((Lane**) luaL_checkudata( L, i, "Lane")))
88 79
89// crc64/we of string "CANCEL_ERROR" generated at http://www.nitrxgen.net/hashgen/
90static DECLARE_CONST_UNIQUE_KEY(CANCEL_ERROR, 0xe97d41626cc97577); // 'cancel_error' sentinel
91
92// crc64/we of string "CANCEL_TEST_KEY" generated at http://www.nitrxgen.net/hashgen/
93static DECLARE_CONST_UNIQUE_KEY(CANCEL_TEST_KEY, 0xe66f5960c57d133a); // used as registry key
94
95static inline Lane* get_lane_from_registry( lua_State* L) 80static inline Lane* get_lane_from_registry( lua_State* L)
96{ 81{
97 Lane* s; 82 Lane* s;
@@ -104,11 +89,4 @@ static inline Lane* get_lane_from_registry( lua_State* L)
104 return s; 89 return s;
105} 90}
106 91
107static inline int cancel_error( lua_State* L)
108{
109 STACK_GROW( L, 1);
110 push_unique_key( L, CANCEL_ERROR); // special error value
111 return lua_error( L); // doesn't return
112}
113
114#endif // __lanes_private_h__ \ No newline at end of file 92#endif // __lanes_private_h__ \ No newline at end of file
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h
index 4b0b9d3..ae3a6c9 100644
--- a/src/macros_and_utils.h
+++ b/src/macros_and_utils.h
@@ -97,4 +97,6 @@ extern char const* debugspew_indent;
97 lua_rawget( L, LUA_REGISTRYINDEX); \ 97 lua_rawget( L, LUA_REGISTRYINDEX); \
98} 98}
99 99
100#define LUAG_FUNC( func_name) int LG_##func_name( lua_State* L)
101
100#endif // MACROS_AND_UTILS_H 102#endif // MACROS_AND_UTILS_H
diff --git a/src/tools.c b/src/tools.c
index 48e904c..02d51ae 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -1736,7 +1736,7 @@ static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache
1736 } 1736 }
1737} 1737}
1738 1738
1739bool_t copyclone( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_) 1739static bool_t copyclone( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
1740{ 1740{
1741 STACK_CHECK( L, 0); 1741 STACK_CHECK( L, 0);
1742 STACK_CHECK( L2, 0); 1742 STACK_CHECK( L2, 0);
@@ -1849,7 +1849,7 @@ static bool_t inter_copy_userdata( Universe* U, lua_State* L2, uint_t L2_cache_i
1849 STACK_MID( L, 0); 1849 STACK_MID( L, 0);
1850 STACK_MID( L2, 0); 1850 STACK_MID( L2, 0);
1851 1851
1852 if( copyclone( U, L2, L2_cache_i, L, i, vt, mode_, upName_)) 1852 if( copyclone( U, L2, L2_cache_i, L, i, mode_, upName_))
1853 { 1853 {
1854 STACK_MID( L, 0); 1854 STACK_MID( L, 0);
1855 STACK_MID( L2, 1); 1855 STACK_MID( L2, 1);
diff --git a/src/tools.h b/src/tools.h
index 71460c3..8a8ad7b 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -13,8 +13,6 @@ typedef struct s_Universe Universe;
13 13
14// ################################################################################################ 14// ################################################################################################
15 15
16#define LUAG_FUNC( func_name) int LG_##func_name( lua_State* L)
17
18#define luaG_optunsigned(L,i,d) ((uint_t) luaL_optinteger(L,i,d)) 16#define luaG_optunsigned(L,i,d) ((uint_t) luaL_optinteger(L,i,d))
19#define luaG_tounsigned(L,i) ((uint_t) lua_tointeger(L,i)) 17#define luaG_tounsigned(L,i) ((uint_t) lua_tointeger(L,i))
20 18