10#ifdef RESIP_POLL_IMPL_EPOLL
11# include <sys/epoll.h>
13#if defined(RESIP_POLL_IMPL_POLL) && !defined(WIN32)
18#define RESIPROCATE_SUBSYSTEM Subsystem::SIP
31 mPollGrp(grp), mPollSocket(fd), mPollHandle(0)
78 ErrLog(<<
"Exception thrown for FdPollItem: " << e);
166#define IMPL_FDSET_IdxToHandle(idx) ((FdPollItemHandle)( ((char*)0) + ((idx)+1) ))
167#define IMPL_FDSET_HandleToIdx(handle) ( ((char*)(handle)) - ((char*)0) - 1)
170 : mLiveHeadIdx(-1), mFreeHeadIdx(-1)
177 for (itemIdx=0; itemIdx <
mItems.size(); itemIdx++)
182 CritLog(<<
"FdPollItem idx="<<itemIdx
183 <<
" not deleted prior to destruction");
204 size_t newsz = 10+useIdx + useIdx/3;
211 for (itemIdx=useIdx+1; itemIdx < newsz; itemIdx++)
340 while ( (itemIdx = *prevIdxRef) != (
size_t)-1 )
369 bool didsomething =
false;
377 while ( (itemIdx = *prevIdxRef) != (
size_t)-1 )
399 prevIdxRef = &
mItems[itemIdx].mNextIdx;
413#ifdef RESIP_POLL_IMPL_POLL
418class FdPollItemPollInfo
428 unsigned int mFdPollCacheIndex;
437 virtual const char* getImplName()
const {
return "poll"; }
438 virtual ImplType getImplType()
const {
return PollImpl; }
444 virtual bool waitAndProcess(
int ms=0);
447 virtual int getEPollFd()
const {
return -1; }
448 virtual void buildFdSet(
FdSet& fdSet);
449 virtual bool processFdSet(
FdSet& fdset);
452 typedef std::map<Socket, FdPollItemPollInfo> FdPollItemPollInfoMap;
453 FdPollItemPollInfoMap mItems;
460 std::vector<pollfd> mPollFdCache;
461 std::vector<pollfd> mPollFds;
466#define IMPL_POLL_FdToHandle(fd) ((FdPollItemHandle)( ((char*)0) + ((fd)+1) ))
467#define IMPL_POLL_HandleToFd(handle) ( ((char*)(handle)) - ((char*)0) - 1)
471FdPollImplPoll::FdPollImplPoll()
474 mPollFdCache.reserve(sz);
475 mPollFds.reserve(sz);
478FdPollImplPoll::~FdPollImplPoll()
480 FdPollItemPollInfoMap::iterator it;
481 for(it = mItems.begin(); it != mItems.end(); it++)
483 CritLog(<<
"FdPollItem fd=" << it->first <<
" not deleted prior to destruction");
487static inline unsigned short
488CvtPollToUsrMask(
unsigned long sysMask)
490 unsigned usrMask = 0;
491 if(sysMask & POLLIN) usrMask |=
FPEM_Read;
500static inline unsigned long
501CvtUsrToPollMask(
unsigned short usrMask)
503 unsigned long sysMask = 0;
504 if(usrMask &
FPEM_Read) sysMask |= POLLIN;
517 FdPollItemPollInfo& info = mItems[fd];
519 info.mItemObj = item;
520 info.mFdPollCacheIndex = (
unsigned int)mPollFdCache.size();
524 pollFD.events = (short)CvtUsrToPollMask(newMask);
525 mPollFdCache.push_back(pollFD);
527 return IMPL_POLL_FdToHandle(fd);
533 int fd = (int)IMPL_POLL_HandleToFd(handle);
536 FdPollItemPollInfoMap::iterator it = mItems.find(fd);
537 if(it != mItems.end())
539 FdPollItemPollInfo& info = it->second;
545 mPollFdCache[info.mFdPollCacheIndex].events = (short)CvtUsrToPollMask(newMask);
553 int fd = (int)IMPL_POLL_HandleToFd(handle);
557 FdPollItemPollInfoMap::iterator it = mItems.find(fd);
558 if(it != mItems.end())
560 FdPollItemPollInfo& info = it->second;
566 if(mPollFdCache.size() > 1)
570 size_t lastCacheIndex = mPollFdCache.size() - 1;
573 mItems[mPollFdCache[lastCacheIndex].fd].mFdPollCacheIndex = info.mFdPollCacheIndex;
576 mPollFdCache[info.mFdPollCacheIndex] = mPollFdCache[mPollFdCache.size() - 1];
579 mPollFdCache.pop_back();
587FdPollImplPoll::waitAndProcess(
int ms)
593 mPollFds = mPollFdCache;
597 if(mPollFds.size() == 0)
603 bool didsomething=
false;
605 pollfd *pollFDArray = &(mPollFds.front());
607 int numReadyFDs = WSAPoll(pollFDArray, (ULONG)mPollFds.size(), ms);
609 int numReadyFDs = poll(pollFDArray, mPollFds.size(), ms);
611 if ( numReadyFDs < 0 )
622 if ( numReadyFDs==0 )
630 for (
size_t index = 0; index < mPollFds.size() && numReadyFDs > 0; index++)
632 int revents = pollFDArray[index].revents;
638 FdPollItemPollInfoMap::iterator it = mItems.find(pollFDArray[index].fd);
639 if(it != mItems.end())
642 processItem(pdPollItem, CvtPollToUsrMask(revents));
653FdPollImplPoll::buildFdSet(
FdSet& fdset)
655 CritLog(<<
"buildFdSet failed - API not supported for FdPollImplPoll.");
660FdPollImplPoll::processFdSet(
FdSet& fdset)
662 CritLog(<<
"processFdSet failed - API not supported for FdPollImplPoll.");
677#ifdef RESIP_POLL_IMPL_EPOLL
688 virtual const char* getImplName()
const {
return "epoll"; }
689 virtual ImplType getImplType()
const {
return EPollImpl; }
697 virtual bool waitAndProcess(
int ms=0);
700 virtual int getEPollFd()
const {
return mEPollFd; }
701 virtual void buildFdSet(
FdSet& fdSet);
702 virtual bool processFdSet(
FdSet& fdset);
705 void killCache(
Socket fd);
706 bool epollWait(
int ms);
708 std::vector<FdPollItemIf*> mItems;
716 std::vector<struct epoll_event> mEvCache;
724#define IMPL_EPOLL_FdToHandle(fd) ((FdPollItemHandle)( ((char*)0) + ((fd)+1) ))
725#define IMPL_EPOLL_HandleToFd(handle) ( ((char*)(handle)) - ((char*)0) - 1)
727FdPollImplEpoll::FdPollImplEpoll() :
731 if ( (mEPollFd = epoll_create(sz)) < 0 )
737 mEvCacheCur = mEvCacheLen = 0;
740FdPollImplEpoll::~FdPollImplEpoll()
744 for (itemIdx=0; itemIdx < mItems.size(); itemIdx++)
749 CritLog(<<
"FdPollItem idx="<<itemIdx
750 <<
" not deleted prior to destruction");
759static inline unsigned short
760CvtSysToUsrMask(
unsigned long sysMask)
762 unsigned usrMask = 0;
763 if(sysMask & EPOLLIN) usrMask |=
FPEM_Read;
771static inline unsigned long
772CvtUsrToSysMask(
unsigned short usrMask)
774 unsigned long sysMask = 0;
775 if(usrMask &
FPEM_Read) sysMask |= EPOLLIN;
777 if(usrMask &
FPEM_Edge) sysMask |= EPOLLET;
786 if (mItems.size() <= (
unsigned)fd)
788 unsigned newsz = fd+1;
792 mItems.resize(newsz);
797 struct epoll_event ev;
798 memset(&ev, 0,
sizeof(ev));
799 ev.events = CvtUsrToSysMask(newMask);
801 if (epoll_ctl(mEPollFd, EPOLL_CTL_ADD, fd, &ev) < 0)
806 return IMPL_EPOLL_FdToHandle(fd);
812 int fd = IMPL_EPOLL_HandleToFd(handle);
816 struct epoll_event ev;
817 memset(&ev, 0,
sizeof(ev));
818 ev.events = CvtUsrToSysMask(newMask);
820 if (epoll_ctl(mEPollFd, EPOLL_CTL_MOD, fd, &ev) < 0)
830 int fd = IMPL_EPOLL_HandleToFd(handle);
835 if (epoll_ctl(mEPollFd, EPOLL_CTL_DEL, fd, NULL) < 0)
868FdPollImplEpoll::killCache(
int fd)
871 for (ne=mEvCacheCur; ne < mEvCacheLen; ne++)
873 if ( mEvCache[ne].data.fd == fd )
882FdPollImplEpoll::waitAndProcess(
int ms)
886 return epollWait(ms);
890FdPollImplEpoll::buildFdSet(
FdSet& fdset)
892 int fd = getEPollFd();
900FdPollImplEpoll::processFdSet(
FdSet& fdset)
902 int fd = getEPollFd();
911FdPollImplEpoll::epollWait(
int waitMs)
914 bool didsomething=
false;
917 int nfds = epoll_wait(mEPollFd, &mEvCache.front(), mEvCache.size(), waitMs);
923 DebugLog(<<
"epoll_wait() broken by EINTR");
935 maybeMore = ( ((unsigned)nfds)==mEvCache.size()) ? 1 : 0;
937 for (ne=0; ne < nfds; ne++)
939 int fd = mEvCache[ne].data.fd;
944 int sysEvtMask = mEvCache[ne].events;
954 processItem(item, CvtSysToUsrMask(sysEvtMask));
974 if ( implName==0 || implName[0]==0 || strcmp(implName,
"event")==0 )
976#ifdef RESIP_POLL_IMPL_EPOLL
977 if ( implName==0 || strcmp(implName,
"epoll")==0 )
979 return new FdPollImplEpoll();
982#ifdef RESIP_POLL_IMPL_POLL
983 if ( implName==0 || strcmp(implName,
"poll")==0 )
985 return new FdPollImplPoll();
988 if ( implName==0 || strcmp(implName,
"fdset")==0 )
1001#ifdef RESIP_POLL_IMPL_EPOLL
1002 #ifdef RESIP_POLL_IMPL_POLL
1003 return "event|epoll|fdset|poll";
1005 return "event|epoll|fdset";
1008 #ifdef RESIP_POLL_IMPL_POLL
1009 return "event|fdset|poll";
1011 return "event|fdset";
#define IMPL_FDSET_HandleToIdx(handle)
#define IMPL_FDSET_IdxToHandle(idx)
#define resip_assert(x)
This file needs to work for both C and C++ code.
The abstract base-class for all exceptions thrown by resip code.
void processItem(FdPollItemIf *item, FdPollEventMask mask)
static const char * getImplList()
Return candidate impl names with vertical bar (|) between them Intended for help messages.
static FdPollGrp * create(const char *implName=NULL)
factory
virtual FdPollItemHandle addPollItem(Socket sock, FdPollEventMask newMask, FdPollItemIf *item)=0
virtual int getEPollFd() const
get the epoll-fd (epoll_create()) This is fd (type int), not Socket.
virtual void delPollItem(FdPollItemHandle handle)=0
virtual ImplType getImplType() const
void killCache(Socket fd)
There is a boundary case:
virtual bool waitAndProcess(int ms=0)
Wait at most {ms} milliseconds.
virtual FdPollItemHandle addPollItem(Socket fd, FdPollEventMask newMask, FdPollItemIf *item)
virtual void delPollItem(FdPollItemHandle handle)
std::vector< FdPollItemFdSetInfo > mItems
virtual void buildFdSet(FdSet &fdSet)
virtual bool processFdSet(FdSet &fdset)
virtual const char * getImplName() const
virtual void modPollItem(FdPollItemHandle handle, FdPollEventMask newMask)
FdPollItemHandle mPollHandle
virtual ~FdPollItemBase()
FdPollItemBase(FdPollGrp *grp, Socket fd, FdPollEventMask mask)
virtual void processPollEvent(FdPollEventMask mask)=0
Called by PollGrp when activity is possible.
Object-oriented wrapper for your platform's file-descriptor set.
bool readyToWrite(Socket fd)
bool readyToRead(Socket fd)
void setExcept(Socket fd)
int selectMilliSeconds(unsigned long ms)
bool hasException(Socket fd)
dcm! – add UnusedChecking(_enum) below;
unsigned short FdPollEventMask
std::unique_lock< RecursiveMutex > RecursiveLock
struct FdPollItemFake * FdPollItemHandle
This is opaque type used to identify a particular Item.
std::string strError(int err)
std::recursive_mutex RecursiveMutex