mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 09:52:44 +00:00 
			
		
		
		
	LibCore: Allow listening for multiple conditions using a single Notifier
While on it, implement currently unused Notifier::set_type correctly (but not efficiently) by re-registering Notifier in the EventLoop.
This commit is contained in:
		
							parent
							
								
									5d1657f57f
								
							
						
					
					
						commit
						77e4f0d7d8
					
				
					 6 changed files with 44 additions and 20 deletions
				
			
		|  | @ -106,7 +106,7 @@ static void socket_notifier(CFSocketRef socket, CFSocketCallBackType notificatio | ||||||
|     // before dispatching the event, which allows it to be triggered again. |     // before dispatching the event, which allows it to be triggered again. | ||||||
|     CFSocketEnableCallBacks(socket, notification_type); |     CFSocketEnableCallBacks(socket, notification_type); | ||||||
| 
 | 
 | ||||||
|     Core::NotifierActivationEvent event(notifier.fd()); |     Core::NotifierActivationEvent event(notifier.fd(), notifier.type()); | ||||||
|     notifier.dispatch_event(event); |     notifier.dispatch_event(event); | ||||||
| 
 | 
 | ||||||
|     // This manual process of enabling the callbacks also seems to require waking the event loop, |     // This manual process of enabling the callbacks also seems to require waking the event loop, | ||||||
|  |  | ||||||
|  | @ -118,7 +118,7 @@ bool EventLoopManagerQt::unregister_timer(int timer_id) | ||||||
| 
 | 
 | ||||||
| static void qt_notifier_activated(Core::Notifier& notifier) | static void qt_notifier_activated(Core::Notifier& notifier) | ||||||
| { | { | ||||||
|     Core::NotifierActivationEvent event(notifier.fd()); |     Core::NotifierActivationEvent event(notifier.fd(), notifier.type()); | ||||||
|     notifier.dispatch_event(event); |     notifier.dispatch_event(event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <AK/EnumBits.h> | ||||||
| #include <AK/Function.h> | #include <AK/Function.h> | ||||||
| #include <AK/Types.h> | #include <AK/Types.h> | ||||||
| #include <AK/WeakPtr.h> | #include <AK/WeakPtr.h> | ||||||
|  | @ -78,19 +79,30 @@ private: | ||||||
|     int m_timer_id; |     int m_timer_id; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | enum class NotificationType { | ||||||
|  |     None = 0, | ||||||
|  |     Read = 1, | ||||||
|  |     Write = 2, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | AK_ENUM_BITWISE_OPERATORS(NotificationType); | ||||||
|  | 
 | ||||||
| class NotifierActivationEvent final : public Event { | class NotifierActivationEvent final : public Event { | ||||||
| public: | public: | ||||||
|     explicit NotifierActivationEvent(int fd) |     explicit NotifierActivationEvent(int fd, NotificationType type) | ||||||
|         : Event(Event::NotifierActivation) |         : Event(Event::NotifierActivation) | ||||||
|         , m_fd(fd) |         , m_fd(fd) | ||||||
|  |         , m_type(type) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|     ~NotifierActivationEvent() = default; |     ~NotifierActivationEvent() = default; | ||||||
| 
 | 
 | ||||||
|     int fd() const { return m_fd; } |     int fd() const { return m_fd; } | ||||||
|  |     NotificationType type() const { return m_type; } | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|     int m_fd; |     int m_fd; | ||||||
|  |     NotificationType m_type; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class ChildEvent final : public Event { | class ChildEvent final : public Event { | ||||||
|  |  | ||||||
|  | @ -157,12 +157,10 @@ retry: | ||||||
|     add_fd_to_set(thread_data.wake_pipe_fds[0], read_fds); |     add_fd_to_set(thread_data.wake_pipe_fds[0], read_fds); | ||||||
| 
 | 
 | ||||||
|     for (auto& notifier : thread_data.notifiers) { |     for (auto& notifier : thread_data.notifiers) { | ||||||
|         if (notifier->type() == Notifier::Type::Read) |         if (has_flag(notifier->type(), Notifier::Type::Read)) | ||||||
|             add_fd_to_set(notifier->fd(), read_fds); |             add_fd_to_set(notifier->fd(), read_fds); | ||||||
|         if (notifier->type() == Notifier::Type::Write) |         if (has_flag(notifier->type(), Notifier::Type::Write)) | ||||||
|             add_fd_to_set(notifier->fd(), write_fds); |             add_fd_to_set(notifier->fd(), write_fds); | ||||||
|         if (notifier->type() == Notifier::Type::Exceptional) |  | ||||||
|             TODO(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool has_pending_events = ThreadEventQueue::current().has_pending_events(); |     bool has_pending_events = ThreadEventQueue::current().has_pending_events(); | ||||||
|  | @ -257,12 +255,14 @@ try_select_again: | ||||||
| 
 | 
 | ||||||
|     // Handle file system notifiers by making them normal events.
 |     // Handle file system notifiers by making them normal events.
 | ||||||
|     for (auto& notifier : thread_data.notifiers) { |     for (auto& notifier : thread_data.notifiers) { | ||||||
|         if (notifier->type() == Notifier::Type::Read && FD_ISSET(notifier->fd(), &read_fds)) { |         auto type = NotificationType::None; | ||||||
|             ThreadEventQueue::current().post_event(*notifier, make<NotifierActivationEvent>(notifier->fd())); |         if (FD_ISSET(notifier->fd(), &read_fds)) | ||||||
|         } |             type |= NotificationType::Read; | ||||||
|         if (notifier->type() == Notifier::Type::Write && FD_ISSET(notifier->fd(), &write_fds)) { |         if (FD_ISSET(notifier->fd(), &write_fds)) | ||||||
|             ThreadEventQueue::current().post_event(*notifier, make<NotifierActivationEvent>(notifier->fd())); |             type |= NotificationType::Write; | ||||||
|         } |         type &= notifier->type(); | ||||||
|  |         if (type != NotificationType::None) | ||||||
|  |             ThreadEventQueue::current().post_event(*notifier, make<NotifierActivationEvent>(notifier->fd(), type)); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -27,6 +27,9 @@ void Notifier::set_enabled(bool enabled) | ||||||
| { | { | ||||||
|     if (m_fd < 0) |     if (m_fd < 0) | ||||||
|         return; |         return; | ||||||
|  |     if (enabled == m_is_enabled) | ||||||
|  |         return; | ||||||
|  |     m_is_enabled = enabled; | ||||||
|     if (enabled) |     if (enabled) | ||||||
|         Core::EventLoop::register_notifier({}, *this); |         Core::EventLoop::register_notifier({}, *this); | ||||||
|     else |     else | ||||||
|  | @ -41,6 +44,18 @@ void Notifier::close() | ||||||
|     m_fd = -1; |     m_fd = -1; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Notifier::set_type(Type type) | ||||||
|  | { | ||||||
|  |     if (m_is_enabled) { | ||||||
|  |         // FIXME: Directly communicate intent to the EventLoop.
 | ||||||
|  |         set_enabled(false); | ||||||
|  |         m_type = type; | ||||||
|  |         set_enabled(true); | ||||||
|  |     } else { | ||||||
|  |         m_type = type; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Notifier::event(Core::Event& event) | void Notifier::event(Core::Event& event) | ||||||
| { | { | ||||||
|     if (event.type() == Core::Event::NotifierActivation) { |     if (event.type() == Core::Event::NotifierActivation) { | ||||||
|  |  | ||||||
|  | @ -7,6 +7,7 @@ | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include <AK/Function.h> | #include <AK/Function.h> | ||||||
|  | #include <LibCore/Event.h> | ||||||
| #include <LibCore/EventReceiver.h> | #include <LibCore/EventReceiver.h> | ||||||
| 
 | 
 | ||||||
| namespace Core { | namespace Core { | ||||||
|  | @ -15,12 +16,7 @@ class Notifier final : public EventReceiver { | ||||||
|     C_OBJECT(Notifier); |     C_OBJECT(Notifier); | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     enum class Type { |     using Type = NotificationType; | ||||||
|         None, |  | ||||||
|         Read, |  | ||||||
|         Write, |  | ||||||
|         Exceptional, |  | ||||||
|     }; |  | ||||||
| 
 | 
 | ||||||
|     virtual ~Notifier() override; |     virtual ~Notifier() override; | ||||||
| 
 | 
 | ||||||
|  | @ -32,7 +28,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     int fd() const { return m_fd; } |     int fd() const { return m_fd; } | ||||||
|     Type type() const { return m_type; } |     Type type() const { return m_type; } | ||||||
|     void set_type(Type type) { m_type = type; } |     void set_type(Type type); | ||||||
| 
 | 
 | ||||||
|     void event(Core::Event&) override; |     void event(Core::Event&) override; | ||||||
| 
 | 
 | ||||||
|  | @ -40,6 +36,7 @@ private: | ||||||
|     Notifier(int fd, Type type, EventReceiver* parent = nullptr); |     Notifier(int fd, Type type, EventReceiver* parent = nullptr); | ||||||
| 
 | 
 | ||||||
|     int m_fd { -1 }; |     int m_fd { -1 }; | ||||||
|  |     bool m_is_enabled { false }; | ||||||
|     Type m_type { Type::None }; |     Type m_type { Type::None }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Klishch
						Dan Klishch