aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-04-08 18:26:47 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-04-08 18:26:47 +0200
commit6efef88d0c7c155690dc2ac478d52e75da97d147 (patch)
tree9706bac4d419f0f242f69d283412f912e0b2b6fb
parent96daea993eeea17f0c64325491943e48795ff751 (diff)
downloadlanes-6efef88d0c7c155690dc2ac478d52e75da97d147.tar.gz
lanes-6efef88d0c7c155690dc2ac478d52e75da97d147.tar.bz2
lanes-6efef88d0c7c155690dc2ac478d52e75da97d147.zip
C++ migration: lanes.now_secs uses std::chrono::sytem_clock. plus more enum class cleanup.
Diffstat (limited to '')
-rw-r--r--src/cancel.cpp17
-rw-r--r--src/lanes.cpp74
-rw-r--r--src/lanes_private.h26
-rw-r--r--src/linda.cpp20
-rw-r--r--src/threading.cpp78
-rw-r--r--src/threading.h15
6 files changed, 77 insertions, 153 deletions
diff --git a/src/cancel.cpp b/src/cancel.cpp
index 6a94343..437a6f0 100644
--- a/src/cancel.cpp
+++ b/src/cancel.cpp
@@ -33,13 +33,14 @@ THE SOFTWARE.
33]]-- 33]]--
34*/ 34*/
35 35
36#include <assert.h> 36#include "cancel.h"
37#include <string.h> 37
38// #include <assert.h>
39//#include <string.h>
38 40
41#include "lanes_private.h"
39#include "threading.h" 42#include "threading.h"
40#include "cancel.h"
41#include "tools.h" 43#include "tools.h"
42#include "lanes_private.h"
43 44
44// ################################################################################################ 45// ################################################################################################
45// ################################################################################################ 46// ################################################################################################
@@ -103,7 +104,7 @@ static void cancel_hook(lua_State* L, [[maybe_unused]] lua_Debug* ar)
103// 'wake_lindas_bool': if true, signal any linda the thread is waiting on 104// 'wake_lindas_bool': if true, signal any linda the thread is waiting on
104// instead of waiting for its timeout (if any) 105// instead of waiting for its timeout (if any)
105// 106//
106// Returns: true if the lane was already finished (DONE/ERROR_ST/CANCELLED) or if we 107// Returns: true if the lane was already finished (Done/Error/Cancelled) or if we
107// managed to cancel it. 108// managed to cancel it.
108// false if the cancellation timed out, or a kill was needed. 109// false if the cancellation timed out, or a kill was needed.
109// 110//
@@ -117,7 +118,7 @@ static CancelResult thread_cancel_soft(Lane* lane_, lua_Duration duration_, bool
117 if (wake_lane_) // wake the thread so that execution returns from any pending linda operation if desired 118 if (wake_lane_) // wake the thread so that execution returns from any pending linda operation if desired
118 { 119 {
119 std::condition_variable* const waiting_on{ lane_->m_waiting_on }; 120 std::condition_variable* const waiting_on{ lane_->m_waiting_on };
120 if (lane_->status == WAITING && waiting_on != nullptr) 121 if (lane_->m_status == Lane::Waiting && waiting_on != nullptr)
121 { 122 {
122 waiting_on->notify_all(); 123 waiting_on->notify_all();
123 } 124 }
@@ -135,7 +136,7 @@ static CancelResult thread_cancel_hard(Lane* lane_, lua_Duration duration_, bool
135 if (wake_lane_) // wake the thread so that execution returns from any pending linda operation if desired 136 if (wake_lane_) // wake the thread so that execution returns from any pending linda operation if desired
136 { 137 {
137 std::condition_variable* waiting_on = lane_->m_waiting_on; 138 std::condition_variable* waiting_on = lane_->m_waiting_on;
138 if (lane_->status == WAITING && waiting_on != nullptr) 139 if (lane_->m_status == Lane::Waiting && waiting_on != nullptr)
139 { 140 {
140 waiting_on->notify_all(); 141 waiting_on->notify_all();
141 } 142 }
@@ -151,7 +152,7 @@ CancelResult thread_cancel(Lane* lane_, CancelOp op_, int hook_count_, lua_Durat
151{ 152{
152 // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here 153 // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here
153 // We can read 'lane_->status' without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN) 154 // We can read 'lane_->status' without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN)
154 if (lane_->status >= DONE) 155 if (lane_->m_status >= Lane::Done)
155 { 156 {
156 // say "ok" by default, including when lane is already done 157 // say "ok" by default, including when lane is already done
157 return CancelResult::Cancelled; 158 return CancelResult::Cancelled;
diff --git a/src/lanes.cpp b/src/lanes.cpp
index 4dd9b46..12cd7ef 100644
--- a/src/lanes.cpp
+++ b/src/lanes.cpp
@@ -126,8 +126,8 @@ bool Lane::waitForCompletion(lua_Duration duration_)
126 126
127 std::unique_lock lock{ m_done_mutex }; 127 std::unique_lock lock{ m_done_mutex };
128 //std::stop_token token{ m_thread.get_stop_token() }; 128 //std::stop_token token{ m_thread.get_stop_token() };
129 //return m_done_signal.wait_for(lock, token, secs_, [this](){ return status >= DONE; }); 129 //return m_done_signal.wait_until(lock, token, secs_, [this](){ return m_status >= Lane::Done; });
130 return m_done_signal.wait_until(lock, until, [this](){ return status >= DONE; }); 130 return m_done_signal.wait_until(lock, until, [this](){ return m_status >= Lane::Done; });
131} 131}
132 132
133static void lane_main(Lane* lane); 133static void lane_main(Lane* lane);
@@ -848,12 +848,12 @@ static void lane_main(Lane* lane)
848 // wait until the launching thread has finished preparing L 848 // wait until the launching thread has finished preparing L
849 lane->m_ready.wait(); 849 lane->m_ready.wait();
850 int rc{ LUA_ERRRUN }; 850 int rc{ LUA_ERRRUN };
851 if (lane->status == PENDING) // nothing wrong happened during preparation, we can work 851 if (lane->m_status == Lane::Pending) // nothing wrong happened during preparation, we can work
852 { 852 {
853 // At this point, the lane function and arguments are on the stack 853 // At this point, the lane function and arguments are on the stack
854 int const nargs{ lua_gettop(L) - 1 }; 854 int const nargs{ lua_gettop(L) - 1 };
855 DEBUGSPEW_CODE(Universe* U = universe_get(L)); 855 DEBUGSPEW_CODE(Universe* U = universe_get(L));
856 lane->status = RUNNING; // PENDING -> RUNNING 856 lane->m_status = Lane::Running; // Pending -> Running
857 857
858 // Tie "set_finalizer()" to the state 858 // Tie "set_finalizer()" to the state
859 lua_pushcfunction(L, LG_set_finalizer); 859 lua_pushcfunction(L, LG_set_finalizer);
@@ -924,14 +924,12 @@ static void lane_main(Lane* lane)
924 { 924 {
925 // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them 925 // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them
926 926
927 enum e_status st = (rc == 0) ? DONE : CANCEL_ERROR.equals(L, 1) ? CANCELLED : ERROR_ST; 927 Lane::Status st = (rc == LUA_OK) ? Lane::Done : CANCEL_ERROR.equals(L, 1) ? Lane::Cancelled : Lane::Error;
928 928
929 // Posix no PTHREAD_TIMEDJOIN:
930 // 'm_done_mutex' protects the -> DONE|ERROR_ST|CANCELLED state change
931 //
932 { 929 {
930 // 'm_done_mutex' protects the -> Done|Error|Cancelled state change
933 std::lock_guard lock{ lane->m_done_mutex }; 931 std::lock_guard lock{ lane->m_done_mutex };
934 lane->status = st; 932 lane->m_status = st;
935 lane->m_done_signal.notify_one();// wake up master (while 'lane->m_done_mutex' is on) 933 lane->m_done_signal.notify_one();// wake up master (while 'lane->m_done_mutex' is on)
936 } 934 }
937 } 935 }
@@ -1045,13 +1043,15 @@ LUAG_FUNC(lane_new)
1045 lua_State* const m_L; 1043 lua_State* const m_L;
1046 Lane* m_lane{ nullptr }; 1044 Lane* m_lane{ nullptr };
1047 int const m_gc_cb_idx; 1045 int const m_gc_cb_idx;
1046 DEBUGSPEW_CODE(Universe* const U); // for DEBUGSPEW only (hence the absence of m_ prefix)
1048 1047
1049 public: 1048 public:
1050 1049
1051 OnExit(lua_State* L_, Lane* lane_, int gc_cb_idx_) 1050 OnExit(lua_State* L_, Lane* lane_, int gc_cb_idx_ DEBUGSPEW_COMMA_PARAM(Universe* U_))
1052 : m_L{ L_ } 1051 : m_L{ L_ }
1053 , m_lane{ lane_ } 1052 , m_lane{ lane_ }
1054 , m_gc_cb_idx{ gc_cb_idx_ } 1053 , m_gc_cb_idx{ gc_cb_idx_ }
1054 DEBUGSPEW_COMMA_PARAM(U{ U_ })
1055 {} 1055 {}
1056 1056
1057 ~OnExit() 1057 ~OnExit()
@@ -1065,7 +1065,7 @@ LUAG_FUNC(lane_new)
1065 CANCEL_ERROR.pushKey(m_lane->L); 1065 CANCEL_ERROR.pushKey(m_lane->L);
1066 { 1066 {
1067 std::lock_guard lock{ m_lane->m_done_mutex }; 1067 std::lock_guard lock{ m_lane->m_done_mutex };
1068 m_lane->status = CANCELLED; 1068 m_lane->m_status = Lane::Cancelled;
1069 m_lane->m_done_signal.notify_one(); // wake up master (while 'lane->m_done_mutex' is on) 1069 m_lane->m_done_signal.notify_one(); // wake up master (while 'lane->m_done_mutex' is on)
1070 } 1070 }
1071 // unblock the thread so that it can terminate gracefully 1071 // unblock the thread so that it can terminate gracefully
@@ -1113,7 +1113,7 @@ LUAG_FUNC(lane_new)
1113 m_lane->m_ready.count_down(); 1113 m_lane->m_ready.count_down();
1114 m_lane = nullptr; 1114 m_lane = nullptr;
1115 } 1115 }
1116 } onExit{ L, lane, gc_cb_idx }; 1116 } onExit{ L, lane, gc_cb_idx DEBUGSPEW_COMMA_PARAM(U) };
1117 // launch the thread early, it will sync with a std::latch to parallelize OS thread warmup and L2 preparation 1117 // launch the thread early, it will sync with a std::latch to parallelize OS thread warmup and L2 preparation
1118 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END)); 1118 DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END));
1119 lane->startThread(priority); 1119 lane->startThread(priority);
@@ -1311,7 +1311,7 @@ static int lane_gc(lua_State* L)
1311 } 1311 }
1312 1312
1313 // We can read 'lane->status' without locks, but not wait for it 1313 // We can read 'lane->status' without locks, but not wait for it
1314 if (lane->status < DONE) 1314 if (lane->m_status < Lane::Done)
1315 { 1315 {
1316 // still running: will have to be cleaned up later 1316 // still running: will have to be cleaned up later
1317 selfdestruct_add(lane); 1317 selfdestruct_add(lane);
@@ -1358,14 +1358,14 @@ static int lane_gc(lua_State* L)
1358// 1358//
1359static char const * thread_status_string(Lane* lane_) 1359static char const * thread_status_string(Lane* lane_)
1360{ 1360{
1361 enum e_status const st{ lane_->status }; // read just once (volatile) 1361 Lane::Status const st{ lane_->m_status }; // read just once (volatile)
1362 char const* str = 1362 char const* str =
1363 (st == PENDING) ? "pending" : 1363 (st == Lane::Pending) ? "pending" :
1364 (st == RUNNING) ? "running" : // like in 'co.status()' 1364 (st == Lane::Running) ? "running" : // like in 'co.status()'
1365 (st == WAITING) ? "waiting" : 1365 (st == Lane::Waiting) ? "waiting" :
1366 (st == DONE) ? "done" : 1366 (st == Lane::Done) ? "done" :
1367 (st == ERROR_ST) ? "error" : 1367 (st == Lane::Error) ? "error" :
1368 (st == CANCELLED) ? "cancelled" : nullptr; 1368 (st == Lane::Cancelled) ? "cancelled" : nullptr;
1369 return str; 1369 return str;
1370} 1370}
1371 1371
@@ -1406,16 +1406,16 @@ LUAG_FUNC(thread_join)
1406 } 1406 }
1407 1407
1408 STACK_CHECK_START_REL(L, 0); 1408 STACK_CHECK_START_REL(L, 0);
1409 // Thread is DONE/ERROR_ST/CANCELLED; all ours now 1409 // Thread is Done/Error/Cancelled; all ours now
1410 1410
1411 int ret{ 0 }; 1411 int ret{ 0 };
1412 Universe* const U{ lane->U }; 1412 Universe* const U{ lane->U };
1413 // debug_name is a pointer to string possibly interned in the lane's state, that no longer exists when the state is closed 1413 // debug_name is a pointer to string possibly interned in the lane's state, that no longer exists when the state is closed
1414 // so store it in the userdata uservalue at a key that can't possibly collide 1414 // so store it in the userdata uservalue at a key that can't possibly collide
1415 securize_debug_threadname(L, lane); 1415 securize_debug_threadname(L, lane);
1416 switch (lane->status) 1416 switch (lane->m_status)
1417 { 1417 {
1418 case DONE: 1418 case Lane::Done:
1419 { 1419 {
1420 int const n{ lua_gettop(L2) }; // whole L2 stack 1420 int const n{ lua_gettop(L2) }; // whole L2 stack
1421 if ((n > 0) && (luaG_inter_move(U, L2, L, n, LookupMode::LaneBody) != 0)) 1421 if ((n > 0) && (luaG_inter_move(U, L2, L, n, LookupMode::LaneBody) != 0))
@@ -1426,7 +1426,7 @@ LUAG_FUNC(thread_join)
1426 } 1426 }
1427 break; 1427 break;
1428 1428
1429 case ERROR_ST: 1429 case Lane::Error:
1430 { 1430 {
1431 int const n{ lua_gettop(L2) }; 1431 int const n{ lua_gettop(L2) };
1432 STACK_GROW(L, 3); 1432 STACK_GROW(L, 3);
@@ -1440,12 +1440,12 @@ LUAG_FUNC(thread_join)
1440 } 1440 }
1441 break; 1441 break;
1442 1442
1443 case CANCELLED: 1443 case Lane::Cancelled:
1444 ret = 0; 1444 ret = 0;
1445 break; 1445 break;
1446 1446
1447 default: 1447 default:
1448 DEBUGSPEW_CODE(fprintf(stderr, "Status: %d\n", lane->status)); 1448 DEBUGSPEW_CODE(fprintf(stderr, "Status: %d\n", lane->m_status));
1449 ASSERT_L(false); 1449 ASSERT_L(false);
1450 ret = 0; 1450 ret = 0;
1451 } 1451 }
@@ -1505,7 +1505,7 @@ LUAG_FUNC(thread_index)
1505 lua_pushcfunction(L, LG_thread_join); 1505 lua_pushcfunction(L, LG_thread_join);
1506 lua_pushvalue(L, UD); 1506 lua_pushvalue(L, UD);
1507 lua_call(L, 1, LUA_MULTRET); // all return values are on the stack, at slots 4+ 1507 lua_call(L, 1, LUA_MULTRET); // all return values are on the stack, at slots 4+
1508 switch (lane->status) 1508 switch (lane->m_status)
1509 { 1509 {
1510 default: 1510 default:
1511 // this is an internal error, we probably never get here 1511 // this is an internal error, we probably never get here
@@ -1516,7 +1516,7 @@ LUAG_FUNC(thread_index)
1516 raise_lua_error(L); 1516 raise_lua_error(L);
1517 [[fallthrough]]; // fall through if we are killed, as we got nil, "killed" on the stack 1517 [[fallthrough]]; // fall through if we are killed, as we got nil, "killed" on the stack
1518 1518
1519 case DONE: // got regular return values 1519 case Lane::Done: // got regular return values
1520 { 1520 {
1521 int const nvalues{ lua_gettop(L) - 3 }; 1521 int const nvalues{ lua_gettop(L) - 3 };
1522 for (int i = nvalues; i > 0; --i) 1522 for (int i = nvalues; i > 0; --i)
@@ -1527,7 +1527,7 @@ LUAG_FUNC(thread_index)
1527 } 1527 }
1528 break; 1528 break;
1529 1529
1530 case ERROR_ST: // got 3 values: nil, errstring, callstack table 1530 case Lane::Error: // got 3 values: nil, errstring, callstack table
1531 // me[-2] could carry the stack table, but even 1531 // me[-2] could carry the stack table, but even
1532 // me[-1] is rather unnecessary (and undocumented); 1532 // me[-1] is rather unnecessary (and undocumented);
1533 // use ':join()' instead. --AKa 22-Jan-2009 1533 // use ':join()' instead. --AKa 22-Jan-2009
@@ -1538,7 +1538,7 @@ LUAG_FUNC(thread_index)
1538 lua_rawset(L, USR); 1538 lua_rawset(L, USR);
1539 break; 1539 break;
1540 1540
1541 case CANCELLED: 1541 case Lane::Cancelled:
1542 // do nothing 1542 // do nothing
1543 break; 1543 break;
1544 } 1544 }
@@ -1648,13 +1648,17 @@ LUAG_FUNC(threads)
1648 */ 1648 */
1649 1649
1650/* 1650/*
1651* secs= now_secs() 1651* secs = now_secs()
1652* 1652*
1653* Returns the current time, as seconds (millisecond resolution). 1653* Returns the current time, as seconds. Resolution depends on std::system_clock implementation
1654* Can't use std::chrono::steady_clock because we need the same baseline as std::mktime
1654*/ 1655*/
1655LUAG_FUNC(now_secs) 1656LUAG_FUNC(now_secs)
1656{ 1657{
1657 lua_pushnumber(L, now_secs()); 1658 auto const now{ std::chrono::system_clock::now() };
1659 lua_Duration duration { now.time_since_epoch() };
1660
1661 lua_pushnumber(L, duration.count());
1658 return 1; 1662 return 1;
1659} 1663}
1660 1664
@@ -1739,10 +1743,6 @@ static const struct luaL_Reg lanes_functions[] =
1739 */ 1743 */
1740static void init_once_LOCKED( void) 1744static void init_once_LOCKED( void)
1741{ 1745{
1742#if (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
1743 now_secs(); // initialize 'now_secs()' internal offset
1744#endif
1745
1746#if (defined PLATFORM_OSX) && (defined _UTILBINDTHREADTOCPU) 1746#if (defined PLATFORM_OSX) && (defined _UTILBINDTHREADTOCPU)
1747 chudInitialize(); 1747 chudInitialize();
1748#endif 1748#endif
diff --git a/src/lanes_private.h b/src/lanes_private.h
index 01d43c0..3ed52fe 100644
--- a/src/lanes_private.h
+++ b/src/lanes_private.h
@@ -17,6 +17,22 @@ class Lane
17{ 17{
18 public: 18 public:
19 19
20 /*
21 Pending: The Lua VM hasn't done anything yet.
22 Running, Waiting: Thread is inside the Lua VM. If the thread is forcefully stopped, we can't lua_close() the Lua State.
23 Done, Error, Cancelled: Thread execution is outside the Lua VM. It can be lua_close()d.
24 */
25 enum class Status
26 {
27 Pending,
28 Running,
29 Waiting,
30 Done,
31 Error,
32 Cancelled
33 };
34 using enum Status;
35
20 // the thread 36 // the thread
21 std::jthread m_thread; 37 std::jthread m_thread;
22 // a latch to wait for the lua_State to be ready 38 // a latch to wait for the lua_State to be ready
@@ -36,16 +52,16 @@ class Lane
36 // M: prepares the state, and reads results 52 // M: prepares the state, and reads results
37 // S: while S is running, M must keep out of modifying the state 53 // S: while S is running, M must keep out of modifying the state
38 54
39 volatile enum e_status status{ PENDING }; 55 Status volatile m_status{ Pending };
40 // 56 //
41 // M: sets to PENDING (before launching) 57 // M: sets to Pending (before launching)
42 // S: updates -> RUNNING/WAITING -> DONE/ERROR_ST/CANCELLED 58 // S: updates -> Running/Waiting -> Done/Error/Cancelled
43 59
44 std::condition_variable* volatile m_waiting_on{ nullptr }; 60 std::condition_variable* volatile m_waiting_on{ nullptr };
45 // 61 //
46 // When status is WAITING, points on the linda's signal the thread waits on, else nullptr 62 // When status is Waiting, points on the linda's signal the thread waits on, else nullptr
47 63
48 volatile CancelRequest cancel_request{ CancelRequest::None }; 64 CancelRequest volatile cancel_request{ CancelRequest::None };
49 // 65 //
50 // M: sets to false, flags true for cancel request 66 // M: sets to false, flags true for cancel request
51 // S: reads to see if cancel is requested 67 // S: reads to see if cancel is requested
diff --git a/src/linda.cpp b/src/linda.cpp
index ea1410e..fb74abe 100644
--- a/src/linda.cpp
+++ b/src/linda.cpp
@@ -306,13 +306,13 @@ LUAG_FUNC(linda_send)
306 306
307 // storage limit hit, wait until timeout or signalled that we should try again 307 // storage limit hit, wait until timeout or signalled that we should try again
308 { 308 {
309 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings 309 Lane::Status prev_status{ Lane::Error }; // prevent 'might be used uninitialized' warnings
310 if (lane != nullptr) 310 if (lane != nullptr)
311 { 311 {
312 // change status of lane to "waiting" 312 // change status of lane to "waiting"
313 prev_status = lane->status; // RUNNING, most likely 313 prev_status = lane->m_status; // Running, most likely
314 ASSERT_L(prev_status == RUNNING); // but check, just in case 314 ASSERT_L(prev_status == Lane::Running); // but check, just in case
315 lane->status = WAITING; 315 lane->m_status = Lane::Waiting;
316 ASSERT_L(lane->m_waiting_on == nullptr); 316 ASSERT_L(lane->m_waiting_on == nullptr);
317 lane->m_waiting_on = &linda->m_read_happened; 317 lane->m_waiting_on = &linda->m_read_happened;
318 } 318 }
@@ -324,7 +324,7 @@ LUAG_FUNC(linda_send)
324 if (lane != nullptr) 324 if (lane != nullptr)
325 { 325 {
326 lane->m_waiting_on = nullptr; 326 lane->m_waiting_on = nullptr;
327 lane->status = prev_status; 327 lane->m_status = prev_status;
328 } 328 }
329 } 329 }
330 } 330 }
@@ -470,13 +470,13 @@ LUAG_FUNC(linda_receive)
470 470
471 // nothing received, wait until timeout or signalled that we should try again 471 // nothing received, wait until timeout or signalled that we should try again
472 { 472 {
473 enum e_status prev_status = ERROR_ST; // prevent 'might be used uninitialized' warnings 473 Lane::Status prev_status{ Lane::Error }; // prevent 'might be used uninitialized' warnings
474 if (lane != nullptr) 474 if (lane != nullptr)
475 { 475 {
476 // change status of lane to "waiting" 476 // change status of lane to "waiting"
477 prev_status = lane->status; // RUNNING, most likely 477 prev_status = lane->m_status; // Running, most likely
478 ASSERT_L(prev_status == RUNNING); // but check, just in case 478 ASSERT_L(prev_status == Lane::Running); // but check, just in case
479 lane->status = WAITING; 479 lane->m_status = Lane::Waiting;
480 ASSERT_L(lane->m_waiting_on == nullptr); 480 ASSERT_L(lane->m_waiting_on == nullptr);
481 lane->m_waiting_on = &linda->m_write_happened; 481 lane->m_waiting_on = &linda->m_write_happened;
482 } 482 }
@@ -488,7 +488,7 @@ LUAG_FUNC(linda_receive)
488 if (lane != nullptr) 488 if (lane != nullptr)
489 { 489 {
490 lane->m_waiting_on = nullptr; 490 lane->m_waiting_on = nullptr;
491 lane->status = prev_status; 491 lane->m_status = prev_status;
492 } 492 }
493 } 493 }
494 } 494 }
diff --git a/src/threading.cpp b/src/threading.cpp
index fc20931..bc1852f 100644
--- a/src/threading.cpp
+++ b/src/threading.cpp
@@ -115,84 +115,6 @@ static void FAIL( char const* funcname, int rc)
115#endif // win32 build 115#endif // win32 build
116 116
117 117
118/*
119* Returns millisecond timing (in seconds) for the current time.
120*
121* Note: This function should be called once in single-threaded mode in Win32,
122* to get it initialized.
123*/
124time_d now_secs(void) {
125
126#if defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)
127 /*
128 * Windows FILETIME values are "100-nanosecond intervals since
129 * January 1, 1601 (UTC)" (MSDN). Well, we'd want Unix Epoch as
130 * the offset and it seems, so would they:
131 *
132 * <http://msdn.microsoft.com/en-us/library/ms724928(VS.85).aspx>
133 */
134 SYSTEMTIME st;
135 FILETIME ft;
136 ULARGE_INTEGER uli;
137 static ULARGE_INTEGER uli_epoch; // Jan 1st 1970 0:0:0
138
139 if (uli_epoch.HighPart==0) {
140 st.wYear= 1970;
141 st.wMonth= 1; // Jan
142 st.wDay= 1;
143 st.wHour= st.wMinute= st.wSecond= st.wMilliseconds= 0;
144
145 if (!SystemTimeToFileTime( &st, &ft ))
146 FAIL( "SystemTimeToFileTime", GetLastError() );
147
148 uli_epoch.LowPart= ft.dwLowDateTime;
149 uli_epoch.HighPart= ft.dwHighDateTime;
150 }
151
152 GetSystemTime( &st ); // current system date/time in UTC
153 if (!SystemTimeToFileTime( &st, &ft ))
154 FAIL( "SystemTimeToFileTime", GetLastError() );
155
156 uli.LowPart= ft.dwLowDateTime;
157 uli.HighPart= ft.dwHighDateTime;
158
159 /* 'double' has less accuracy than 64-bit int, but if it were to degrade,
160 * it would do so gracefully. In practice, the integer accuracy is not
161 * of the 100ns class but just 1ms (Windows XP).
162 */
163# if 1
164 // >= 2.0.3 code
165 return (double) ((uli.QuadPart - uli_epoch.QuadPart)/10000) / 1000.0;
166# elif 0
167 // fix from Kriss Daniels, see:
168 // <http://luaforge.net/forum/forum.php?thread_id=22704&forum_id=1781>
169 //
170 // "seem to be getting negative numbers from the old version, probably number
171 // conversion clipping, this fixes it and maintains ms resolution"
172 //
173 // This was a bad fix, and caused timer test 5 sec timers to disappear.
174 // --AKa 25-Jan-2009
175 //
176 return ((double)((signed)((uli.QuadPart/10000) - (uli_epoch.QuadPart/10000)))) / 1000.0;
177# else
178 // <= 2.0.2 code
179 return (double)(uli.QuadPart - uli_epoch.QuadPart) / 10000000.0;
180# endif
181#else // !(defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC))
182 struct timeval tv;
183 // {
184 // time_t tv_sec; /* seconds since Jan. 1, 1970 */
185 // suseconds_t tv_usec; /* and microseconds */
186 // };
187
188 int rc = gettimeofday(&tv, nullptr /*time zone not used any more (in Linux)*/);
189 assert( rc==0 );
190
191 return ((double)tv.tv_sec) + ((tv.tv_usec)/1000) / 1000.0;
192#endif // !(defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC))
193}
194
195
196/*---=== Threading ===---*/ 118/*---=== Threading ===---*/
197 119
198//--- 120//---
diff --git a/src/threading.h b/src/threading.h
index e9f302a..82c8f52 100644
--- a/src/threading.h
+++ b/src/threading.h
@@ -5,13 +5,6 @@
5#include <time.h> 5#include <time.h>
6#include <thread> 6#include <thread>
7 7
8/* Note: ERROR is a defined entity on Win32
9 PENDING: The Lua VM hasn't done anything yet.
10 RUNNING, WAITING: Thread is inside the Lua VM. If the thread is forcefully stopped, we can't lua_close() the Lua State.
11 DONE, ERROR_ST, CANCELLED: Thread execution is outside the Lua VM. It can be lua_close()d.
12*/
13enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED };
14
15#define THREADAPI_WINDOWS 1 8#define THREADAPI_WINDOWS 1
16#define THREADAPI_PTHREAD 2 9#define THREADAPI_PTHREAD 2
17 10
@@ -129,14 +122,6 @@ enum e_status { PENDING, RUNNING, WAITING, DONE, ERROR_ST, CANCELLED };
129 #define THREAD_CALLCONV 122 #define THREAD_CALLCONV
130#endif //THREADAPI == THREADAPI_PTHREAD 123#endif //THREADAPI == THREADAPI_PTHREAD
131 124
132/*
133* 'time_d': <0.0 for no timeout
134* 0.0 for instant check
135* >0.0 absolute timeout in secs + ms
136*/
137using time_d = double;
138time_d now_secs(void);
139
140/*---=== Threading ===--- 125/*---=== Threading ===---
141*/ 126*/
142 127