| // Copyright 2022 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef QUICHE_QUIC_IO_QUIC_EVENT_LOOP_H_ | |
| #define QUICHE_QUIC_IO_QUIC_EVENT_LOOP_H_ | |
| #include <cstdint> | |
| #include <memory> | |
| #include "absl/base/attributes.h" | |
| #include "quiche/quic/core/io/socket.h" | |
| #include "quiche/quic/core/quic_alarm_factory.h" | |
| #include "quiche/quic/core/quic_clock.h" | |
| #include "quiche/quic/core/quic_time.h" | |
| namespace quic { | |
| // A bitmask indicating a set of I/O events. | |
| using QuicSocketEventMask = uint8_t; | |
| inline constexpr QuicSocketEventMask kSocketEventReadable = 0x01; | |
| inline constexpr QuicSocketEventMask kSocketEventWritable = 0x02; | |
| inline constexpr QuicSocketEventMask kSocketEventError = 0x04; | |
| class QuicEventLoop; | |
| // A listener associated with a file descriptor. | |
| class QuicSocketEventListener { | |
| public: | |
| virtual ~QuicSocketEventListener() = default; | |
| virtual void OnSocketEvent(QuicEventLoop* event_loop, SocketFd fd, | |
| QuicSocketEventMask events) = 0; | |
| }; | |
| // An abstraction for an event loop that can handle alarms and notify the | |
| // listener about I/O events occuring to the registered UDP sockets. | |
| // | |
| // Note on error handling: while most of the methods below return a boolean to | |
| // indicate whether the operation has succeeded or not, some will QUIC_BUG | |
| // instead. | |
| class QuicEventLoop { | |
| public: | |
| virtual ~QuicEventLoop() = default; | |
| // Indicates whether the event loop implementation supports edge-triggered | |
| // notifications. If true, all of the events are permanent and are notified | |
| // as long as they are registered. If false, whenever an event is triggered, | |
| // the event registration is unset and has to be re-armed using RearmSocket(). | |
| virtual bool SupportsEdgeTriggered() const = 0; | |
| // Watches for all of the requested |events| that occur on the |fd| and | |
| // notifies the |listener| about them. |fd| must not be already registered; | |
| // if it is, the function returns false. The |listener| must be alive for as | |
| // long as it is registered. | |
| [[nodiscard]] virtual bool RegisterSocket( | |
| SocketFd fd, QuicSocketEventMask events, | |
| QuicSocketEventListener* listener) = 0; | |
| // Removes the listener associated with |fd|. Returns false if the listener | |
| // is not found. | |
| [[nodiscard]] virtual bool UnregisterSocket(SocketFd fd) = 0; | |
| // Adds |events| to the list of the listened events for |fd|, given that |fd| | |
| // is already registered. Must be only called if SupportsEdgeTriggered() is | |
| // false. | |
| [[nodiscard]] virtual bool RearmSocket(SocketFd fd, | |
| QuicSocketEventMask events) = 0; | |
| // Causes the |fd| to be notified of |events| on the next event loop iteration | |
| // even if none of the specified events has happened. | |
| [[nodiscard]] virtual bool ArtificiallyNotifyEvent( | |
| SocketFd fd, QuicSocketEventMask events) = 0; | |
| // Runs a single iteration of the event loop. The iteration will run for at | |
| // most |default_timeout|. | |
| virtual void RunEventLoopOnce(QuicTimeDelta default_timeout) = 0; | |
| // Returns an alarm factory that allows alarms to be scheduled on this event | |
| // loop. | |
| virtual std::unique_ptr<QuicAlarmFactory> CreateAlarmFactory() = 0; | |
| // Returns the clock that is used by the alarm factory that the event loop | |
| // provides. | |
| virtual const QuicClock* GetClock() = 0; | |
| // Returns true if the event loop implementation supports the `WakeUp()` call. | |
| virtual bool SupportsWakeUp() const = 0; | |
| // If `RunEventLoopOnce` is called in another thread, causes that call to exit | |
| // even if no event occurred. Thread-safe, unlike all other methods in the | |
| // class; the caller still has to ensure the lifetime safety across both of | |
| // the threads involved. | |
| // | |
| // `WakeUp()` is not supported in all implementations and/or platforms; the | |
| // caller has to call `SupportsWakeUp()` to ensure it is enabled. | |
| virtual void WakeUp() = 0; | |
| }; | |
| // A factory object for the event loop. Every implementation is expected to have | |
| // a static singleton instance. | |
| class QuicEventLoopFactory { | |
| public: | |
| virtual ~QuicEventLoopFactory() {} | |
| // Creates an event loop. Note that |clock| may be ignored if the event loop | |
| // implementation uses its own clock internally. | |
| virtual std::unique_ptr<QuicEventLoop> Create(QuicClock* clock) = 0; | |
| // A human-readable name of the event loop implementation used in diagnostics | |
| // output. | |
| virtual std::string GetName() const = 0; | |
| }; | |
| } // namespace quic | |
| #endif // QUICHE_QUIC_IO_QUIC_EVENT_LOOP_H_ |