📄 rvselect.c
字号:
#if (RV_OS_TYPE == RV_OS_TYPE_NUCLEUS)
*error = (NU_Is_Connected(*osFd) != NU_TRUE);
#else
if (RvSocketGetLastError(osFd, &lastError) != RV_OK)
*error = RV_TRUE;
if (lastError != 0)
*error = RV_TRUE;
#endif
}
return RV_OK;
}
#endif /* select(), poll(), /dev/poll */
#if (RV_SELECT_TYPE == RV_SELECT_SELECT)
/* todo: comment the following 4 functions */
RvStatus RvSelectGetSelectFds(
IN RvSelectEngine* selectEngine,
OUT int* numFds,
OUT fd_set* rdSet,
OUT fd_set* wrSet)
{
*numFds = selectEngine->maxFdInSelect + 1;
/* todo: these memcpy might not work in all operating systems! */
if (rdSet != NULL)
memcpy(rdSet, &selectEngine->rdSet, sizeof(fd_set));
if (wrSet != NULL)
memcpy(wrSet, &selectEngine->wrSet, sizeof(fd_set));
return RV_OK;
}
RvStatus RvSelectHandleSelectFds(
IN RvSelectEngine* selectEngine,
IN fd_set* rdSet,
IN fd_set* wrSet,
IN int numFds,
IN int numEvents)
{
/* Seems like we'll have to look for these events */
RvSocket fd;
RvBool hasRead, hasWrite;
if (numEvents < 0)
return RvSelectErrorCode(RV_ERROR_UNKNOWN);
if (numEvents == 0)
return RV_OK;
for (fd = numFds; fd >= 0; fd--)
{
hasRead = FD_ISSET(fd, rdSet);
hasWrite = FD_ISSET(fd, wrSet);
if (hasRead || hasWrite)
{
/* We've got an event */
RvSelectEvents selectEvent = 0;
RvSelectFd* fdNode = fdBucketHashFind(selectEngine, fd);
if ((fdNode != NULL) && (fdNode->callback != NULL))
{
RvBool error = RV_FALSE;
if (hasRead)
selectEvent = RV_SELECT_READ;
if (hasWrite)
selectEvent = RV_SELECT_WRITE;
/* Translate events to the richer set of events */
RvSelectEventsToUser(&fdNode->fd, fdNode->events, &selectEvent, &error);
/* Make sure we're actually waiting for this event */
if ((fdNode->events & selectEvent) != 0)
{
RvSelectLogDebug((&rvSelectLogSource,
"Occured event: fd=%d,event=%s,error=%d",
fdNode->fd, fdGetEventStr(selectEvent), error));
/* Tell the user about this event */
fdNode->callback(selectEngine, fdNode, selectEvent, error);
}
}
if (hasRead) numEvents--;
if (hasWrite) numEvents--;
if (numEvents == 0)
break; /* No more events to look for */
}
}
return RV_OK;
}
#endif /* (RV_SELECT_TYPE == RV_SELECT_SELECT) */
#if ((RV_SELECT_TYPE == RV_SELECT_POLL) || (RV_SELECT_TYPE == RV_SELECT_DEVPOLL))
RvStatus RvSelectGetPollFds(
IN RvSelectEngine* selectEngine,
INOUT int* maxFds,
OUT struct pollfd* pollFdSet)
{
int engineMaxFds;
#if (RV_SELECT_TYPE == RV_SELECT_POLL)
engineMaxFds = (int)selectEngine->maxFdInPoll;
#elif (RV_SELECT_TYPE == RV_SELECT_DEVPOLL)
engineMaxFds = (int)selectEngine->maxFdInDevPoll;
#endif
if (*maxFds < engineMaxFds)
return RvSelectErrorCode(RV_ERROR_OUTOFRANGE);
*maxFds = engineMaxFds;
memcpy(pollFdSet, selectEngine->fdArray, sizeof(struct pollfd) * engineMaxFds);
return RV_OK;
}
RvStatus RvSelectHandlePollFds(
IN RvSelectEngine* selectEngine,
IN struct pollfd* pollFdSet,
IN int numFds,
IN int numEvents)
{
struct pollfd* pollFdElem;
RvUint32 i;
RvSelectFd* fdNode;
if (numEvents < 0)
return RvSelectErrorCode(RV_ERROR_UNKNOWN);
if (numEvents == 0)
return RV_OK;
pollFdElem = pollFdSet;
for (i = 0; i < numFds; i++)
{
if (pollFdElem->revents != 0)
{
/* Find out which fd are we dealing with */
fdNode = fdBucketHashFind(selectEngine, pollFdElem->fd);
if ((fdNode != NULL) && (fdNode->callback != NULL))
{
RvSelectEvents selectEvent = 0;
RvBool error = RV_FALSE;
/* Get read/write/error from the returned events */
if ((pollFdElem->revents & POLLIN) || (pollFdElem->revents & POLLHUP))
selectEvent |= RV_SELECT_READ;
if (pollFdElem->revents & POLLOUT)
selectEvent |= RV_SELECT_WRITE;
if (pollFdElem->revents & POLLERR)
error = RV_TRUE;
/* Translate events to the richer set of events */
RvSelectEventsToUser(&fdNode->fd, fdNode->events, &selectEvent, &error);
/* Make sure we're actually waiting for this event */
if ((fdNode->events & selectEvent) != 0)
{
RvInt32 lastError = 0;
if (error == RV_TRUE)
{
RvSocketGetLastError(&fdNode->fd, &lastError);
if (lastError == 0)
lastError = 1;
}
RvSelectLogDebug((&rvSelectLogSource,
"Occured event: fd=%d,event=%s,error=%d",
fdNode->fd, fdGetEventStr(selectEvent), lastError));
/* Tell the user about this event */
fdNode->callback(selectEngine, fdNode, selectEvent, error);
}
}
else
{
RvSelectLogExcep((&rvSelectLogSource,
"Event on something that we're not waiting for (fd=%d)", pollFdElem->fd));
}
/* We've got one less result to look for */
numEvents--;
if (numEvents == 0)
break;
}
/* Get the next one in array */
pollFdElem++;
}
return RV_OK;
}
#endif /* ((RV_SELECT_TYPE == RV_SELECT_POLL) || (RV_SELECT_TYPE == RV_SELECT_DEVPOLL)) */
/********************************************************************************************
*
* Public functions
*
********************************************************************************************/
RvStatus RvSelectInit(void)
{
#if (RV_SELECT_TYPE == RV_SELECT_WIN32_WSA)
{
WNDCLASS wc;
WSADATA wsaData;
/* Start Windows Sockets */
WORD winsockVersion = MAKEWORD(2, 2);
if (WSAStartup(winsockVersion, &wsaData) != 0)
return RvSelectErrorCode(RV_ERROR_UNKNOWN);
/* Create a window class for network events */
memset(&wc, 0, sizeof(WNDCLASS));
wc.lpfnWndProc = rvSelectWinFunc;
wc.hInstance = NULL;
wc.lpszClassName = RV_FD_EVENTS_CLASS;
if (!RegisterClass(&wc))
return RvSelectErrorCode(RV_ERROR_UNKNOWN);
return RV_OK;
}
#elif (RV_SELECT_TYPE == RV_SELECT_WIN32_COMPLETION)
{
WSADATA wsaData;
/* Start Windows Sockets */
WORD winsockVersion = MAKEWORD(2, 2);
if (WSAStartup(winsockVersion, &wsaData) != 0)
return RvSelectErrorCode(RV_ERROR_UNKNOWN);
return RV_OK;
}
#elif (RV_SELECT_TYPE == RV_SELECT_SELECT)
rvSelectMaxDescriptors = SELECT_FD_SETSIZE;
return RV_OK;
#elif ((RV_SELECT_TYPE == RV_SELECT_POLL) || (RV_SELECT_TYPE == RV_SELECT_DEVPOLL))
/* Find out the limits posed by the OS on the amount of file descriptors */
{
struct rlimit r;
if (getrlimit(RLIMIT_NOFILE, &r) < 0)
return RvSelectErrorCode(RV_SELECT_ERROR_GETRLIMIT);
rvSelectMaxDescriptors = r.rlim_cur;
}
return RV_OK;
#endif
}
RvStatus RvSelectEnd(void)
{
RvStatus ret = RV_OK;
#if (RV_SELECT_TYPE == RV_SELECT_WIN32_WSA)
if (WSACleanup() != 0)
ret = RvSelectErrorCode(RV_ERROR_UNKNOWN);
if (UnregisterClass(RV_FD_EVENTS_CLASS, NULL/*hInstance*/) == 0)
ret = RvSelectErrorCode(RV_ERROR_UNKNOWN);
#elif (RV_SELECT_TYPE == RV_SELECT_WIN32_COMPLETION)
if (WSACleanup() != 0)
return RvSelectErrorCode(RV_ERROR_UNKNOWN);
#elif (RV_SELECT_TYPE == RV_SELECT_SELECT)
#elif (RV_SELECT_TYPE == RV_SELECT_POLL)
#elif (RV_SELECT_TYPE == RV_SELECT_DEVPOLL)
#endif
return ret;
}
RVCOREAPI RvStatus RVCALLCONV RvSelectSetMaxFileDescriptors(IN RvUint32 maxFileDescriptors)
{
#if ((RV_SELECT_TYPE == RV_SELECT_SELECT) || \
(RV_SELECT_TYPE == RV_SELECT_POLL) || \
(RV_SELECT_TYPE == RV_SELECT_DEVPOLL))
rvSelectMaxDescriptors = maxFileDescriptors;
return RV_OK;
#else
return RvSelectErrorCode(RV_ERROR_NOTSUPPORTED);
#endif
}
RVCOREAPI RvUint32 RVCALLCONV RvSelectGetMaxFileDescriptors(void)
{
#if ((RV_SELECT_TYPE == RV_SELECT_SELECT) || \
(RV_SELECT_TYPE == RV_SELECT_POLL) || \
(RV_SELECT_TYPE == RV_SELECT_DEVPOLL))
return rvSelectMaxDescriptors;
#else
return 0;
#endif
}
/********************************************************************************************
* RvSelectConstruct
*
* purpose : Create a new file descriptor engine
* input : selectEngine - Events engine to construct
* maxHashSize - Hash size used by the engine
*
* output : None
* return : RV_OK on success, other on failure
********************************************************************************************/
RVCOREAPI
RvStatus RVCALLCONV RvSelectConstruct(
OUT RvSelectEngine* selectEngine,
IN RvUint32 maxHashSize)
{
RvStatus status = RV_OK;
status = RvLogSourceConstruct(RvLogGet(), &rvSelectLogSource, RV_LOG_LIBCODE_CCORE,
"SELECT", "File Descriptors Events Engine");
if (status != RV_OK)
return status;
memset(selectEngine, 0, sizeof(RvSelectEngine));
status = RvLockConstruct(&selectEngine->lock);
if (status != RV_OK)
return status;
/* Create a bucket hash if needed */
status = fdBucketHashConstruct(selectEngine, maxHashSize);
if (status != RV_OK)
{
RvLockDestruct(&selectEngine->lock);
return status;
}
#if (RV_SELECT_TYPE == RV_SELECT_WIN32_WSA)
{
/* Create a widnow to use for network events */
char windowName[30];
if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
GetCurrentProcess(), &selectEngine->threadHandle,
DUPLICATE_SAME_ACCESS, FALSE, THREAD_ALL_ACCESS) == 0)
{
/* Got an error */
status = RvSelectErrorCode(RV_ERROR_UNKNOWN);
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -