vn-verdnaturachat/ios/Pods/Flipper-Folly/folly/io/async/EventHandler.h

195 lines
6.0 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <cstddef>
#include <glog/logging.h>
#include <folly/io/async/EventBaseBackendBase.h>
#include <folly/io/async/EventUtil.h>
#include <folly/net/NetworkSocket.h>
#include <folly/portability/Event.h>
namespace folly {
class EventBase;
/**
* The EventHandler class is used to asynchronously wait for events on a file
* descriptor.
*
* Users that wish to wait on I/O events should derive from EventHandler and
* implement the handlerReady() method.
*/
class EventHandler {
public:
enum EventFlags {
NONE = 0,
READ = EV_READ,
WRITE = EV_WRITE,
READ_WRITE = (READ | WRITE),
PERSIST = EV_PERSIST,
// Temporary flag until EPOLLPRI is upstream on libevent.
#ifdef EV_PRI
PRI = EV_PRI,
#endif
};
/**
* Create a new EventHandler object.
*
* @param eventBase The EventBase to use to drive this event handler.
* This may be nullptr, in which case the EventBase must be
* set separately using initHandler() or attachEventBase()
* before the handler can be registered.
* @param fd The file descriptor that this EventHandler will
* monitor. This may be -1, in which case the file
* descriptor must be set separately using initHandler() or
* changeHandlerFD() before the handler can be registered.
*/
explicit EventHandler(
EventBase* eventBase = nullptr,
NetworkSocket fd = NetworkSocket());
EventHandler(const EventHandler&) = delete;
EventHandler& operator=(const EventHandler&) = delete;
/**
* EventHandler destructor.
*
* The event will be automatically unregistered if it is still registered.
*/
virtual ~EventHandler();
/**
* handlerReady() is invoked when the handler is ready.
*
* @param events A bitset indicating the events that are ready.
*/
virtual void handlerReady(uint16_t events) noexcept = 0;
/**
* Register the handler.
*
* If the handler is already registered, the registration will be updated
* to wait on the new set of events.
*
* @param events A bitset specifying the events to monitor.
* If the PERSIST bit is set, the handler will remain
* registered even after handlerReady() is called.
*
* @return Returns true if the handler was successfully registered,
* or false if an error occurred. After an error, the handler is
* always unregistered, even if it was already registered prior to
* this call to registerHandler().
*/
bool registerHandler(uint16_t events) {
return registerImpl(events, false);
}
/**
* Unregister the handler, if it is registered.
*/
void unregisterHandler();
/**
* Returns true if the handler is currently registered.
*/
bool isHandlerRegistered() const {
return event_.isEventRegistered();
}
/**
* Attach the handler to a EventBase.
*
* This may only be called if the handler is not currently attached to a
* EventBase (either by using the default constructor, or by calling
* detachEventBase()).
*
* This method must be invoked in the EventBase's thread.
*/
void attachEventBase(EventBase* eventBase);
/**
* Detach the handler from its EventBase.
*
* This may only be called when the handler is not currently registered.
* Once detached, the handler may not be registered again until it is
* re-attached to a EventBase by calling attachEventBase().
*
* This method must be called from the current EventBase's thread.
*/
void detachEventBase();
/**
* Change the file descriptor that this handler is associated with.
*
* This may only be called when the handler is not currently registered.
*/
void changeHandlerFD(NetworkSocket fd);
/**
* Attach the handler to a EventBase, and change the file descriptor.
*
* This method may only be called if the handler is not currently attached to
* a EventBase. This is primarily intended to be used to initialize
* EventHandler objects created using the default constructor.
*/
void initHandler(EventBase* eventBase, NetworkSocket fd);
/**
* Return the set of events that we're currently registered for.
*/
uint16_t getRegisteredEvents() const {
return (isHandlerRegistered()) ? (uint16_t)(event_.eb_ev_events()) : 0u;
}
/**
* Register the handler as an internal event.
*
* This event will not count as an active event for determining if the
* EventBase loop has more events to process. The EventBase loop runs
* only as long as there are active EventHandlers, however "internal" event
* handlers are not counted. Therefore this event handler will not prevent
* EventBase loop from exiting with no more work to do if there are no other
* non-internal event handlers registered.
*
* This is intended to be used only in very rare cases by the internal
* EventBase code. This API is not guaranteed to remain stable or portable
* in the future.
*/
bool registerInternalHandler(uint16_t events) {
return registerImpl(events, true);
}
bool isPending() const;
private:
bool registerImpl(uint16_t events, bool internal);
void ensureNotRegistered(const char* fn);
void setEventBase(EventBase* eventBase);
static void libeventCallback(libevent_fd_t fd, short events, void* arg);
EventBaseBackendBase::Event event_;
EventBase* eventBase_;
};
} // namespace folly