1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-14 06:14:58 +00:00

LibThreading: Remove Thread's inheritance from Core::EventReceiver

Inheritance from `EventReceiver` on the `Thread` class was only used in
the `BackgroundAction` class, where the children vector was keeping the
action alive until the work was completed. However, this can be
accomplished by instead capturing a `NonnullRefPtr` of `this`. The work
function can then avoid having to remove the `BackgroundAction` from
its parent `Thread` when the work completes.
This commit is contained in:
Zaggy1024 2023-08-06 01:21:49 -05:00 committed by Andrew Kaster
parent 925afcd4b0
commit 71df0ee994
3 changed files with 28 additions and 29 deletions

View file

@ -55,8 +55,7 @@ public:
private:
BackgroundAction(Function<ErrorOr<Result>(BackgroundAction&)> action, Function<ErrorOr<void>(Result)> on_complete, Optional<Function<void(Error)>> on_error = {})
: Core::EventReceiver(&background_thread())
, m_promise(Promise::try_create().release_value_but_fixme_should_propagate_errors())
: m_promise(Promise::try_create().release_value_but_fixme_should_propagate_errors())
, m_action(move(action))
, m_on_complete(move(on_complete))
{
@ -75,21 +74,18 @@ private:
if (on_error.has_value())
m_on_error = on_error.release_value();
enqueue_work([this, origin_event_loop = &Core::EventLoop::current()] {
auto result = m_action(*this);
enqueue_work([self = NonnullRefPtr(*this), origin_event_loop = &Core::EventLoop::current()]() {
auto result = self->m_action(*self);
// The event loop cancels the promise when it exits.
m_canceled |= m_promise->is_rejected();
auto callback_scheduled = false;
self->m_canceled |= self->m_promise->is_rejected();
// All of our work was successful and we weren't cancelled; resolve the event loop's promise.
if (!m_canceled && !result.is_error()) {
m_result = result.release_value();
if (!self->m_canceled && !result.is_error()) {
self->m_result = result.release_value();
// If there is no completion callback, we don't rely on the user keeping around the event loop.
if (m_on_complete) {
callback_scheduled = true;
origin_event_loop->deferred_invoke([this] {
if (self->m_on_complete) {
origin_event_loop->deferred_invoke([self] {
// Our promise's resolution function will never error.
(void)m_promise->resolve(*this);
remove_from_parent();
(void)self->m_promise->resolve(*self);
});
origin_event_loop->wake();
}
@ -99,21 +95,16 @@ private:
if (result.is_error())
error = result.release_error();
m_promise->reject(Error::from_errno(ECANCELED));
if (!m_canceled && m_on_error) {
callback_scheduled = true;
origin_event_loop->deferred_invoke([this, error = move(error)]() mutable {
m_on_error(move(error));
remove_from_parent();
self->m_promise->reject(Error::from_errno(ECANCELED));
if (!self->m_canceled && self->m_on_error) {
origin_event_loop->deferred_invoke([self, error = move(error)]() mutable {
self->m_on_error(move(error));
});
origin_event_loop->wake();
} else if (m_on_error) {
m_on_error(move(error));
} else if (self->m_on_error) {
self->m_on_error(move(error));
}
}
if (!callback_scheduled)
remove_from_parent();
});
}

View file

@ -12,8 +12,7 @@
namespace Threading {
Thread::Thread(Function<intptr_t()> action, StringView thread_name)
: Core::EventReceiver(nullptr)
, m_action(move(action))
: m_action(move(action))
, m_thread_name(thread_name.is_null() ? ""sv : thread_name)
{
}

View file

@ -41,10 +41,19 @@ enum class ThreadState : u8 {
Joined,
};
class Thread final : public Core::EventReceiver {
C_OBJECT(Thread);
class Thread final
: public RefCounted<Thread>
, public Weakable<Thread> {
public:
static NonnullRefPtr<Thread> construct(Function<intptr_t()> action, StringView thread_name = {})
{
return adopt_ref(*new Thread(move(action), thread_name));
}
static ErrorOr<NonnullRefPtr<Thread>> try_create(Function<intptr_t()> action, StringView thread_name = {})
{
return adopt_nonnull_ref_or_enomem(new (nothrow) Thread(move(action), thread_name));
}
virtual ~Thread();
ErrorOr<void> set_priority(int priority);