queue: re-implement
This commit is contained in:
parent
4568ce69d8
commit
4d9a24a708
@ -30,12 +30,6 @@ typedef struct _ep_sock_private {
|
||||
uint32_t flags;
|
||||
} _ep_sock_private_t;
|
||||
|
||||
#define ATTN_LIST_ADD(p, sock_info) \
|
||||
do { \
|
||||
QUEUE_INSERT_TAIL(&(p)->update_queue, &(sock_info)->queue_entry); \
|
||||
(_ep_sock_private(sock_info))->flags |= _EP_SOCK_LISTED; \
|
||||
} while (0)
|
||||
|
||||
static inline _ep_sock_private_t* _ep_sock_private(ep_sock_t* sock_info) {
|
||||
return container_of(sock_info, _ep_sock_private_t, pub);
|
||||
}
|
||||
@ -64,7 +58,7 @@ ep_sock_t* ep_sock_new(ep_port_t* port_info) {
|
||||
|
||||
memset(sock_private, 0, sizeof *sock_private);
|
||||
handle_tree_entry_init(&sock_private->pub.tree_entry);
|
||||
QUEUE_INIT(&sock_private->pub.queue_entry);
|
||||
queue_elem_init(&sock_private->pub.queue_entry);
|
||||
|
||||
return &sock_private->pub;
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ typedef struct poll_req poll_req_t;
|
||||
|
||||
typedef struct ep_sock {
|
||||
handle_tree_entry_t tree_entry;
|
||||
QUEUE queue_entry;
|
||||
queue_elem_t queue_entry;
|
||||
} ep_sock_t;
|
||||
|
||||
EPOLL_INTERNAL ep_sock_t* ep_sock_new(ep_port_t* port_info);
|
||||
|
||||
16
src/epoll.c
16
src/epoll.c
@ -99,13 +99,13 @@ int epoll_ctl(epoll_t port_handle,
|
||||
}
|
||||
|
||||
static int _ep_port_update_events(ep_port_t* port_info) {
|
||||
QUEUE* update_queue = &port_info->update_queue;
|
||||
queue_t* update_queue = &port_info->update_queue;
|
||||
|
||||
/* Walk the queue, submitting new poll requests for every socket that needs
|
||||
* it. */
|
||||
while (!QUEUE_EMPTY(update_queue)) {
|
||||
QUEUE* queue_entry = QUEUE_HEAD(update_queue);
|
||||
ep_sock_t* sock_info = QUEUE_DATA(queue_entry, ep_sock_t, queue_entry);
|
||||
while (!queue_empty(update_queue)) {
|
||||
queue_elem_t* queue_entry = queue_first(update_queue);
|
||||
ep_sock_t* sock_info = container_of(queue_entry, ep_sock_t, queue_entry);
|
||||
|
||||
if (ep_sock_update(port_info, sock_info) < 0)
|
||||
return -1;
|
||||
@ -229,7 +229,7 @@ epoll_t epoll_create(void) {
|
||||
port_info->iocp = iocp;
|
||||
port_info->poll_req_count = 0;
|
||||
|
||||
QUEUE_INIT(&port_info->update_queue);
|
||||
queue_init(&port_info->update_queue);
|
||||
|
||||
memset(&port_info->driver_sockets, 0, sizeof port_info->driver_sockets);
|
||||
handle_tree_init(&port_info->sock_tree);
|
||||
@ -393,19 +393,19 @@ error:;
|
||||
bool ep_port_is_socket_update_pending(ep_port_t* port_info,
|
||||
ep_sock_t* sock_info) {
|
||||
unused(port_info);
|
||||
return QUEUE_ENQUEUED(&sock_info->queue_entry);
|
||||
return queue_enqueued(&sock_info->queue_entry);
|
||||
}
|
||||
|
||||
void ep_port_request_socket_update(ep_port_t* port_info,
|
||||
ep_sock_t* sock_info) {
|
||||
if (ep_port_is_socket_update_pending(port_info, sock_info))
|
||||
return;
|
||||
QUEUE_INSERT_TAIL(&port_info->update_queue, &sock_info->queue_entry);
|
||||
queue_append(&port_info->update_queue, &sock_info->queue_entry);
|
||||
assert(ep_port_is_socket_update_pending(port_info, sock_info));
|
||||
}
|
||||
|
||||
void ep_port_clear_socket_update(ep_port_t* port_info, ep_sock_t* sock_info) {
|
||||
if (!ep_port_is_socket_update_pending(port_info, sock_info))
|
||||
return;
|
||||
QUEUE_REMOVE(&sock_info->queue_entry);
|
||||
queue_remove(&sock_info->queue_entry);
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ typedef struct ep_port {
|
||||
HANDLE iocp;
|
||||
SOCKET driver_sockets[array_count(AFD_PROVIDER_GUID_LIST)];
|
||||
handle_tree_t sock_tree;
|
||||
QUEUE update_queue;
|
||||
queue_t update_queue;
|
||||
size_t poll_req_count;
|
||||
} ep_port_t;
|
||||
|
||||
|
||||
133
src/queue.h
133
src/queue.h
@ -1,101 +1,64 @@
|
||||
/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QUEUE_H_
|
||||
#define QUEUE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef void* QUEUE[2];
|
||||
#include "internal.h"
|
||||
|
||||
/* Private macros. */
|
||||
#define _QUEUE_NEXT(q) (*(QUEUE**) &((*(q))[0]))
|
||||
#define _QUEUE_PREV(q) (*(QUEUE**) &((*(q))[1]))
|
||||
#define _QUEUE_PREV_NEXT(q) (_QUEUE_NEXT(_QUEUE_PREV(q)))
|
||||
#define _QUEUE_NEXT_PREV(q) (_QUEUE_PREV(_QUEUE_NEXT(q)))
|
||||
typedef struct queue_elem queue_elem_t;
|
||||
typedef struct queue_elem {
|
||||
queue_elem_t* prev;
|
||||
queue_elem_t* next;
|
||||
} queue_elem_t;
|
||||
typedef struct queue {
|
||||
queue_elem_t head;
|
||||
} queue_t;
|
||||
|
||||
/* Public macros. */
|
||||
#define QUEUE_DATA(ptr, type, field) \
|
||||
((type*) ((char*) (ptr) -offsetof(type, field)))
|
||||
EPOLL_INTERNAL inline void queue_elem_init(queue_elem_t* elem) {
|
||||
elem->prev = elem;
|
||||
elem->next = elem;
|
||||
}
|
||||
|
||||
/* Important note: mutating the list while QUEUE_FOREACH is
|
||||
* iterating over its elements results in undefined behavior.
|
||||
*/
|
||||
#define QUEUE_FOREACH(q, h) \
|
||||
for ((q) = _QUEUE_NEXT(h); (q) != (h); (q) = _QUEUE_NEXT(q))
|
||||
EPOLL_INTERNAL inline void queue_init(queue_t* queue) {
|
||||
queue_elem_init(&queue->head);
|
||||
}
|
||||
|
||||
#define QUEUE_EMPTY(q) ((const QUEUE*) (q) == (const QUEUE*) _QUEUE_NEXT(q))
|
||||
#define QUEUE_ENQUEUED(q) (!QUEUE_EMPTY(q))
|
||||
EPOLL_INTERNAL inline bool queue_enqueued(const queue_elem_t* elem) {
|
||||
return elem->prev != elem;
|
||||
}
|
||||
|
||||
#define QUEUE_HEAD(q) (_QUEUE_NEXT(q))
|
||||
EPOLL_INTERNAL inline bool queue_empty(const queue_t* queue) {
|
||||
return !queue_enqueued(&queue->head);
|
||||
}
|
||||
|
||||
#define QUEUE_INIT(q) \
|
||||
do { \
|
||||
_QUEUE_NEXT(q) = (q); \
|
||||
_QUEUE_PREV(q) = (q); \
|
||||
} while (0)
|
||||
EPOLL_INTERNAL inline queue_elem_t* queue_first(const queue_t* queue) {
|
||||
return !queue_empty(queue) ? queue->head.next : NULL;
|
||||
}
|
||||
|
||||
#define QUEUE_MERGE(h, n) \
|
||||
do { \
|
||||
_QUEUE_PREV_NEXT(h) = _QUEUE_NEXT(n); \
|
||||
_QUEUE_NEXT_PREV(n) = _QUEUE_PREV(h); \
|
||||
_QUEUE_PREV(h) = _QUEUE_PREV(n); \
|
||||
_QUEUE_PREV_NEXT(h) = (h); \
|
||||
} while (0)
|
||||
EPOLL_INTERNAL inline queue_elem_t* queue_last(const queue_t* queue) {
|
||||
return !queue_empty(queue) ? queue->head.prev : NULL;
|
||||
}
|
||||
|
||||
#define QUEUE_SPLIT(h, q, n) \
|
||||
do { \
|
||||
_QUEUE_PREV(n) = _QUEUE_PREV(h); \
|
||||
_QUEUE_PREV_NEXT(n) = (n); \
|
||||
_QUEUE_NEXT(n) = (q); \
|
||||
_QUEUE_PREV(h) = _QUEUE_PREV(q); \
|
||||
_QUEUE_PREV_NEXT(h) = (h); \
|
||||
_QUEUE_PREV(q) = (n); \
|
||||
} while (0)
|
||||
EPOLL_INTERNAL inline void queue_prepend(queue_t* queue, queue_elem_t* elem) {
|
||||
elem->next = queue->head.next;
|
||||
elem->prev = &queue->head;
|
||||
elem->next->prev = elem;
|
||||
queue->head.next = elem;
|
||||
}
|
||||
|
||||
#define QUEUE_MOVE(h, n) \
|
||||
do { \
|
||||
if (QUEUE_EMPTY(h)) \
|
||||
QUEUE_INIT(n); \
|
||||
else { \
|
||||
QUEUE* q = QUEUE_HEAD(h); \
|
||||
QUEUE_SPLIT(h, q, n); \
|
||||
} \
|
||||
} while (0)
|
||||
EPOLL_INTERNAL inline void queue_append(queue_t* queue, queue_elem_t* elem) {
|
||||
elem->next = &queue->head;
|
||||
elem->prev = queue->head.prev;
|
||||
elem->prev->next = elem;
|
||||
queue->head.prev = elem;
|
||||
}
|
||||
|
||||
#define QUEUE_INSERT_HEAD(h, q) \
|
||||
do { \
|
||||
_QUEUE_NEXT(q) = _QUEUE_NEXT(h); \
|
||||
_QUEUE_PREV(q) = (h); \
|
||||
_QUEUE_NEXT_PREV(q) = (q); \
|
||||
_QUEUE_NEXT(h) = (q); \
|
||||
} while (0)
|
||||
|
||||
#define QUEUE_INSERT_TAIL(h, q) \
|
||||
do { \
|
||||
_QUEUE_NEXT(q) = (h); \
|
||||
_QUEUE_PREV(q) = _QUEUE_PREV(h); \
|
||||
_QUEUE_PREV_NEXT(q) = (q); \
|
||||
_QUEUE_PREV(h) = (q); \
|
||||
} while (0)
|
||||
|
||||
#define QUEUE_REMOVE(q) \
|
||||
do { \
|
||||
_QUEUE_PREV_NEXT(q) = _QUEUE_NEXT(q); \
|
||||
_QUEUE_NEXT_PREV(q) = _QUEUE_PREV(q); \
|
||||
QUEUE_INIT(q); \
|
||||
} while (0)
|
||||
EPOLL_INTERNAL inline void queue_remove(queue_elem_t* elem) {
|
||||
elem->prev->next = elem->next;
|
||||
elem->next->prev = elem->prev;
|
||||
elem->prev = elem;
|
||||
elem->next = elem;
|
||||
}
|
||||
|
||||
#endif /* QUEUE_H_ */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user