2020-01-18 05:38:21 -03:00
/*
2024-10-04 08:19:50 -03:00
* Copyright ( c ) 2018 - 2023 , Andreas Kling < andreas @ ladybird . org >
2022-12-29 09:20:44 -03:00
* Copyright ( c ) 2022 , kleines Filmröllchen < filmroellchen @ serenityos . org >
2022-02-26 13:09:45 -03:00
* Copyright ( c ) 2022 , the SerenityOS developers .
2020-01-18 05:38:21 -03:00
*
2021-04-22 05:24:48 -03:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 05:38:21 -03:00
*/
2019-04-10 12:30:34 -03:00
# pragma once
2025-12-05 16:48:48 -03:00
# include <AK/AtomicRefCounted.h>
2020-02-14 18:29:06 -03:00
# include <AK/Forward.h>
2020-07-06 18:48:02 -03:00
# include <AK/Function.h>
2020-02-14 22:09:00 -03:00
# include <AK/Noncopyable.h>
# include <AK/NonnullOwnPtr.h>
2026-02-21 07:55:51 -03:00
# include <AK/NonnullRefPtr.h>
# include <AK/RefPtr.h>
2025-12-04 14:12:06 -03:00
# include <LibCore/Export.h>
2020-02-14 18:29:06 -03:00
# include <LibCore/Forward.h>
2025-10-30 09:29:29 -03:00
# include <LibSync/RWLock.h>
2019-04-10 12:30:34 -03:00
2020-02-02 08:34:39 -03:00
namespace Core {
2019-04-10 12:30:34 -03:00
2023-04-24 07:25:14 -03:00
class EventLoopImplementation ;
2023-04-25 11:53:07 -03:00
class ThreadEventQueue ;
2025-12-05 16:48:48 -03:00
class WeakEventLoopReference ;
2023-04-24 07:25:14 -03:00
2022-12-30 11:17:52 -03:00
// The event loop enables asynchronous (not parallel or multi-threaded) computing by efficiently handling events from various sources.
// Event loops are most important for GUI programs, where the various GUI updates and action callbacks run on the EventLoop,
// as well as services, where asynchronous remote procedure calls of multiple clients are handled.
// Event loops, through select(), allow programs to "go to sleep" for most of their runtime until some event happens.
// EventLoop is too expensive to use in realtime scenarios (read: audio) where even the time required by a single select() system call is too large and unpredictable.
//
2026-06-04 13:58:06 -03:00
// There is at most one event loop per thread.
2022-12-30 11:17:52 -03:00
// Event loops currently handle these kinds of events:
// - Deferred invocations caused by various objects. These are just a generic way of telling the EventLoop to run some function as soon as possible at a later point.
// - Timers, which repeatedly (or once after a delay) run a function on the EventLoop. Note that timers are not super accurate.
// - Filesystem notifications, i.e. whenever a file is read from, written to, etc.
// - POSIX signals, which allow the event loop to act as a signal handler and dispatch those signals in a more user-friendly way.
// - Fork events, because the child process event loop needs to clear its events and handlers.
// - Quit events, i.e. the event loop should exit.
// Any event that the event loop needs to wait on or needs to repeatedly handle is stored in a handle, e.g. s_timers.
2025-12-04 14:12:06 -03:00
class CORE_API EventLoop {
2025-03-09 16:43:51 -03:00
AK_MAKE_NONMOVABLE ( EventLoop ) ;
AK_MAKE_NONCOPYABLE ( EventLoop ) ;
2019-04-10 12:30:34 -03:00
public :
2022-12-30 11:17:52 -03:00
enum class WaitMode {
WaitForEvents ,
PollForEvents ,
} ;
2023-04-24 05:31:49 -03:00
EventLoop ( ) ;
2020-02-02 08:34:39 -03:00
~ EventLoop ( ) ;
2022-12-30 11:17:52 -03:00
2026-06-04 14:51:47 -03:00
// Create an event loop for the current thread and keep it alive for the rest of the program.
static EventLoop & initialize_for_current_thread ( ) ;
2022-12-30 11:17:52 -03:00
// Pump the event loop until its exit is requested.
2019-04-10 12:30:34 -03:00
int exec ( ) ;
2022-12-30 11:17:52 -03:00
// Process events, generally called by exec() in a loop.
// This should really only be used for integrating with other event loops.
// The wait mode determines whether pump() uses select() to wait for the next event.
2022-01-05 20:55:48 -03:00
size_t pump ( WaitMode = WaitMode : : WaitForEvents ) ;
2019-05-18 08:39:21 -03:00
2022-12-30 11:17:52 -03:00
// Pump the event loop until some condition is met.
2021-09-25 14:32:14 -03:00
void spin_until ( Function < bool ( ) > ) ;
2024-05-17 21:14:06 -03:00
void deferred_invoke ( ESCAPING Function < void ( ) > ) ;
2022-12-30 11:17:52 -03:00
void wake ( ) ;
2019-04-10 12:30:34 -03:00
2022-12-30 11:17:52 -03:00
void quit ( int ) ;
2019-04-10 12:30:34 -03:00
2025-04-29 18:41:18 -03:00
bool was_exit_requested ( ) ;
2022-12-30 11:17:52 -03:00
// The registration functions act upon the current loop of the current thread.
2025-08-11 06:45:39 -03:00
static intptr_t register_timer ( EventReceiver & , int milliseconds , bool should_reload ) ;
2024-02-18 02:11:38 -03:00
static void unregister_timer ( intptr_t timer_id ) ;
2019-04-10 12:30:34 -03:00
2020-02-02 08:34:39 -03:00
static void register_notifier ( Badge < Notifier > , Notifier & ) ;
static void unregister_notifier ( Badge < Notifier > , Notifier & ) ;
2019-04-10 12:30:34 -03:00
2024-05-17 21:14:06 -03:00
static int register_signal ( int signo , ESCAPING Function < void ( int ) > handler ) ;
2020-07-06 18:48:02 -03:00
static void unregister_signal ( int handler_id ) ;
2025-11-22 20:02:26 -03:00
// Invokes the specified handler when the process exits
static void register_process ( pid_t pid , ESCAPING Function < void ( pid_t ) > exit_handler ) ;
static void unregister_process ( pid_t pid ) ;
2023-07-11 22:48:56 -03:00
static bool is_running ( ) ;
2022-12-30 11:17:52 -03:00
static EventLoop & current ( ) ;
2025-12-05 16:48:48 -03:00
static NonnullRefPtr < WeakEventLoopReference > current_weak ( ) ;
2022-12-30 11:17:52 -03:00
2023-04-25 11:53:07 -03:00
EventLoopImplementation & impl ( ) { return * m_impl ; }
2019-04-10 12:30:34 -03:00
private :
2023-04-24 07:25:14 -03:00
NonnullOwnPtr < EventLoopImplementation > m_impl ;
2025-12-05 16:48:48 -03:00
RefPtr < WeakEventLoopReference > m_weak ;
2026-02-17 10:23:39 -03:00
} ;
2020-02-02 08:34:39 -03:00
2025-12-05 16:48:48 -03:00
class StrongEventLoopReference ;
2025-12-04 14:12:06 -03:00
class CORE_API WeakEventLoopReference : public AtomicRefCounted < WeakEventLoopReference > {
2025-12-05 16:48:48 -03:00
public :
StrongEventLoopReference take ( ) ;
private :
friend class EventLoop ;
friend class StrongEventLoopReference ;
WeakEventLoopReference ( EventLoop & ) ;
void revoke ( ) ;
EventLoop * m_event_loop ;
2025-10-30 09:29:29 -03:00
Sync : : RWLock m_lock ;
2025-12-05 16:48:48 -03:00
} ;
2025-12-04 14:12:06 -03:00
class CORE_API StrongEventLoopReference {
2025-12-05 16:48:48 -03:00
public :
~ StrongEventLoopReference ( ) ;
bool is_alive ( ) const ;
operator bool ( ) const ;
EventLoop * operator * ( ) const ;
EventLoop * operator - > ( ) const ;
private :
friend class WeakEventLoopReference ;
StrongEventLoopReference ( WeakEventLoopReference & ) ;
WeakEventLoopReference * m_event_loop_weak ;
} ;
2025-12-04 14:12:06 -03:00
CORE_API void deferred_invoke ( ESCAPING Function < void ( ) > ) ;
2024-05-21 17:08:53 -03:00
2020-02-02 08:34:39 -03:00
}