wepoll/src/poll-group.c
Bert Belder 3e3251e0d9
error: break up return_error() macro into two non-variadic macros
This prevents clang 6.x from emitting a
gnu-zero-variadic-macro-arguments warning.
2018-05-17 01:31:21 -07:00

84 lines
2.2 KiB
C

#include <assert.h>
#include <malloc.h>
#include <string.h>
#include "error.h"
#include "poll-group.h"
#include "port.h"
#include "util.h"
#include "win.h"
static const size_t _POLL_GROUP_MAX_GROUP_SIZE = 32;
typedef struct poll_group {
ep_port_t* port_info;
queue_node_t queue_node;
SOCKET socket;
size_t group_size;
} poll_group_t;
static poll_group_t* _poll_group_new(ep_port_t* port_info) {
poll_group_t* poll_group = malloc(sizeof *poll_group);
if (poll_group == NULL)
return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY);
memset(poll_group, 0, sizeof *poll_group);
queue_node_init(&poll_group->queue_node);
poll_group->port_info = port_info;
if (afd_create_driver_socket(port_info->iocp, &poll_group->socket) < 0) {
free(poll_group);
return NULL;
}
queue_append(&port_info->poll_group_queue, &poll_group->queue_node);
return poll_group;
}
void poll_group_delete(poll_group_t* poll_group) {
assert(poll_group->group_size == 0);
closesocket(poll_group->socket);
queue_remove(&poll_group->queue_node);
free(poll_group);
}
poll_group_t* poll_group_from_queue_node(queue_node_t* queue_node) {
return container_of(queue_node, poll_group_t, queue_node);
}
SOCKET poll_group_get_socket(poll_group_t* poll_group) {
return poll_group->socket;
}
poll_group_t* poll_group_acquire(ep_port_t* port_info) {
queue_t* queue = &port_info->poll_group_queue;
poll_group_t* poll_group =
!queue_empty(queue)
? container_of(queue_last(queue), poll_group_t, queue_node)
: NULL;
if (poll_group == NULL ||
poll_group->group_size >= _POLL_GROUP_MAX_GROUP_SIZE)
poll_group = _poll_group_new(port_info);
if (poll_group == NULL)
return NULL;
if (++poll_group->group_size == _POLL_GROUP_MAX_GROUP_SIZE)
queue_move_first(&port_info->poll_group_queue, &poll_group->queue_node);
return poll_group;
}
void poll_group_release(poll_group_t* poll_group) {
ep_port_t* port_info = poll_group->port_info;
poll_group->group_size--;
assert(poll_group->group_size < _POLL_GROUP_MAX_GROUP_SIZE);
queue_move_last(&port_info->poll_group_queue, &poll_group->queue_node);
/* Poll groups are currently only freed when the epoll port is closed. */
}