Files
NE_YuR/openflow/include/click/selectset.hh

138 lines
2.9 KiB
C++

// -*- related-file-name: "../../lib/selectset.cc" -*-
#ifndef CLICK_SELECTSET_HH
#define CLICK_SELECTSET_HH 1
#if !CLICK_USERLEVEL
# error "<click/selectset.hh> only meaningful at user level"
#endif
#include <click/vector.hh>
#include <click/sync.hh>
#include <unistd.h>
#if !HAVE_ALLOW_SELECT && !HAVE_ALLOW_POLL && !HAVE_ALLOW_KQUEUE
# define HAVE_ALLOW_SELECT 1
#endif
#if defined(__APPLE__) && HAVE_ALLOW_SELECT && HAVE_ALLOW_POLL
// Apple's poll() is often broken
# undef HAVE_ALLOW_POLL
#endif
#if HAVE_POLL_H && HAVE_ALLOW_POLL
# include <poll.h>
#else
# undef HAVE_ALLOW_POLL
# if !HAVE_ALLOW_SELECT && !HAVE_ALLOW_KQUEUE
# error "poll is not supported on this system, try --enable-select"
# endif
#endif
#if !HAVE_SYS_EVENT_H || !HAVE_KQUEUE
# undef HAVE_ALLOW_KQUEUE
# if !HAVE_ALLOW_SELECT && !HAVE_ALLOW_POLL
# error "kqueue is not supported on this system, try --enable-select"
# endif
#endif
CLICK_DECLS
class Element;
class Router;
class RouterThread;
class SelectSet { public:
SelectSet();
~SelectSet();
void initialize();
int add_select(int fd, Element *element, int mask);
int remove_select(int fd, Element *element, int mask);
void run_selects(RouterThread *thread);
inline void wake_immediate() {
_wake_pipe_pending = true;
ignore_result(write(_wake_pipe[1], "", 1));
}
void kill_router(Router *router);
inline void fence();
private:
struct SelectorInfo {
Element *read;
Element *write;
int pollfd;
SelectorInfo()
: read(0), write(0), pollfd(-1)
{
}
};
int _wake_pipe[2];
volatile bool _wake_pipe_pending;
#if HAVE_ALLOW_KQUEUE
int _kqueue;
#endif
#if !HAVE_ALLOW_POLL
struct pollfd {
int fd;
int events;
};
fd_set _read_select_fd_set;
fd_set _write_select_fd_set;
int _max_select_fd;
#endif /* !HAVE_ALLOW_POLL */
Vector<struct pollfd> _pollfds;
Vector<SelectorInfo> _selinfo;
#if HAVE_MULTITHREAD
SimpleSpinlock _select_lock;
click_processor_t _select_processor;
#endif
void register_select(int fd, bool add_read, bool add_write);
void remove_pollfd(int pi, int event);
inline void call_selected(int fd, int mask) const;
inline bool post_select(RouterThread *thread, bool acquire);
#if HAVE_ALLOW_KQUEUE
void run_selects_kqueue(RouterThread *thread);
#endif
#if HAVE_ALLOW_POLL
void run_selects_poll(RouterThread *thread);
#else
void run_selects_select(RouterThread *thread);
#endif
inline void lock();
inline void unlock();
#if CLICK_DEBUG_MASTER || CLICK_DEBUG_SCHEDULING
friend class Master;
#endif
};
inline void
SelectSet::lock()
{
#if HAVE_MULTITHREAD
if (click_get_processor() != _select_processor)
_select_lock.acquire();
#endif
}
inline void
SelectSet::unlock()
{
#if HAVE_MULTITHREAD
if (click_get_processor() != _select_processor)
_select_lock.release();
#endif
}
inline void
SelectSet::fence()
{
lock();
unlock();
}
CLICK_ENDDECLS
#endif