📄 socketmgrlinux.cpp
字号:
/*
* Multiplatform Async Network Library
* Copyright (c) 2007 Burlex
*
* SocketMgr - epoll manager for Linux.
*
*/
#include "Network.h"
#ifdef CONFIG_USE_EPOLL
initialiseSingleton(SocketMgr);
void SocketMgr::AddSocket(Socket * s)
{
if(fds[s->GetFd()] != NULL)
{
//fds[s->GetFd()]->Delete();
//fds[s->GetFd()] = NULL;
s->Delete();
return;
}
fds[s->GetFd()] = s;
// Add epoll event based on socket activity.
struct epoll_event ev;
memset(&ev, 0, sizeof(epoll_event));
ev.events = (s->GetWriteBuffer().GetSize()) ? EPOLLOUT : EPOLLIN;
ev.events |= EPOLLET; /* use edge-triggered instead of level-triggered because we're using nonblocking sockets */
ev.data.fd = s->GetFd();
if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ev.data.fd, &ev))
Log.Warning("epoll", "Could not add event to epoll set on fd %u", ev.data.fd);
}
void SocketMgr::AddListenSocket(ListenSocketBase * s)
{
assert(listenfds[s->GetFd()] == 0);
listenfds[s->GetFd()] = s;
// Add epoll event based on socket activity.
struct epoll_event ev;
memset(&ev, 0, sizeof(epoll_event));
ev.events = EPOLLIN;
ev.events |= EPOLLET; /* use edge-triggered instead of level-triggered because we're using nonblocking sockets */
ev.data.fd = s->GetFd();
if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, ev.data.fd, &ev))
Log.Warning("epoll", "Could not add event to epoll set on fd %u", ev.data.fd);
}
void SocketMgr::RemoveSocket(Socket * s)
{
if(fds[s->GetFd()] != s)
{
Log.Warning("epoll", "Could not remove fd %u from the set due to it not existing?", s->GetFd());
return;
}
fds[s->GetFd()] = 0;
// Remove from epoll list.
struct epoll_event ev;
memset(&ev, 0, sizeof(epoll_event));
ev.data.fd = s->GetFd();
ev.events = EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLONESHOT;
if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, ev.data.fd, &ev))
Log.Warning("epoll", "Could not remove fd %u from epoll set, errno %u", s->GetFd(), errno);
}
void SocketMgr::CloseAll()
{
for(uint32 i = 0; i < SOCKET_HOLDER_SIZE; ++i)
if(fds[i] != NULL)
fds[i]->Delete();
}
void SocketMgr::SpawnWorkerThreads()
{
uint32 count = 1;
for(uint32 i = 0; i < count; ++i)
ThreadPool.ExecuteTask(new SocketWorkerThread());
}
bool SocketWorkerThread::run()
{
int fd_count;
Socket * ptr;
int i;
running = true;
SocketMgr * mgr = SocketMgr::getSingletonPtr();
while(running)
{
fd_count = epoll_wait(mgr->epoll_fd, events, THREAD_EVENT_SIZE, 5000);
for(i = 0; i < fd_count; ++i)
{
if(events[i].data.fd >= SOCKET_HOLDER_SIZE)
{
Log.Warning("epoll", "Requested FD that is too high (%u)", events[i].data.fd);
continue;
}
ptr = mgr->fds[events[i].data.fd];
if(ptr == NULL)
{
if( (ptr = ((Socket*)mgr->listenfds[events[i].data.fd])) != NULL )
((ListenSocketBase*)ptr)->OnAccept();
else
Log.Warning("epoll", "Returned invalid fd (no pointer) of FD %u", events[i].data.fd);
continue;
}
if(events[i].events & EPOLLHUP || events[i].events & EPOLLERR)
{
ptr->Disconnect();
continue;
}
else if(events[i].events & EPOLLIN)
{
ptr->ReadCallback(0); // Len is unknown at this point.
/* changing to written state? */
if(ptr->GetWriteBuffer().GetSize() && !ptr->HasSendLock() && ptr->IsConnected())
ptr->PostEvent(EPOLLOUT);
}
else if(events[i].events & EPOLLOUT)
{
ptr->BurstBegin(); // Lock receive mutex
ptr->WriteCallback(); // Perform actual send()
if(ptr->GetWriteBuffer().GetSize() > 0)
{
/* we don't have to do anything here. no more oneshots :) */
}
else
{
/* change back to a read event */
ptr->DecSendLock();
ptr->PostEvent(EPOLLIN);
}
ptr->BurstEnd(); // Unlock
}
}
}
return true;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -