rocksdb/thrift/lib/cpp/async/TEventHandler.h
Dhruba Borthakur 80c663882a Create leveldb server via Thrift.
Summary:
First draft.
Unit tests pass.

Test Plan: unit tests attached

Reviewers: heyongqiang

Reviewed By: heyongqiang

Differential Revision: https://reviews.facebook.net/D3969
2012-07-07 09:42:39 -07:00

183 lines
5.9 KiB
C++

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
#ifndef THRIFT_ASYNC_TEVENTHANDLER_H_
#define THRIFT_ASYNC_TEVENTHANDLER_H_ 1
#include "thrift/lib/cpp/thrift_config.h"
#include "thrift/lib/cpp/async/TEventUtil.h"
#include <boost/noncopyable.hpp>
#include <stddef.h>
namespace apache { namespace thrift { namespace async {
class TEventBase;
/**
* The TEventHandler class is used to asynchronously wait for events on a file
* descriptor.
*
* Users that wish to wait on I/O events should derive from TEventHandler and
* implement the handlerReady() method.
*/
class TEventHandler : private boost::noncopyable {
public:
enum EventFlags {
NONE = 0,
READ = EV_READ,
WRITE = EV_WRITE,
READ_WRITE = (READ | WRITE),
PERSIST = EV_PERSIST
};
/**
* Create a new TEventHandler object.
*
* @param eventBase The TEventBase to use to drive this event handler.
* This may be NULL, in which case the TEventBase must be
* set separately using initHandler() or attachEventBase()
* before the handler can be registered.
* @param fd The file descriptor that this TEventHandler 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 TEventHandler(TEventBase* eventBase = NULL, int fd = -1);
/**
* TEventHandler destructor.
*
* The event will be automatically unregistered if it is still registered.
*/
virtual ~TEventHandler();
/**
* handlerReady() is invoked when the handler is ready.
*
* @param events A bitset indicating the events that are ready.
*/
virtual void handlerReady(uint16_t events) THRIFT_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 TEventUtil::isEventRegistered(&event_);
}
/**
* Attach the handler to a TEventBase.
*
* This may only be called if the handler is not currently attached to a
* TEventBase (either by using the default constructor, or by calling
* detachEventBase()).
*
* This method must be invoked in the TEventBase's thread.
*/
void attachEventBase(TEventBase* eventBase);
/**
* Detach the handler from its TEventBase.
*
* 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 TEventBase by calling attachEventBase().
*
* This method must be called from the current TEventBase'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(int fd);
/**
* Attach the handler to a TEventBase, and change the file descriptor.
*
* This method may only be called if the handler is not currently attached to
* a TEventBase. This is primarily intended to be used to initialize
* TEventHandler objects created using the default constructor.
*/
void initHandler(TEventBase* eventBase, int fd);
/**
* Return the set of events that we're currently registered for.
*/
uint16_t getRegisteredEvents() const {
return (isHandlerRegistered()) ?
event_.ev_events : 0;
}
/**
* Register the handler as an internal event.
*
* This event will not count as an active event for determining if the
* TEventBase loop has more events to process. The TEventBase loop runs
* only as long as there are active TEventHandlers, however "internal" event
* handlers are not counted. Therefore this event handler will not prevent
* TEventBase 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
* TEventBase code. This API is not guaranteed to remain stable or portable
* in the future.
*/
bool registerInternalHandler(uint16_t events) {
return registerImpl(events, true);
}
private:
bool registerImpl(uint16_t events, bool internal);
void ensureNotRegistered(const char* fn);
static void libeventCallback(int fd, short events, void* arg);
struct event event_;
};
}}} // apache::thrift::async
#endif // THRIFT_ASYNC_TEVENTHANDLER_H_