From 0b13436b835ea96ecdf930a380e9e5c8add8cb45 Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Wed, 20 Mar 2024 18:03:00 +0100 Subject: C++ migration: ThreadStatus, CancelRequest and CancelResult are enum class --- src/cancel.cpp | 55 ++++++++++++++++++++++++++--------------------------- src/cancel.h | 18 +++++++++--------- src/lanes.cpp | 18 +++++++++--------- src/lanes_private.h | 12 ++++++------ src/linda.cpp | 34 ++++++++++++++++----------------- 5 files changed, 68 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/cancel.cpp b/src/cancel.cpp index 81f25d5..73e50f5 100644 --- a/src/cancel.cpp +++ b/src/cancel.cpp @@ -53,11 +53,11 @@ THE SOFTWARE. * Returns CANCEL_SOFT/HARD if any locks are to be exited, and 'cancel_error()' called, * to make execution of the lane end. */ -static inline enum e_cancel_request cancel_test( lua_State* L) +static inline CancelRequest cancel_test(lua_State* L) { Lane* const s = get_lane_from_registry( L); // 's' is nullptr for the original main state (and no-one can cancel that) - return s ? s->cancel_request : CANCEL_NONE; + return s ? s->cancel_request : CancelRequest::None; } // ################################################################################################ @@ -70,19 +70,18 @@ static inline enum e_cancel_request cancel_test( lua_State* L) // LUAG_FUNC( cancel_test) { - enum e_cancel_request test = cancel_test( L); - lua_pushboolean( L, test != CANCEL_NONE); + CancelRequest test{ cancel_test(L) }; + lua_pushboolean(L, test != CancelRequest::None); return 1; } // ################################################################################################ // ################################################################################################ -static void cancel_hook( lua_State* L, lua_Debug* ar) +static void cancel_hook( lua_State* L, [[maybe_unused]] lua_Debug* ar) { - (void)ar; DEBUGSPEW_CODE( fprintf( stderr, "cancel_hook\n")); - if( cancel_test( L) != CANCEL_NONE) + if (cancel_test(L) != CancelRequest::None) { lua_sethook( L, nullptr, 0, 0); cancel_error( L); @@ -112,40 +111,40 @@ static void cancel_hook( lua_State* L, lua_Debug* ar) // ################################################################################################ -static cancel_result thread_cancel_soft( Lane* s, double secs_, bool wake_lindas_) +static CancelResult thread_cancel_soft(Lane* s, double secs_, bool wake_lindas_) { - s->cancel_request = CANCEL_SOFT; // it's now signaled to stop + s->cancel_request = CancelRequest::Soft; // it's now signaled to stop // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own if( wake_lindas_) // wake the thread so that execution returns from any pending linda operation if desired { - SIGNAL_T *waiting_on = s->waiting_on; + SIGNAL_T* waiting_on = s->waiting_on; if( s->status == WAITING && waiting_on != nullptr) { SIGNAL_ALL( waiting_on); } } - return THREAD_WAIT( &s->thread, secs_, &s->done_signal, &s->done_lock, &s->status) ? CR_Cancelled : CR_Timeout; + return THREAD_WAIT(&s->thread, secs_, &s->done_signal, &s->done_lock, &s->status) ? CancelResult::Cancelled : CancelResult::Timeout; } // ################################################################################################ -static cancel_result thread_cancel_hard( lua_State* L, Lane* s, double secs_, bool force_, double waitkill_timeout_) +static CancelResult thread_cancel_hard(lua_State* L, Lane* s, double secs_, bool force_, double waitkill_timeout_) { - cancel_result result; + CancelResult result; - s->cancel_request = CANCEL_HARD; // it's now signaled to stop + s->cancel_request = CancelRequest::Hard; // it's now signaled to stop { - SIGNAL_T *waiting_on = s->waiting_on; + SIGNAL_T* waiting_on = s->waiting_on; if( s->status == WAITING && waiting_on != nullptr) { SIGNAL_ALL( waiting_on); } } - result = THREAD_WAIT( &s->thread, secs_, &s->done_signal, &s->done_lock, &s->status) ? CR_Cancelled : CR_Timeout; + result = THREAD_WAIT(&s->thread, secs_, &s->done_signal, &s->done_lock, &s->status) ? CancelResult::Cancelled : CancelResult::Timeout; - if( (result == CR_Timeout) && force_) + if ((result == CancelResult::Timeout) && force_) { // Killing is asynchronous; we _will_ wait for it to be done at // GC, to make sure the data structure can be released (alternative @@ -156,8 +155,8 @@ static cancel_result thread_cancel_hard( lua_State* L, Lane* s, double secs_, bo #if THREADAPI == THREADAPI_PTHREAD // pthread: make sure the thread is really stopped! // note that this may block forever if the lane doesn't call a cancellation point and pthread doesn't honor PTHREAD_CANCEL_ASYNCHRONOUS - result = THREAD_WAIT( &s->thread, waitkill_timeout_, &s->done_signal, &s->done_lock, &s->status) ? CR_Killed : CR_Timeout; - if( result == CR_Timeout) + result = THREAD_WAIT(&s->thread, waitkill_timeout_, &s->done_signal, &s->done_lock, &s->status) ? CancelResult::Killed : CancelResult::Timeout; + if (result == CancelResult::Timeout) { (void) luaL_error( L, "force-killed lane failed to terminate within %f second%s", waitkill_timeout_, waitkill_timeout_ > 1 ? "s" : ""); } @@ -165,29 +164,29 @@ static cancel_result thread_cancel_hard( lua_State* L, Lane* s, double secs_, bo (void) waitkill_timeout_; // unused (void) L; // unused #endif // THREADAPI == THREADAPI_PTHREAD - s->mstatus = KILLED; // mark 'gc' to wait for it + s->mstatus = ThreadStatus::Killed; // mark 'gc' to wait for it // note that s->status value must remain to whatever it was at the time of the kill // because we need to know if we can lua_close() the Lua State or not. - result = CR_Killed; + result = CancelResult::Killed; } return result; } // ################################################################################################ -cancel_result thread_cancel( lua_State* L, Lane* s, CancelOp op_, double secs_, bool force_, double waitkill_timeout_) +CancelResult thread_cancel(lua_State* L, Lane* s, CancelOp op_, double secs_, bool force_, double waitkill_timeout_) { // remember that lanes are not transferable: only one thread can cancel a lane, so no multithreading issue here // We can read 's->status' without locks, but not wait for it (if Posix no PTHREAD_TIMEDJOIN) - if( s->mstatus == KILLED) + if (s->mstatus == ThreadStatus::Killed) { - return CR_Killed; + return CancelResult::Killed; } if( s->status >= DONE) { // say "ok" by default, including when lane is already done - return CR_Cancelled; + return CancelResult::Cancelled; } // signal the linda the wake up the thread so that it can react to the cancel query @@ -281,17 +280,17 @@ LUAG_FUNC( thread_cancel) switch( thread_cancel( L, s, op, secs, force, forcekill_timeout)) { - case CR_Timeout: + case CancelResult::Timeout: lua_pushboolean( L, 0); lua_pushstring( L, "timeout"); return 2; - case CR_Cancelled: + case CancelResult::Cancelled: lua_pushboolean( L, 1); push_thread_status( L, s); return 2; - case CR_Killed: + case CancelResult::Killed: lua_pushboolean( L, 1); push_thread_status( L, s); return 2; diff --git a/src/cancel.h b/src/cancel.h index be4d781..9a20774 100644 --- a/src/cancel.h +++ b/src/cancel.h @@ -20,18 +20,18 @@ struct Lane; // forward /* * Lane cancellation request modes */ -enum e_cancel_request +enum class CancelRequest { - CANCEL_NONE, // no pending cancel request - CANCEL_SOFT, // user wants the lane to cancel itself manually on cancel_test() - CANCEL_HARD // user wants the lane to be interrupted (meaning code won't return from those functions) from inside linda:send/receive calls + None, // no pending cancel request + Soft, // user wants the lane to cancel itself manually on cancel_test() + Hard // user wants the lane to be interrupted (meaning code won't return from those functions) from inside linda:send/receive calls }; -enum cancel_result +enum class CancelResult { - CR_Timeout, - CR_Cancelled, - CR_Killed + Timeout, + Cancelled, + Killed }; enum CancelOp @@ -51,7 +51,7 @@ static constexpr UniqueKey CANCEL_ERROR{ 0xe97d41626cc97577ull }; // 'cancel_err // crc64/we of string "CANCEL_TEST_KEY" generated at http://www.nitrxgen.net/hashgen/ static constexpr UniqueKey CANCEL_TEST_KEY{ 0xe66f5960c57d133aull }; // used as registry key -cancel_result thread_cancel( lua_State* L, Lane* s, CancelOp op_, double secs_, bool force_, double waitkill_timeout_); +CancelResult thread_cancel(lua_State* L, Lane* s, CancelOp op_, double secs_, bool force_, double waitkill_timeout_); static inline int cancel_error( lua_State* L) { diff --git a/src/lanes.cpp b/src/lanes.cpp index e3f53c0..acfa0dc 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp @@ -456,7 +456,7 @@ static int selfdestruct_gc( lua_State* L) while( s != SELFDESTRUCT_END) { // attempt a regular unforced hard cancel with a small timeout - bool const cancelled = THREAD_ISNULL( s->thread) || thread_cancel( L, s, CO_Hard, 0.0001, false, 0.0); + bool const cancelled = THREAD_ISNULL( s->thread) || thread_cancel( L, s, CO_Hard, 0.0001, false, 0.0) != CancelResult::Timeout; // if we failed, and we know the thread is waiting on a linda if( cancelled == false && s->status == WAITING && s->waiting_on != nullptr) { @@ -501,7 +501,7 @@ static int selfdestruct_gc( lua_State* L) Lane* s = U->selfdestruct_first; while( s != SELFDESTRUCT_END) { - if( s->cancel_request == CANCEL_HARD) + if (s->cancel_request == CancelRequest::Hard) ++ n; s = s->selfdestruct_next; } @@ -1239,13 +1239,13 @@ LUAG_FUNC( lane_new) s->status = PENDING; s->waiting_on = nullptr; s->debug_name = ""; - s->cancel_request = CANCEL_NONE; + s->cancel_request = CancelRequest::None; #if THREADWAIT_METHOD == THREADWAIT_CONDVAR MUTEX_INIT( &s->done_lock); SIGNAL_INIT( &s->done_signal); #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR - s->mstatus = NORMAL; + s->mstatus = ThreadStatus::Normal; s->selfdestruct_next = nullptr; #if HAVE_LANE_TRACKING() s->tracking_next = nullptr; @@ -1322,8 +1322,8 @@ LUAG_FUNC( thread_gc) } // We can read 's->status' without locks, but not wait for it - // test KILLED state first, as it doesn't need to enter the selfdestruct chain - if( s->mstatus == KILLED) + // test Killed state first, as it doesn't need to enter the selfdestruct chain + if (s->mstatus == ThreadStatus::Killed) { // Make sure a kill has proceeded, before cleaning up the data structure. // @@ -1392,7 +1392,7 @@ static char const * thread_status_string( Lane* s) { enum e_status st = s->status; // read just once (volatile) char const* str = - (s->mstatus == KILLED) ? "killed" : // new to v3.3.0! + (s->mstatus == ThreadStatus::Killed) ? "killed" : // new to v3.3.0! (st == PENDING) ? "pending" : (st == RUNNING) ? "running" : // like in 'co.status()' (st == WAITING) ? "waiting" : @@ -1438,7 +1438,7 @@ LUAG_FUNC( thread_join) STACK_CHECK( L, 0); // Thread is DONE/ERROR_ST/CANCELLED; all ours now - if( s->mstatus == KILLED) // OS thread was killed if thread_cancel was forced + if (s->mstatus == ThreadStatus::Killed) // OS thread was killed if thread_cancel was forced { // in that case, even if the thread was killed while DONE/ERROR_ST/CANCELLED, ignore regular return values STACK_GROW( L, 2); @@ -1548,7 +1548,7 @@ LUAG_FUNC( thread_index) switch( s->status) { default: - if( s->mstatus != KILLED) + if (s->mstatus != ThreadStatus::Killed) { // this is an internal error, we probably never get here lua_settop( L, 0); diff --git a/src/lanes_private.h b/src/lanes_private.h index cd0c388..75607b9 100644 --- a/src/lanes_private.h +++ b/src/lanes_private.h @@ -4,10 +4,10 @@ #include "cancel.h" #include "universe.h" -enum ThreadStatus +enum class ThreadStatus { - NORMAL, // normal master side state - KILLED // issued an OS kill + Normal, // normal master side state + Killed // issued an OS kill }; // NOTE: values to be changed by either thread, during execution, without @@ -37,7 +37,7 @@ struct Lane // // When status is WAITING, points on the linda's signal the thread waits on, else nullptr - volatile enum e_cancel_request cancel_request; + volatile CancelRequest cancel_request; // // M: sets to false, flags true for cancel request // S: reads to see if cancel is requested @@ -54,9 +54,9 @@ struct Lane // lane status changes to DONE/ERROR_ST/CANCELLED. #endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR - volatile enum ThreadStatus mstatus; + volatile ThreadStatus mstatus; // - // M: sets to NORMAL, if issued a kill changes to KILLED + // M: sets to Normal, if issued a kill changes to Killed // S: not used Lane* volatile selfdestruct_next; diff --git a/src/linda.cpp b/src/linda.cpp index 10ee08b..ff3d543 100644 --- a/src/linda.cpp +++ b/src/linda.cpp @@ -53,7 +53,7 @@ struct s_Linda SIGNAL_T write_happened; Universe* U; // the universe this linda belongs to ptrdiff_t group; // a group to control keeper allocation between lindas - enum e_cancel_request simulate_cancel; + CancelRequest simulate_cancel; char name[1]; }; #define LINDA_KEEPER_HASHSEED( linda) (linda->group ? linda->group : (ptrdiff_t)linda) @@ -122,7 +122,7 @@ LUAG_FUNC( linda_send) { struct s_Linda* linda = lua_toLinda( L, 1); bool ret{ false }; - enum e_cancel_request cancel = CANCEL_NONE; + CancelRequest cancel{ CancelRequest::None }; int pushed; time_d timeout = -1.0; int key_i = 2; // index of first key, if timeout not there @@ -178,9 +178,9 @@ LUAG_FUNC( linda_send) { cancel = s->cancel_request; } - cancel = (cancel != CANCEL_NONE) ? cancel : linda->simulate_cancel; + cancel = (cancel != CancelRequest::None) ? cancel : linda->simulate_cancel; // if user wants to cancel, or looped because of a timeout, the call returns without sending anything - if( !try_again || cancel != CANCEL_NONE) + if (!try_again || cancel != CancelRequest::None) { pushed = 0; break; @@ -241,12 +241,12 @@ LUAG_FUNC( linda_send) switch( cancel) { - case CANCEL_SOFT: + case CancelRequest::Soft: // if user wants to soft-cancel, the call returns lanes.cancel_error CANCEL_ERROR.push(L); return 1; - case CANCEL_HARD: + case CancelRequest::Hard: // raise an error interrupting execution only in case of hard cancel return cancel_error( L); // raises an error and doesn't return @@ -273,7 +273,7 @@ LUAG_FUNC( linda_receive) { struct s_Linda* linda = lua_toLinda( L, 1); int pushed, expected_pushed_min, expected_pushed_max; - enum e_cancel_request cancel = CANCEL_NONE; + CancelRequest cancel{ CancelRequest::None }; keeper_api_t keeper_receive; time_d timeout = -1.0; @@ -335,9 +335,9 @@ LUAG_FUNC( linda_receive) { cancel = s->cancel_request; } - cancel = (cancel != CANCEL_NONE) ? cancel : linda->simulate_cancel; + cancel = (cancel != CancelRequest::None) ? cancel : linda->simulate_cancel; // if user wants to cancel, or looped because of a timeout, the call returns without sending anything - if( !try_again || cancel != CANCEL_NONE) + if (!try_again || cancel != CancelRequest::None) { pushed = 0; break; @@ -395,12 +395,12 @@ LUAG_FUNC( linda_receive) switch( cancel) { - case CANCEL_SOFT: + case CancelRequest::Soft: // if user wants to soft-cancel, the call returns CANCEL_ERROR CANCEL_ERROR.push(L); return 1; - case CANCEL_HARD: + case CancelRequest::Hard: // raise an error interrupting execution only in case of hard cancel return cancel_error( L); // raises an error and doesn't return @@ -430,7 +430,7 @@ LUAG_FUNC( linda_set) { Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); - if( linda->simulate_cancel == CANCEL_NONE) + if (linda->simulate_cancel == CancelRequest::None) { if( has_value) { @@ -511,7 +511,7 @@ LUAG_FUNC( linda_get) { Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); - if( linda->simulate_cancel == CANCEL_NONE) + if (linda->simulate_cancel == CancelRequest::None) { pushed = keeper_call( linda->U, K->L, KEEPER_API( get), L, linda, 2); if( pushed > 0) @@ -557,7 +557,7 @@ LUAG_FUNC( linda_limit) { Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); - if( linda->simulate_cancel == CANCEL_NONE) + if (linda->simulate_cancel == CancelRequest::None) { pushed = keeper_call( linda->U, K->L, KEEPER_API( limit), L, linda, 2); ASSERT_L( pushed == 0 || pushed == 1); // no error, optional boolean value saying if we should wake blocked writer threads @@ -592,7 +592,7 @@ LUAG_FUNC( linda_cancel) // make sure we got 3 arguments: the linda, a key and a limit luaL_argcheck( L, lua_gettop( L) <= 2, 2, "wrong number of arguments"); - linda->simulate_cancel = CANCEL_SOFT; + linda->simulate_cancel = CancelRequest::Soft; if( strcmp( who, "both") == 0) // tell everyone writers to wake up { SIGNAL_ALL( &linda->write_happened); @@ -600,7 +600,7 @@ LUAG_FUNC( linda_cancel) } else if( strcmp( who, "none") == 0) // reset flag { - linda->simulate_cancel = CANCEL_NONE; + linda->simulate_cancel = CancelRequest::None; } else if( strcmp( who, "read") == 0) // tell blocked readers to wake up { @@ -802,7 +802,7 @@ static void* linda_id( lua_State* L, DeepOp op_) SIGNAL_INIT( &s->read_happened); SIGNAL_INIT( &s->write_happened); s->U = universe_get( L); - s->simulate_cancel = CANCEL_NONE; + s->simulate_cancel = CancelRequest::None; s->group = linda_group << KEEPER_MAGIC_SHIFT; s->name[0] = 0; memcpy( s->name, linda_name, name_len ? name_len + 1 : 0); -- cgit v1.2.3-55-g6feb