aboutsummaryrefslogtreecommitdiff
path: root/src/lanes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lanes.cpp')
-rw-r--r--src/lanes.cpp74
1 files changed, 37 insertions, 37 deletions
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