diff --git a/Userland/Libraries/LibThreading/Thread.h b/Userland/Libraries/LibThreading/Thread.h index 3a620f6969..bb06473a6e 100644 --- a/Userland/Libraries/LibThreading/Thread.h +++ b/Userland/Libraries/LibThreading/Thread.h @@ -18,6 +18,28 @@ namespace Threading { AK_TYPEDEF_DISTINCT_ORDERED_ID(intptr_t, ThreadError); +// States of userspace threads are simplified over actual kernel states (and possibly POSIX states). +// There are only a couple of well-defined transitions between these states, and any attempt to call a function in a state where this is not allowed will crash the program. +enum class ThreadState : u8 { + // Thread has been constructed but not started. + // Transitions to Running via start(). + Startable, + // Thread has been started, might be running, and can be joined. + // Note that join() (valid to call in this state) only changes the thread state after the thread has exited, so it only ever transitions from Exited to Joined. + // Transitions to Detached via detach(), transitions to Exited when the thread finishes its action function. + Running, + // Thread has not been detached and exited, and has to still be joined. + // Transitions to Joined via join(). + Exited, + // Thread has been started but also detached, meaning it cannot be joined. + // Transitions to DetachedExited when the thread finishes its action function. + Detached, + // Thread has exited but was detached, meaning it cannot be joined. + DetachedExited, + // Thread has exited and been joined. + Joined, +}; + class Thread final : public Core::Object { C_OBJECT(Thread); @@ -71,3 +93,34 @@ struct AK::Formatter : AK::Formatter { return Formatter::format(builder, "Thread \"{}\"({})"sv, thread.thread_name(), thread.tid()); } }; + +template<> +struct AK::Formatter : AK::Formatter { + ErrorOr format(FormatBuilder& builder, Threading::ThreadState state) + { + String name = ""; + switch (state) { + case Threading::ThreadState::Detached: + name = "Detached"; + break; + case Threading::ThreadState::DetachedExited: + name = "DetachedExited"; + break; + case Threading::ThreadState::Exited: + name = "Exited"; + break; + case Threading::ThreadState::Joined: + name = "Joined"; + break; + case Threading::ThreadState::Running: + name = "Running"; + break; + case Threading::ThreadState::Startable: + name = "Startable"; + break; + default: + VERIFY_NOT_REACHED(); + } + return Formatter::format(builder, "{}"sv, name); + } +};