mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 04:42: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. | ||||
|     CFSocketEnableCallBacks(socket, notification_type); | ||||
| 
 | ||||
|     Core::NotifierActivationEvent event(notifier.fd()); | ||||
|     Core::NotifierActivationEvent event(notifier.fd(), notifier.type()); | ||||
|     notifier.dispatch_event(event); | ||||
| 
 | ||||
|     // 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) | ||||
| { | ||||
|     Core::NotifierActivationEvent event(notifier.fd()); | ||||
|     Core::NotifierActivationEvent event(notifier.fd(), notifier.type()); | ||||
|     notifier.dispatch_event(event); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <AK/EnumBits.h> | ||||
| #include <AK/Function.h> | ||||
| #include <AK/Types.h> | ||||
| #include <AK/WeakPtr.h> | ||||
|  | @ -78,19 +79,30 @@ private: | |||
|     int m_timer_id; | ||||
| }; | ||||
| 
 | ||||
| enum class NotificationType { | ||||
|     None = 0, | ||||
|     Read = 1, | ||||
|     Write = 2, | ||||
| }; | ||||
| 
 | ||||
| AK_ENUM_BITWISE_OPERATORS(NotificationType); | ||||
| 
 | ||||
| class NotifierActivationEvent final : public Event { | ||||
| public: | ||||
|     explicit NotifierActivationEvent(int fd) | ||||
|     explicit NotifierActivationEvent(int fd, NotificationType type) | ||||
|         : Event(Event::NotifierActivation) | ||||
|         , m_fd(fd) | ||||
|         , m_type(type) | ||||
|     { | ||||
|     } | ||||
|     ~NotifierActivationEvent() = default; | ||||
| 
 | ||||
|     int fd() const { return m_fd; } | ||||
|     NotificationType type() const { return m_type; } | ||||
| 
 | ||||
| private: | ||||
|     int m_fd; | ||||
|     NotificationType m_type; | ||||
| }; | ||||
| 
 | ||||
| class ChildEvent final : public Event { | ||||
|  |  | |||
|  | @ -157,12 +157,10 @@ retry: | |||
|     add_fd_to_set(thread_data.wake_pipe_fds[0], read_fds); | ||||
| 
 | ||||
|     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); | ||||
|         if (notifier->type() == Notifier::Type::Write) | ||||
|         if (has_flag(notifier->type(), Notifier::Type::Write)) | ||||
|             add_fd_to_set(notifier->fd(), write_fds); | ||||
|         if (notifier->type() == Notifier::Type::Exceptional) | ||||
|             TODO(); | ||||
|     } | ||||
| 
 | ||||
|     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.
 | ||||
|     for (auto& notifier : thread_data.notifiers) { | ||||
|         if (notifier->type() == Notifier::Type::Read && FD_ISSET(notifier->fd(), &read_fds)) { | ||||
|             ThreadEventQueue::current().post_event(*notifier, make<NotifierActivationEvent>(notifier->fd())); | ||||
|         } | ||||
|         if (notifier->type() == Notifier::Type::Write && FD_ISSET(notifier->fd(), &write_fds)) { | ||||
|             ThreadEventQueue::current().post_event(*notifier, make<NotifierActivationEvent>(notifier->fd())); | ||||
|         } | ||||
|         auto type = NotificationType::None; | ||||
|         if (FD_ISSET(notifier->fd(), &read_fds)) | ||||
|             type |= NotificationType::Read; | ||||
|         if (FD_ISSET(notifier->fd(), &write_fds)) | ||||
|             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) | ||||
|         return; | ||||
|     if (enabled == m_is_enabled) | ||||
|         return; | ||||
|     m_is_enabled = enabled; | ||||
|     if (enabled) | ||||
|         Core::EventLoop::register_notifier({}, *this); | ||||
|     else | ||||
|  | @ -41,6 +44,18 @@ void Notifier::close() | |||
|     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) | ||||
| { | ||||
|     if (event.type() == Core::Event::NotifierActivation) { | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <AK/Function.h> | ||||
| #include <LibCore/Event.h> | ||||
| #include <LibCore/EventReceiver.h> | ||||
| 
 | ||||
| namespace Core { | ||||
|  | @ -15,12 +16,7 @@ class Notifier final : public EventReceiver { | |||
|     C_OBJECT(Notifier); | ||||
| 
 | ||||
| public: | ||||
|     enum class Type { | ||||
|         None, | ||||
|         Read, | ||||
|         Write, | ||||
|         Exceptional, | ||||
|     }; | ||||
|     using Type = NotificationType; | ||||
| 
 | ||||
|     virtual ~Notifier() override; | ||||
| 
 | ||||
|  | @ -32,7 +28,7 @@ public: | |||
| 
 | ||||
|     int fd() const { return m_fd; } | ||||
|     Type type() const { return m_type; } | ||||
|     void set_type(Type type) { m_type = type; } | ||||
|     void set_type(Type type); | ||||
| 
 | ||||
|     void event(Core::Event&) override; | ||||
| 
 | ||||
|  | @ -40,6 +36,7 @@ private: | |||
|     Notifier(int fd, Type type, EventReceiver* parent = nullptr); | ||||
| 
 | ||||
|     int m_fd { -1 }; | ||||
|     bool m_is_enabled { false }; | ||||
|     Type m_type { Type::None }; | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Klishch
						Dan Klishch