mirror of
https://github.com/Relintai/rcpp_framework.git
synced 2024-11-14 04:57:21 +01:00
213 lines
4.6 KiB
C++
213 lines
4.6 KiB
C++
#pragma once
|
|
|
|
#include <brynet/base/Stack.hpp>
|
|
#include <brynet/net/SocketLibTypes.hpp>
|
|
#include <cassert>
|
|
#include <cstdlib>
|
|
|
|
#if defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
#include <poll.h>
|
|
#endif
|
|
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
const static int CHECK_READ_FLAG = (POLLIN | POLLRDNORM | POLLRDBAND);
|
|
const static int CHECK_WRITE_FLAG = (POLLOUT | POLLWRNORM);
|
|
const static int CHECK_ERROR_FLAG = (POLLERR | POLLHUP);
|
|
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
const static int CHECK_READ_FLAG = (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI);
|
|
const static int CHECK_WRITE_FLAG = (POLLOUT | POLLWRNORM | POLLWRBAND);
|
|
const static int CHECK_ERROR_FLAG = (POLLERR | POLLHUP);
|
|
#endif
|
|
|
|
enum CheckType {
|
|
ReadCheck = 0x1,
|
|
WriteCheck = 0x2,
|
|
ErrorCheck = 0x4,
|
|
};
|
|
|
|
struct poller_s {
|
|
struct pollfd *pollFds;
|
|
int nfds;
|
|
int limitSize;
|
|
};
|
|
|
|
static void upstep_pollfd(struct poller_s *self, int upSize) {
|
|
if (upSize <= 0) {
|
|
return;
|
|
}
|
|
|
|
struct pollfd *newPollfds = (struct pollfd *)malloc(
|
|
sizeof(struct pollfd) * (self->limitSize + upSize));
|
|
if (newPollfds == nullptr) {
|
|
return;
|
|
}
|
|
|
|
if (self->pollFds != nullptr) {
|
|
memcpy(newPollfds, self->pollFds, sizeof(struct pollfd) * self->nfds);
|
|
free(self->pollFds);
|
|
self->pollFds = nullptr;
|
|
}
|
|
self->pollFds = newPollfds;
|
|
self->limitSize += upSize;
|
|
}
|
|
|
|
static struct pollfd *find_pollfd(struct poller_s *self, BrynetSocketFD fd) {
|
|
for (int i = 0; i < self->nfds; i++) {
|
|
if (self->pollFds[i].fd == fd) {
|
|
return self->pollFds + i;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
static void try_remove_pollfd(struct poller_s *self, BrynetSocketFD fd) {
|
|
int pos = -1;
|
|
for (int i = 0; i < self->nfds; i++) {
|
|
if (self->pollFds[i].fd == fd) {
|
|
pos = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (pos != -1) {
|
|
memmove(self->pollFds + pos,
|
|
self->pollFds + pos + 1,
|
|
sizeof(struct pollfd) * (self->nfds - pos - 1));
|
|
self->nfds--;
|
|
assert(self->nfds >= 0);
|
|
}
|
|
}
|
|
|
|
static struct poller_s *poller_new(void) {
|
|
struct poller_s *ret = (struct poller_s *)malloc(sizeof(struct poller_s));
|
|
if (ret != nullptr) {
|
|
ret->pollFds = NULL;
|
|
ret->limitSize = 0;
|
|
ret->nfds = 0;
|
|
upstep_pollfd(ret, 1024);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void poller_delete(struct poller_s *self) {
|
|
free(self->pollFds);
|
|
self->pollFds = nullptr;
|
|
self->nfds = 0;
|
|
self->limitSize = 0;
|
|
|
|
free(self);
|
|
self = nullptr;
|
|
}
|
|
|
|
static void poller_add(struct poller_s *self, BrynetSocketFD fd, int type) {
|
|
if (self->limitSize == self->nfds) {
|
|
upstep_pollfd(self, 128);
|
|
}
|
|
|
|
if (self->limitSize <= self->nfds) {
|
|
return;
|
|
}
|
|
|
|
struct pollfd *pf = find_pollfd(self, fd);
|
|
if (pf == nullptr) {
|
|
/*real add*/
|
|
pf = self->pollFds + self->nfds;
|
|
pf->events = 0;
|
|
pf->fd = fd;
|
|
|
|
self->nfds++;
|
|
}
|
|
|
|
if (type & ReadCheck) {
|
|
pf->events |= CHECK_READ_FLAG;
|
|
}
|
|
|
|
if (type & WriteCheck) {
|
|
pf->events |= CHECK_WRITE_FLAG;
|
|
}
|
|
|
|
if (type & ErrorCheck) {
|
|
//pf->events |= CHECK_ERROR_FLAG; TODO::on windows, not supports
|
|
}
|
|
}
|
|
|
|
static void poller_del(struct poller_s *self, BrynetSocketFD fd, int type) {
|
|
struct pollfd *pf = find_pollfd(self, fd);
|
|
if (pf == nullptr) {
|
|
return;
|
|
}
|
|
|
|
if (type & ReadCheck) {
|
|
pf->events &= ~CHECK_READ_FLAG;
|
|
}
|
|
|
|
if (type & WriteCheck) {
|
|
pf->events &= ~CHECK_WRITE_FLAG;
|
|
}
|
|
|
|
if (type & ErrorCheck) {
|
|
pf->events &= ~CHECK_ERROR_FLAG;
|
|
}
|
|
|
|
if (pf->events == 0) {
|
|
try_remove_pollfd(self, fd);
|
|
}
|
|
}
|
|
|
|
static void poller_remove(struct poller_s *self, BrynetSocketFD fd) {
|
|
try_remove_pollfd(self, fd);
|
|
}
|
|
|
|
static bool check_event(const struct pollfd *pf, enum CheckType type) {
|
|
if (pf == nullptr) {
|
|
return false;
|
|
}
|
|
|
|
if ((type & ReadCheck) &&
|
|
(pf->revents & CHECK_READ_FLAG)) {
|
|
return true;
|
|
} else if ((type & WriteCheck) &&
|
|
(pf->revents & CHECK_WRITE_FLAG)) {
|
|
return true;
|
|
} else if ((type & ErrorCheck) &&
|
|
(pf->revents & CHECK_ERROR_FLAG)) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static void poller_visitor(struct poller_s *self,
|
|
enum CheckType type,
|
|
struct stack_s *result) {
|
|
for (int i = 0; i < self->nfds; i++) {
|
|
if (check_event(self->pollFds + i, type)) {
|
|
stack_push(result, &self->pollFds[i].fd);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int poller_poll(struct poller_s *self, long overtime) {
|
|
#ifdef BRYNET_PLATFORM_WINDOWS
|
|
int ret = WSAPoll(&self->pollFds[0], self->nfds, overtime);
|
|
#elif defined BRYNET_PLATFORM_LINUX || defined BRYNET_PLATFORM_DARWIN
|
|
int ret = poll(self->pollFds, self->nfds, overtime);
|
|
#endif
|
|
|
|
if (ret == BRYNET_SOCKET_ERROR) {
|
|
ret = (BRYNET_ERRNO != BRYNET_EINTR) ? -1 : 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static bool poller_check(struct poller_s *self, BrynetSocketFD fd, enum CheckType type) {
|
|
const struct pollfd *pf = find_pollfd(self, fd);
|
|
if (pf == NULL) {
|
|
return false;
|
|
}
|
|
return check_event(pf, type);
|
|
}
|