diff options
Diffstat (limited to 'src/lanes.cpp')
-rw-r--r-- | src/lanes.cpp | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp index 90f0f9f..d211b6a 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -169,17 +169,12 @@ Lane::Lane(Universe* U_, lua_State* L_) | |||
169 | 169 | ||
170 | // ################################################################################################# | 170 | // ################################################################################################# |
171 | 171 | ||
172 | bool Lane::waitForCompletion(lua_Duration duration_) | 172 | bool Lane::waitForCompletion(std::chrono::time_point<std::chrono::steady_clock> until_) |
173 | { | 173 | { |
174 | std::chrono::time_point<std::chrono::steady_clock> until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; | ||
175 | if (duration_.count() >= 0.0) { | ||
176 | until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration_); | ||
177 | } | ||
178 | |||
179 | std::unique_lock lock{ doneMutex }; | 174 | std::unique_lock lock{ doneMutex }; |
180 | // std::stop_token token{ thread.get_stop_token() }; | 175 | // std::stop_token token{ thread.get_stop_token() }; |
181 | // return doneCondVar.wait_until(lock, token, secs_, [this](){ return status >= Lane::Done; }); | 176 | // return doneCondVar.wait_until(lock, token, secs_, [this](){ return status >= Lane::Done; }); |
182 | return doneCondVar.wait_until(lock, until, [this]() { return status >= Lane::Done; }); | 177 | return doneCondVar.wait_until(lock, until_, [this]() { return status >= Lane::Done; }); |
183 | } | 178 | } |
184 | 179 | ||
185 | // ################################################################################################# | 180 | // ################################################################################################# |
@@ -1209,22 +1204,33 @@ void Lane::pushThreadStatus(lua_State* L_) | |||
1209 | LUAG_FUNC(thread_join) | 1204 | LUAG_FUNC(thread_join) |
1210 | { | 1205 | { |
1211 | Lane* const lane{ ToLane(L_, 1) }; | 1206 | Lane* const lane{ ToLane(L_, 1) }; |
1212 | lua_Duration const duration{ luaL_optnumber(L_, 2, -1.0) }; | ||
1213 | lua_State* const L2{ lane->L }; | 1207 | lua_State* const L2{ lane->L }; |
1214 | 1208 | ||
1215 | bool const done{ !lane->thread.joinable() || lane->waitForCompletion(duration) }; | 1209 | std::chrono::time_point<std::chrono::steady_clock> until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; |
1210 | if (lua_type(L_, 2) == LUA_TNUMBER) { // we don't want to use lua_isnumber() because of autocoercion | ||
1211 | lua_Duration const duration{ lua_tonumber(L_, 2) }; | ||
1212 | if (duration.count() >= 0.0) { | ||
1213 | until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); | ||
1214 | } else { | ||
1215 | raise_luaL_argerror(L_, 2, "duration cannot be < 0"); | ||
1216 | } | ||
1217 | |||
1218 | } else if (!lua_isnoneornil(L_, 2)) { // alternate explicit "infinite timeout" by passing nil before the key | ||
1219 | raise_luaL_argerror(L_, 2, "incorrect duration type"); | ||
1220 | } | ||
1221 | |||
1222 | bool const done{ !lane->thread.joinable() || lane->waitForCompletion(until) }; | ||
1223 | lua_settop(L_, 1); // L_: lane | ||
1216 | if (!done || !L2) { | 1224 | if (!done || !L2) { |
1217 | STACK_GROW(L_, 2); | 1225 | lua_pushnil(L_); // L_: lane nil |
1218 | lua_pushnil(L_); // L_: lane timeout? nil | 1226 | lua_pushliteral(L_, "timeout"); // L_: lane nil "timeout" |
1219 | lua_pushliteral(L_, "timeout"); // L_: lane timeout? nil "timeout" | ||
1220 | return 2; | 1227 | return 2; |
1221 | } | 1228 | } |
1222 | 1229 | ||
1223 | STACK_CHECK_START_REL(L_, 0); | 1230 | STACK_CHECK_START_REL(L_, 0); // L_: lane |
1224 | // Thread is Done/Error/Cancelled; all ours now | 1231 | // Thread is Done/Error/Cancelled; all ours now |
1225 | 1232 | ||
1226 | int ret{ 0 }; | 1233 | int ret{ 0 }; |
1227 | Universe* const U{ lane->U }; | ||
1228 | // debugName is a pointer to string possibly interned in the lane's state, that no longer exists when the state is closed | 1234 | // debugName is a pointer to string possibly interned in the lane's state, that no longer exists when the state is closed |
1229 | // so store it in the userdata uservalue at a key that can't possibly collide | 1235 | // so store it in the userdata uservalue at a key that can't possibly collide |
1230 | lane->securizeDebugName(L_); | 1236 | lane->securizeDebugName(L_); |
@@ -1234,8 +1240,8 @@ LUAG_FUNC(thread_join) | |||
1234 | int const n{ lua_gettop(L2) }; // whole L2 stack | 1240 | int const n{ lua_gettop(L2) }; // whole L2 stack |
1235 | if ( | 1241 | if ( |
1236 | (n > 0) && | 1242 | (n > 0) && |
1237 | (InterCopyContext{ U, DestState{ L_ }, SourceState{ L2 }, {}, {}, {}, {}, {} }.inter_move(n) != InterCopyResult::Success) | 1243 | (InterCopyContext{ lane->U, DestState{ L_ }, SourceState{ L2 }, {}, {}, {}, {}, {} }.inter_move(n) != InterCopyResult::Success) |
1238 | ) { // L_: lane timeout? results L2: | 1244 | ) { // L_: lane results L2: |
1239 | raise_luaL_error(L_, "tried to copy unsupported types"); | 1245 | raise_luaL_error(L_, "tried to copy unsupported types"); |
1240 | } | 1246 | } |
1241 | ret = n; | 1247 | ret = n; |
@@ -1244,12 +1250,12 @@ LUAG_FUNC(thread_join) | |||
1244 | 1250 | ||
1245 | case Lane::Error: | 1251 | case Lane::Error: |
1246 | { | 1252 | { |
1247 | int const n{ lua_gettop(L2) }; // L_: lane timeout? L2: "err" [trace] | 1253 | int const n{ lua_gettop(L2) }; // L_: lane L2: "err" [trace] |
1248 | STACK_GROW(L_, 3); | 1254 | STACK_GROW(L_, 3); |
1249 | lua_pushnil(L_); // L_: lane timeout? nil | 1255 | lua_pushnil(L_); // L_: lane nil |
1250 | // even when ERROR_FULL_STACK, if the error is not LUA_ERRRUN, the handler wasn't called, and we only have 1 error message on the stack ... | 1256 | // even when ERROR_FULL_STACK, if the error is not LUA_ERRRUN, the handler wasn't called, and we only have 1 error message on the stack ... |
1251 | InterCopyContext c{ U, DestState{ L_ }, SourceState{ L2 }, {}, {}, {}, {}, {} }; | 1257 | InterCopyContext c{ lane->U, DestState{ L_ }, SourceState{ L2 }, {}, {}, {}, {}, {} }; |
1252 | if (c.inter_move(n) != InterCopyResult::Success) { // L_: lane timeout? nil "err" [trace] L2: | 1258 | if (c.inter_move(n) != InterCopyResult::Success) { // L_: lane nil "err" [trace] L2: |
1253 | raise_luaL_error(L_, "tried to copy unsupported types: %s", lua_tostring(L_, -n)); | 1259 | raise_luaL_error(L_, "tried to copy unsupported types: %s", lua_tostring(L_, -n)); |
1254 | } | 1260 | } |
1255 | ret = 1 + n; | 1261 | ret = 1 + n; |