Rework the poller
It's about time we stopped fucking ourselves in the butt. The scanning should be much faster now. Thanks to libuv for inspiration.
This commit is contained in:
parent
6f1bc52711
commit
457eff90e3
128
ponymap.c
128
ponymap.c
|
@ -225,6 +225,9 @@ struct unit
|
||||||
struct str read_buffer; ///< Unprocessed input
|
struct str read_buffer; ///< Unprocessed input
|
||||||
struct str write_buffer; ///< Output yet to be sent out
|
struct str write_buffer; ///< Output yet to be sent out
|
||||||
|
|
||||||
|
struct poller_timer timeout_event; ///< Timeout event
|
||||||
|
struct poller_fd fd_event; ///< FD event
|
||||||
|
|
||||||
bool aborted; ///< Scan has been aborted
|
bool aborted; ///< Scan has been aborted
|
||||||
bool success; ///< Service has been found
|
bool success; ///< Service has been found
|
||||||
struct str_vector info; ///< Info resulting from the scan
|
struct str_vector info; ///< Info resulting from the scan
|
||||||
|
@ -270,6 +273,8 @@ struct transport
|
||||||
|
|
||||||
struct indicator
|
struct indicator
|
||||||
{
|
{
|
||||||
|
struct poller_timer timer; ///< The animation timer
|
||||||
|
|
||||||
unsigned position; ///< The current animation character
|
unsigned position; ///< The current animation character
|
||||||
const char *frames; ///< All the characters
|
const char *frames; ///< All the characters
|
||||||
size_t frames_len; ///< The number of characters
|
size_t frames_len; ///< The number of characters
|
||||||
|
@ -278,17 +283,7 @@ struct indicator
|
||||||
char *status; ///< The status text
|
char *status; ///< The status text
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void indicator_init (struct indicator *self, struct poller *poller);
|
||||||
indicator_init (struct indicator *self)
|
|
||||||
{
|
|
||||||
static const char frames[] = "-\\|/";
|
|
||||||
self->position = 0;
|
|
||||||
self->frames = frames;
|
|
||||||
self->frames_len = sizeof frames - 1;
|
|
||||||
|
|
||||||
self->status = NULL;
|
|
||||||
self->shown = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
indicator_free (struct indicator *self)
|
indicator_free (struct indicator *self)
|
||||||
|
@ -362,7 +357,7 @@ app_context_init (struct app_context *self)
|
||||||
|
|
||||||
str_map_init (&self->svc_list);
|
str_map_init (&self->svc_list);
|
||||||
str_map_init (&self->services);
|
str_map_init (&self->services);
|
||||||
indicator_init (&self->indicator);
|
indicator_init (&self->indicator, &self->poller);
|
||||||
// Ignoring the generator so far
|
// Ignoring the generator so far
|
||||||
|
|
||||||
poller_init (&self->poller);
|
poller_init (&self->poller);
|
||||||
|
@ -400,17 +395,18 @@ app_context_free (struct app_context *self)
|
||||||
|
|
||||||
// --- Progress indicator ------------------------------------------------------
|
// --- Progress indicator ------------------------------------------------------
|
||||||
|
|
||||||
// TODO: rework the poller so that we don't have to use a reference to
|
|
||||||
// `struct app_context' to make changes to the animation timer.
|
|
||||||
// TODO: make it so that the indicator is hidden while printing messages to
|
// TODO: make it so that the indicator is hidden while printing messages to
|
||||||
// the same terminal -> wrapper for log_message_stdio().
|
// the same terminal -> wrapper for log_message_stdio().
|
||||||
|
|
||||||
static void indicator_set_timer (struct app_context *ctx);
|
static void
|
||||||
|
indicator_set_timer (struct indicator *self)
|
||||||
|
{
|
||||||
|
poller_timer_set (&self->timer, INDICATOR_INTERVAL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_indicator_tick (struct app_context *ctx)
|
on_indicator_tick (struct indicator *self)
|
||||||
{
|
{
|
||||||
struct indicator *self = &ctx->indicator;
|
|
||||||
if (!self->shown)
|
if (!self->shown)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -420,20 +416,28 @@ on_indicator_tick (struct app_context *ctx)
|
||||||
tputs (cursor_left, 1, putchar);
|
tputs (cursor_left, 1, putchar);
|
||||||
putchar (self->frames[self->position]);
|
putchar (self->frames[self->position]);
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
indicator_set_timer (ctx);
|
indicator_set_timer (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
indicator_set_timer (struct app_context *ctx)
|
indicator_init (struct indicator *self, struct poller *poller)
|
||||||
{
|
{
|
||||||
poller_timers_add (&ctx->poller.timers,
|
poller_timer_init (&self->timer, poller);
|
||||||
(poller_timer_fn) on_indicator_tick, ctx, INDICATOR_INTERVAL);
|
self->timer.dispatcher = (poller_timer_fn) on_indicator_tick;
|
||||||
|
self->timer.user_data = self;
|
||||||
|
|
||||||
|
static const char frames[] = "-\\|/";
|
||||||
|
self->position = 0;
|
||||||
|
self->frames = frames;
|
||||||
|
self->frames_len = sizeof frames - 1;
|
||||||
|
|
||||||
|
self->status = NULL;
|
||||||
|
self->shown = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
indicator_show (struct app_context *ctx)
|
indicator_show (struct indicator *self)
|
||||||
{
|
{
|
||||||
struct indicator *self = &ctx->indicator;
|
|
||||||
if (self->shown || !g_terminal.initialized || !g_terminal.stdout_is_tty)
|
if (self->shown || !g_terminal.initialized || !g_terminal.stdout_is_tty)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -441,15 +445,14 @@ indicator_show (struct app_context *ctx)
|
||||||
printf ("%s... %c", self->status, self->frames[self->position]);
|
printf ("%s... %c", self->status, self->frames[self->position]);
|
||||||
tputs (clr_eol, 1, putchar);
|
tputs (clr_eol, 1, putchar);
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
indicator_set_timer (ctx);
|
|
||||||
|
|
||||||
self->shown = true;
|
self->shown = true;
|
||||||
|
indicator_set_timer (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
indicator_hide (struct app_context *ctx)
|
indicator_hide (struct indicator *self)
|
||||||
{
|
{
|
||||||
struct indicator *self = &ctx->indicator;
|
|
||||||
if (!self->shown)
|
if (!self->shown)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -457,24 +460,20 @@ indicator_hide (struct app_context *ctx)
|
||||||
tputs (clr_eol, 1, putchar);
|
tputs (clr_eol, 1, putchar);
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
|
|
||||||
ssize_t i = poller_timers_find
|
poller_timer_reset (&self->timer);
|
||||||
(&ctx->poller.timers, (poller_timer_fn) on_indicator_tick, ctx);
|
|
||||||
if (i != -1)
|
|
||||||
poller_timers_remove_at_index (&ctx->poller.timers, i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
indicator_set_status (struct app_context *ctx, char *status)
|
indicator_set_status (struct indicator *self, char *status)
|
||||||
{
|
{
|
||||||
struct indicator *self = &ctx->indicator;
|
|
||||||
bool refresh = self->shown;
|
bool refresh = self->shown;
|
||||||
indicator_hide (ctx);
|
indicator_hide (self);
|
||||||
|
|
||||||
free (self->status);
|
free (self->status);
|
||||||
self->status = status;
|
self->status = status;
|
||||||
|
|
||||||
if (refresh)
|
if (refresh)
|
||||||
indicator_show (ctx);
|
indicator_show (self);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Scan units --------------------------------------------------------------
|
// --- Scan units --------------------------------------------------------------
|
||||||
|
@ -513,13 +512,8 @@ unit_abort (struct unit *u)
|
||||||
if (u->service->on_aborted)
|
if (u->service->on_aborted)
|
||||||
u->service->on_aborted (u->service_data, u);
|
u->service->on_aborted (u->service_data, u);
|
||||||
|
|
||||||
ssize_t i;
|
poller_timer_reset (&u->timeout_event);
|
||||||
struct app_context *ctx = u->target->ctx;
|
poller_fd_reset (&u->fd_event);
|
||||||
struct poller *poller = &ctx->poller;
|
|
||||||
if ((i = poller_find_by_fd (poller, u->socket_fd)) != -1)
|
|
||||||
poller_remove_at_index (poller, i);
|
|
||||||
while ((i = poller_timers_find_by_data (&poller->timers, u)) != -1)
|
|
||||||
poller_timers_remove_at_index (&poller->timers, i);
|
|
||||||
|
|
||||||
u->transport->cleanup (u);
|
u->transport->cleanup (u);
|
||||||
u->service->scan_free (u->service_data);
|
u->service->scan_free (u->service_data);
|
||||||
|
@ -533,7 +527,7 @@ unit_abort (struct unit *u)
|
||||||
LIST_UNLINK (u->target->running_units, u);
|
LIST_UNLINK (u->target->running_units, u);
|
||||||
|
|
||||||
// We might have made it possible to launch new units
|
// We might have made it possible to launch new units
|
||||||
while (generator_step (ctx))
|
while (generator_step (u->target->ctx))
|
||||||
;
|
;
|
||||||
|
|
||||||
if (u->success)
|
if (u->success)
|
||||||
|
@ -554,8 +548,7 @@ unit_update_poller (struct unit *u, const struct pollfd *pfd)
|
||||||
hard_assert (new_events != 0);
|
hard_assert (new_events != 0);
|
||||||
|
|
||||||
if (!pfd || pfd->events != new_events)
|
if (!pfd || pfd->events != new_events)
|
||||||
poller_set (&u->target->ctx->poller, u->socket_fd, new_events,
|
poller_fd_set (&u->fd_event, new_events);
|
||||||
(poller_dispatcher_fn) on_unit_ready, u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -608,9 +601,8 @@ end:
|
||||||
static void
|
static void
|
||||||
unit_start_scan (struct unit *u)
|
unit_start_scan (struct unit *u)
|
||||||
{
|
{
|
||||||
struct app_context *ctx = u->target->ctx;
|
poller_timer_set (&u->timeout_event, u->target->ctx->scan_timeout);
|
||||||
poller_timers_add (&ctx->poller.timers,
|
u->fd_event.dispatcher = (poller_fd_fn) on_unit_ready;
|
||||||
(poller_timer_fn) unit_abort, u, ctx->scan_timeout);
|
|
||||||
unit_update_poller (u, NULL);
|
unit_update_poller (u, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,12 +610,8 @@ static void
|
||||||
on_unit_connected (const struct pollfd *pfd, struct unit *u)
|
on_unit_connected (const struct pollfd *pfd, struct unit *u)
|
||||||
{
|
{
|
||||||
(void) pfd;
|
(void) pfd;
|
||||||
struct app_context *ctx = u->target->ctx;
|
|
||||||
|
|
||||||
ssize_t i = poller_timers_find (&ctx->poller.timers,
|
poller_timer_reset (&u->timeout_event);
|
||||||
(poller_timer_fn) unit_abort, u);
|
|
||||||
hard_assert (i != -1);
|
|
||||||
poller_timers_remove_at_index (&ctx->poller.timers, i);
|
|
||||||
|
|
||||||
int error;
|
int error;
|
||||||
socklen_t error_len = sizeof error;
|
socklen_t error_len = sizeof error;
|
||||||
|
@ -666,6 +654,14 @@ unit_new (struct target *target, int socket_fd, uint16_t port,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
poller_timer_init (&u->timeout_event, &target->ctx->poller);
|
||||||
|
u->timeout_event.dispatcher = (poller_timer_fn) unit_abort;
|
||||||
|
u->timeout_event.user_data = u;
|
||||||
|
|
||||||
|
poller_fd_init (&u->fd_event, &target->ctx->poller, socket_fd);
|
||||||
|
u->fd_event.dispatcher = (poller_fd_fn) on_unit_connected;
|
||||||
|
u->fd_event.user_data = u;
|
||||||
|
|
||||||
u->service_data = service->scan_init (u);
|
u->service_data = service->scan_init (u);
|
||||||
LIST_PREPEND (target->running_units, u);
|
LIST_PREPEND (target->running_units, u);
|
||||||
return u;
|
return u;
|
||||||
|
@ -718,11 +714,10 @@ unit_make (struct target *target, uint32_t ip, uint16_t port,
|
||||||
unit_start_scan (u);
|
unit_start_scan (u);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
poller_timers_add (&ctx->poller.timers,
|
poller_timer_set (&u->timeout_event, ctx->connect_timeout);
|
||||||
(poller_timer_fn) unit_abort, u, ctx->connect_timeout);
|
poller_fd_set (&u->fd_event, POLLOUT);
|
||||||
poller_set (&ctx->poller, u->socket_fd, POLLOUT,
|
|
||||||
(poller_dispatcher_fn) on_unit_connected, u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return UNIT_MAKE_OK;
|
return UNIT_MAKE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,7 +734,7 @@ static void
|
||||||
initiate_quit (struct app_context *ctx)
|
initiate_quit (struct app_context *ctx)
|
||||||
{
|
{
|
||||||
ctx->quitting = true;
|
ctx->quitting = true;
|
||||||
indicator_set_status (ctx, xstrdup ("Quitting"));
|
indicator_set_status (&ctx->indicator, xstrdup ("Quitting"));
|
||||||
|
|
||||||
// Abort all running units
|
// Abort all running units
|
||||||
struct target *t_iter, *t_next;
|
struct target *t_iter, *t_next;
|
||||||
|
@ -1292,7 +1287,7 @@ target_dump_json (struct target *self, struct target_dump_data *data)
|
||||||
static void
|
static void
|
||||||
target_dump_terminal (struct target *self, struct target_dump_data *data)
|
target_dump_terminal (struct target *self, struct target_dump_data *data)
|
||||||
{
|
{
|
||||||
indicator_hide (self->ctx);
|
indicator_hide (&self->ctx->indicator);
|
||||||
|
|
||||||
struct str tmp;
|
struct str tmp;
|
||||||
str_init (&tmp);
|
str_init (&tmp);
|
||||||
|
@ -1333,7 +1328,7 @@ target_dump_terminal (struct target *self, struct target_dump_data *data)
|
||||||
node_delete (root);
|
node_delete (root);
|
||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
|
|
||||||
indicator_show (self->ctx);
|
indicator_show (&self->ctx->indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1389,10 +1384,10 @@ target_update_indicator (struct target *self)
|
||||||
char *status = xstrdup_printf ("Scanning %s", buf);
|
char *status = xstrdup_printf ("Scanning %s", buf);
|
||||||
struct indicator *indicator = &self->ctx->indicator;
|
struct indicator *indicator = &self->ctx->indicator;
|
||||||
if (!indicator->status || strcmp (status, indicator->status))
|
if (!indicator->status || strcmp (status, indicator->status))
|
||||||
indicator_set_status (self->ctx, status);
|
indicator_set_status (&self->ctx->indicator, status);
|
||||||
else
|
else
|
||||||
free (status);
|
free (status);
|
||||||
indicator_show (self->ctx);
|
indicator_show (&self->ctx->indicator);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct target *
|
static struct target *
|
||||||
|
@ -1424,7 +1419,7 @@ target_unref (struct target *self)
|
||||||
struct app_context *ctx = self->ctx;
|
struct app_context *ctx = self->ctx;
|
||||||
LIST_UNLINK_WITH_TAIL (ctx->running_targets, ctx->running_tail, self);
|
LIST_UNLINK_WITH_TAIL (ctx->running_targets, ctx->running_tail, self);
|
||||||
if (!ctx->running_targets)
|
if (!ctx->running_targets)
|
||||||
indicator_hide (ctx);
|
indicator_hide (&ctx->indicator);
|
||||||
else if (!ctx->quitting && ctx->running_targets)
|
else if (!ctx->quitting && ctx->running_targets)
|
||||||
target_update_indicator (ctx->running_targets);
|
target_update_indicator (ctx->running_targets);
|
||||||
|
|
||||||
|
@ -1922,8 +1917,11 @@ main (int argc, char *argv[])
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
poller_set (&ctx.poller, g_signal_pipe[0], POLLIN,
|
struct poller_fd signal_event;
|
||||||
(poller_dispatcher_fn) on_signal_pipe_readable, &ctx);
|
poller_fd_init (&signal_event, &ctx.poller, g_signal_pipe[0]);
|
||||||
|
signal_event.dispatcher = (poller_fd_fn) on_signal_pipe_readable;
|
||||||
|
signal_event.user_data = &ctx;
|
||||||
|
poller_fd_set (&signal_event, POLLIN);
|
||||||
|
|
||||||
if (!load_plugins (&ctx))
|
if (!load_plugins (&ctx))
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
|
@ -1961,6 +1959,8 @@ main (int argc, char *argv[])
|
||||||
merge_ip_ranges (&ctx);
|
merge_ip_ranges (&ctx);
|
||||||
|
|
||||||
// Initate the scan: generate as many units as possible
|
// Initate the scan: generate as many units as possible
|
||||||
|
// FIXME: this appears to be quite slow: either make it run faster,
|
||||||
|
// or limit the number of units spawned at a time
|
||||||
generator_init (&ctx);
|
generator_init (&ctx);
|
||||||
while (generator_step (&ctx))
|
while (generator_step (&ctx))
|
||||||
;
|
;
|
||||||
|
|
324
utils.c
324
utils.c
|
@ -840,42 +840,48 @@ xclose (int fd)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Polling -----------------------------------------------------------------
|
// --- Event loop --------------------------------------------------------------
|
||||||
|
|
||||||
// Basically the poor man's GMainLoop/libev/libuv. It might make some sense
|
// Basically the poor man's GMainLoop/libev/libuv. It might make some sense
|
||||||
// to instead use those tested and proven libraries but we don't need much
|
// to instead use those tested and proven libraries but we don't need much
|
||||||
// and it's interesting to implement.
|
// and it's interesting to implement.
|
||||||
|
|
||||||
// At the moment the FD's are stored in an unsorted array. This is not ideal
|
// Actually it mustn't be totally shitty as scanning exercises it quite a bit.
|
||||||
// complexity-wise but I don't think I have much of a choice with poll(),
|
// We sacrifice some memory to allow for O(1) and O(log n) operations.
|
||||||
// and neither with epoll for that matter.
|
|
||||||
//
|
|
||||||
// unsorted array sorted array
|
|
||||||
// search O(n) O(log n) [O(log log n)]
|
|
||||||
// insert by fd O(n) O(n)
|
|
||||||
// delete by fd O(n) O(n)
|
|
||||||
//
|
|
||||||
// Insertion in the unsorted array can be reduced to O(1) if I maintain a
|
|
||||||
// bitmap of present FD's but that's still not a huge win.
|
|
||||||
//
|
|
||||||
// I don't expect this to be much of an issue, as there are typically not going
|
|
||||||
// to be that many FD's to watch, and the linear approach is cache-friendly.
|
|
||||||
|
|
||||||
typedef void (*poller_dispatcher_fn) (const struct pollfd *, void *);
|
typedef void (*poller_fd_fn) (const struct pollfd *, void *);
|
||||||
typedef void (*poller_timer_fn) (void *);
|
typedef void (*poller_timer_fn) (void *);
|
||||||
|
|
||||||
#define POLLER_MIN_ALLOC 16
|
#define POLLER_MIN_ALLOC 16
|
||||||
|
|
||||||
struct poller_timer_info
|
struct poller_timer
|
||||||
{
|
{
|
||||||
|
struct poller_timers *timers; ///< The timers part of our poller
|
||||||
|
ssize_t index; ///< Where we are in the array, or -1
|
||||||
|
|
||||||
int64_t when; ///< When is the timer to expire
|
int64_t when; ///< When is the timer to expire
|
||||||
|
|
||||||
poller_timer_fn dispatcher; ///< Event dispatcher
|
poller_timer_fn dispatcher; ///< Event dispatcher
|
||||||
void *user_data; ///< User data
|
void *user_data; ///< User data
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct poller_fd
|
||||||
|
{
|
||||||
|
struct poller *poller; ///< Our poller
|
||||||
|
ssize_t index; ///< Where we are in the array, or -1
|
||||||
|
|
||||||
|
int fd; ///< Our file descriptor
|
||||||
|
short events; ///< The poll() events we registered for
|
||||||
|
|
||||||
|
poller_fd_fn dispatcher; ///< Event dispatcher
|
||||||
|
void *user_data; ///< User data
|
||||||
|
};
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
struct poller_timers
|
struct poller_timers
|
||||||
{
|
{
|
||||||
struct poller_timer_info *info; ///< Min-heap of timers
|
struct poller_timer **heap; ///< Min-heap of timers
|
||||||
size_t len; ///< Number of scheduled timers
|
size_t len; ///< Number of scheduled timers
|
||||||
size_t alloc; ///< Number of timers allocated
|
size_t alloc; ///< Number of timers allocated
|
||||||
};
|
};
|
||||||
|
@ -885,13 +891,13 @@ poller_timers_init (struct poller_timers *self)
|
||||||
{
|
{
|
||||||
self->alloc = POLLER_MIN_ALLOC;
|
self->alloc = POLLER_MIN_ALLOC;
|
||||||
self->len = 0;
|
self->len = 0;
|
||||||
self->info = xmalloc (self->alloc * sizeof *self->info);
|
self->heap = xmalloc (self->alloc * sizeof *self->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
poller_timers_free (struct poller_timers *self)
|
poller_timers_free (struct poller_timers *self)
|
||||||
{
|
{
|
||||||
free (self->info);
|
free (self->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t
|
static int64_t
|
||||||
|
@ -911,28 +917,30 @@ poller_timers_get_current_time (void)
|
||||||
static void
|
static void
|
||||||
poller_timers_heapify_down (struct poller_timers *self, size_t index)
|
poller_timers_heapify_down (struct poller_timers *self, size_t index)
|
||||||
{
|
{
|
||||||
typedef struct poller_timer_info info_t;
|
typedef struct poller_timer *timer_t;
|
||||||
info_t *end = self->info + self->len;
|
timer_t *end = self->heap + self->len;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
info_t *parent = self->info + index;
|
timer_t *parent = self->heap + index;
|
||||||
info_t *left = self->info + 2 * index + 1;
|
timer_t *left = self->heap + 2 * index + 1;
|
||||||
info_t *right = self->info + 2 * index + 2;
|
timer_t *right = self->heap + 2 * index + 2;
|
||||||
|
|
||||||
info_t *largest = parent;
|
timer_t *largest = parent;
|
||||||
if (left < end && left->when > largest->when)
|
if (left < end && (*left) ->when > (*largest)->when)
|
||||||
largest = left;
|
largest = left;
|
||||||
if (right < end && right->when > largest->when)
|
if (right < end && (*right)->when > (*largest)->when)
|
||||||
largest = right;
|
largest = right;
|
||||||
if (parent == largest)
|
if (parent == largest)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
info_t tmp = *parent;
|
timer_t tmp = *parent;
|
||||||
*parent = *largest;
|
*parent = *largest;
|
||||||
*largest = tmp;
|
*largest = tmp;
|
||||||
|
|
||||||
index = largest - self->info;
|
(*parent) ->index = parent - self->heap;
|
||||||
|
(*largest)->index = largest - self->heap;
|
||||||
|
index = largest - self->heap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -940,10 +948,12 @@ static void
|
||||||
poller_timers_remove_at_index (struct poller_timers *self, size_t index)
|
poller_timers_remove_at_index (struct poller_timers *self, size_t index)
|
||||||
{
|
{
|
||||||
hard_assert (index < self->len);
|
hard_assert (index < self->len);
|
||||||
|
self->heap[index]->index = -1;
|
||||||
if (index == --self->len)
|
if (index == --self->len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
self->info[index] = self->info[self->len];
|
self->heap[index] = self->heap[self->len];
|
||||||
|
self->heap[index]->index = index;
|
||||||
poller_timers_heapify_down (self, index);
|
poller_timers_heapify_down (self, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,11 +961,11 @@ static void
|
||||||
poller_timers_dispatch (struct poller_timers *self)
|
poller_timers_dispatch (struct poller_timers *self)
|
||||||
{
|
{
|
||||||
int64_t now = poller_timers_get_current_time ();
|
int64_t now = poller_timers_get_current_time ();
|
||||||
while (self->len && self->info->when <= now)
|
while (self->len && self->heap[0]->when <= now)
|
||||||
{
|
{
|
||||||
struct poller_timer_info info = *self->info;
|
struct poller_timer *timer = self->heap[0];
|
||||||
poller_timers_remove_at_index (self, 0);
|
poller_timers_remove_at_index (self, 0);
|
||||||
info.dispatcher (info.user_data);
|
timer->dispatcher (timer->user_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -965,49 +975,35 @@ poller_timers_heapify_up (struct poller_timers *self, size_t index)
|
||||||
while (index != 0)
|
while (index != 0)
|
||||||
{
|
{
|
||||||
size_t parent = (index - 1) / 2;
|
size_t parent = (index - 1) / 2;
|
||||||
if (self->info[parent].when <= self->info[index].when)
|
if (self->heap[parent]->when <= self->heap[index]->when)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
struct poller_timer_info tmp = self->info[parent];
|
struct poller_timer *tmp = self->heap[parent];
|
||||||
self->info[parent] = self->info[index];
|
self->heap[parent] = self->heap[index];
|
||||||
self->info[index] = tmp;
|
self->heap[index] = tmp;
|
||||||
|
|
||||||
|
self->heap[parent]->index = parent;
|
||||||
|
self->heap[index] ->index = index;
|
||||||
index = parent;
|
index = parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
poller_timers_find (struct poller_timers *self,
|
|
||||||
poller_timer_fn dispatcher, void *data)
|
|
||||||
{
|
|
||||||
// NOTE: there may be duplicates.
|
|
||||||
for (size_t i = 0; i < self->len; i++)
|
|
||||||
if (self->info[i].dispatcher == dispatcher
|
|
||||||
&& self->info[i].user_data == data)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
poller_timers_find_by_data (struct poller_timers *self, void *data)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < self->len; i++)
|
|
||||||
if (self->info[i].user_data == data)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
poller_timers_add (struct poller_timers *self,
|
poller_timers_set (struct poller_timers *self, struct poller_timer *timer)
|
||||||
poller_timer_fn dispatcher, void *data, int timeout_ms)
|
|
||||||
{
|
{
|
||||||
if (self->len == self->alloc)
|
hard_assert (timer->timers == self);
|
||||||
self->info = xreallocarray (self->info,
|
if (timer->index != -1)
|
||||||
self->alloc <<= 1, sizeof *self->info);
|
{
|
||||||
|
poller_timers_heapify_down (self, timer->index);
|
||||||
|
poller_timers_heapify_up (self, timer->index);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self->info[self->len] = (struct poller_timer_info) {
|
if (self->len == self->alloc)
|
||||||
.when = poller_timers_get_current_time () + timeout_ms,
|
self->heap = xreallocarray (self->heap,
|
||||||
.dispatcher = dispatcher, .user_data = data };
|
self->alloc <<= 1, sizeof *self->heap);
|
||||||
|
self->heap[self->len] = timer;
|
||||||
|
timer->index = self->len;
|
||||||
poller_timers_heapify_up (self, self->len++);
|
poller_timers_heapify_up (self, self->len++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1017,7 +1013,7 @@ poller_timers_get_poll_timeout (struct poller_timers *self)
|
||||||
if (!self->len)
|
if (!self->len)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
int64_t timeout = self->info->when - poller_timers_get_current_time ();
|
int64_t timeout = self->heap[0]->when - poller_timers_get_current_time ();
|
||||||
if (timeout <= 0)
|
if (timeout <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
if (timeout > INT_MAX)
|
if (timeout > INT_MAX)
|
||||||
|
@ -1025,24 +1021,15 @@ poller_timers_get_poll_timeout (struct poller_timers *self)
|
||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
|
|
||||||
// I don't really need this, I've basically implemented this just because I can.
|
|
||||||
|
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
|
|
||||||
struct poller_info
|
|
||||||
{
|
|
||||||
int fd; ///< Our file descriptor
|
|
||||||
short events; ///< The poll() events we registered for
|
|
||||||
poller_dispatcher_fn dispatcher; ///< Event dispatcher
|
|
||||||
void *user_data; ///< User data
|
|
||||||
};
|
|
||||||
|
|
||||||
struct poller
|
struct poller
|
||||||
{
|
{
|
||||||
int epoll_fd; ///< The epoll FD
|
int epoll_fd; ///< The epoll FD
|
||||||
struct poller_info **info; ///< Information associated with each FD
|
struct poller_fd **fds; ///< Information associated with each FD
|
||||||
struct epoll_event *revents; ///< Output array for epoll_wait()
|
struct epoll_event *revents; ///< Output array for epoll_wait()
|
||||||
size_t len; ///< Number of polled descriptors
|
size_t len; ///< Number of polled descriptors
|
||||||
size_t alloc; ///< Number of entries allocated
|
size_t alloc; ///< Number of entries allocated
|
||||||
|
@ -1065,7 +1052,7 @@ poller_init (struct poller *self)
|
||||||
|
|
||||||
self->len = 0;
|
self->len = 0;
|
||||||
self->alloc = POLLER_MIN_ALLOC;
|
self->alloc = POLLER_MIN_ALLOC;
|
||||||
self->info = xcalloc (self->alloc, sizeof *self->info);
|
self->fds = xcalloc (self->alloc, sizeof *self->fds);
|
||||||
self->revents = xcalloc (self->alloc, sizeof *self->revents);
|
self->revents = xcalloc (self->alloc, sizeof *self->revents);
|
||||||
|
|
||||||
poller_timers_init (&self->timers);
|
poller_timers_init (&self->timers);
|
||||||
|
@ -1079,28 +1066,18 @@ poller_free (struct poller *self)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < self->len; i++)
|
for (size_t i = 0; i < self->len; i++)
|
||||||
{
|
{
|
||||||
struct poller_info *info = self->info[i];
|
struct poller_fd *fd = self->fds[i];
|
||||||
hard_assert (epoll_ctl (self->epoll_fd,
|
hard_assert (epoll_ctl (self->epoll_fd,
|
||||||
EPOLL_CTL_DEL, info->fd, (void *) "") != -1);
|
EPOLL_CTL_DEL, fd->fd, (void *) "") != -1);
|
||||||
free (info);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
poller_timers_free (&self->timers);
|
poller_timers_free (&self->timers);
|
||||||
|
|
||||||
xclose (self->epoll_fd);
|
xclose (self->epoll_fd);
|
||||||
free (self->info);
|
free (self->fds);
|
||||||
free (self->revents);
|
free (self->revents);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
poller_find_by_fd (struct poller *self, int fd)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < self->len; i++)
|
|
||||||
if (self->info[i]->fd == fd)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
poller_ensure_space (struct poller *self)
|
poller_ensure_space (struct poller *self)
|
||||||
{
|
{
|
||||||
|
@ -1112,8 +1089,8 @@ poller_ensure_space (struct poller *self)
|
||||||
|
|
||||||
self->revents = xreallocarray
|
self->revents = xreallocarray
|
||||||
(self->revents, sizeof *self->revents, self->alloc);
|
(self->revents, sizeof *self->revents, self->alloc);
|
||||||
self->info = xreallocarray
|
self->fds = xreallocarray
|
||||||
(self->info, sizeof *self->info, self->alloc);
|
(self->fds, sizeof *self->fds, self->alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static short
|
static short
|
||||||
|
@ -1141,41 +1118,33 @@ poller_poll_to_epoll_events (short events)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
poller_set (struct poller *self, int fd, short events,
|
poller_set (struct poller *self, struct poller_fd *fd)
|
||||||
poller_dispatcher_fn dispatcher, void *data)
|
|
||||||
{
|
{
|
||||||
ssize_t index = poller_find_by_fd (self, fd);
|
hard_assert (fd->poller == self);
|
||||||
bool modifying = true;
|
bool modifying = true;
|
||||||
if (index == -1)
|
if (fd->index == -1)
|
||||||
{
|
{
|
||||||
poller_ensure_space (self);
|
poller_ensure_space (self);
|
||||||
self->info[index = self->len++] = xcalloc (1, sizeof **self->info);
|
self->fds[fd->index = self->len++] = fd;
|
||||||
modifying = false;
|
modifying = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct poller_info *info = self->info[index];
|
|
||||||
info->fd = fd;
|
|
||||||
info->events = events;
|
|
||||||
info->dispatcher = dispatcher;
|
|
||||||
info->user_data = data;
|
|
||||||
|
|
||||||
struct epoll_event event;
|
struct epoll_event event;
|
||||||
event.events = poller_poll_to_epoll_events (events);
|
event.events = poller_poll_to_epoll_events (fd->events);
|
||||||
event.data.ptr = info;
|
event.data.ptr = fd;
|
||||||
hard_assert (epoll_ctl (self->epoll_fd,
|
hard_assert (epoll_ctl (self->epoll_fd,
|
||||||
modifying ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &event) != -1);
|
modifying ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd->fd, &event) != -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
poller_remove_from_dispatch (struct poller *self,
|
poller_remove_from_dispatch (struct poller *self, const struct poller_fd *fd)
|
||||||
const struct poller_info *info)
|
|
||||||
{
|
{
|
||||||
if (!self->dispatch_total)
|
if (!self->dispatch_total)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = self->dispatch_next; i < self->dispatch_total; i++)
|
for (i = self->dispatch_next; i < self->dispatch_total; i++)
|
||||||
if (self->revents[i].data.ptr == info)
|
if (self->revents[i].data.ptr == fd)
|
||||||
break;
|
break;
|
||||||
if (i == self->dispatch_total)
|
if (i == self->dispatch_total)
|
||||||
return;
|
return;
|
||||||
|
@ -1188,15 +1157,18 @@ static void
|
||||||
poller_remove_at_index (struct poller *self, size_t index)
|
poller_remove_at_index (struct poller *self, size_t index)
|
||||||
{
|
{
|
||||||
hard_assert (index < self->len);
|
hard_assert (index < self->len);
|
||||||
struct poller_info *info = self->info[index];
|
struct poller_fd *fd = self->fds[index];
|
||||||
|
fd->index = -1;
|
||||||
|
|
||||||
poller_remove_from_dispatch (self, info);
|
poller_remove_from_dispatch (self, fd);
|
||||||
hard_assert (epoll_ctl (self->epoll_fd,
|
hard_assert (epoll_ctl (self->epoll_fd,
|
||||||
EPOLL_CTL_DEL, info->fd, (void *) "") != -1);
|
EPOLL_CTL_DEL, fd->fd, (void *) "") != -1);
|
||||||
|
|
||||||
free (info);
|
|
||||||
if (index != --self->len)
|
if (index != --self->len)
|
||||||
self->info[index] = self->info[self->len];
|
{
|
||||||
|
self->fds[index] = self->fds[self->len];
|
||||||
|
self->fds[index]->index = index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1222,15 +1194,15 @@ poller_run (struct poller *self)
|
||||||
while (self->dispatch_next < self->dispatch_total)
|
while (self->dispatch_next < self->dispatch_total)
|
||||||
{
|
{
|
||||||
struct epoll_event *revents = self->revents + self->dispatch_next;
|
struct epoll_event *revents = self->revents + self->dispatch_next;
|
||||||
struct poller_info *info = revents->data.ptr;
|
struct poller_fd *fd = revents->data.ptr;
|
||||||
|
|
||||||
struct pollfd pfd;
|
struct pollfd pfd;
|
||||||
pfd.fd = info->fd;
|
pfd.fd = fd->fd;
|
||||||
pfd.revents = poller_epoll_to_poll_events (revents->events);
|
pfd.revents = poller_epoll_to_poll_events (revents->events);
|
||||||
pfd.events = info->events;
|
pfd.events = fd->events;
|
||||||
|
|
||||||
self->dispatch_next++;
|
self->dispatch_next++;
|
||||||
info->dispatcher (&pfd, info->user_data);
|
fd->dispatcher (&pfd, fd->user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
self->dispatch_next = 0;
|
self->dispatch_next = 0;
|
||||||
|
@ -1239,16 +1211,10 @@ poller_run (struct poller *self)
|
||||||
|
|
||||||
#else // !__linux__
|
#else // !__linux__
|
||||||
|
|
||||||
struct poller_info
|
|
||||||
{
|
|
||||||
poller_dispatcher_fn dispatcher; ///< Event dispatcher
|
|
||||||
void *user_data; ///< User data
|
|
||||||
};
|
|
||||||
|
|
||||||
struct poller
|
struct poller
|
||||||
{
|
{
|
||||||
struct pollfd *fds; ///< Polled descriptors
|
struct pollfd *fds; ///< Polled descriptors
|
||||||
struct poller_info *fds_info; ///< Additional information for each FD
|
struct poller_fd **fds_data; ///< Additional information for each FD
|
||||||
size_t len; ///< Number of polled descriptors
|
size_t len; ///< Number of polled descriptors
|
||||||
size_t alloc; ///< Number of entries allocated
|
size_t alloc; ///< Number of entries allocated
|
||||||
|
|
||||||
|
@ -1262,7 +1228,7 @@ poller_init (struct poller *self)
|
||||||
self->alloc = POLLER_MIN_ALLOC;
|
self->alloc = POLLER_MIN_ALLOC;
|
||||||
self->len = 0;
|
self->len = 0;
|
||||||
self->fds = xcalloc (self->alloc, sizeof *self->fds);
|
self->fds = xcalloc (self->alloc, sizeof *self->fds);
|
||||||
self->fds_info = xcalloc (self->alloc, sizeof *self->fds_info);
|
self->fds_data = xcalloc (self->alloc, sizeof *self->fds_data);
|
||||||
poller_timers_init (&self->timers);
|
poller_timers_init (&self->timers);
|
||||||
self->dispatch_next = -1;
|
self->dispatch_next = -1;
|
||||||
}
|
}
|
||||||
|
@ -1271,19 +1237,10 @@ static void
|
||||||
poller_free (struct poller *self)
|
poller_free (struct poller *self)
|
||||||
{
|
{
|
||||||
free (self->fds);
|
free (self->fds);
|
||||||
free (self->fds_info);
|
free (self->fds_data);
|
||||||
poller_timers_free (&self->timers);
|
poller_timers_free (&self->timers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
poller_find_by_fd (struct poller *self, int fd)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < self->len; i++)
|
|
||||||
if (self->fds[i].fd == fd)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
poller_ensure_space (struct poller *self)
|
poller_ensure_space (struct poller *self)
|
||||||
{
|
{
|
||||||
|
@ -1292,33 +1249,33 @@ poller_ensure_space (struct poller *self)
|
||||||
|
|
||||||
self->alloc <<= 1;
|
self->alloc <<= 1;
|
||||||
self->fds = xreallocarray (self->fds, sizeof *self->fds, self->alloc);
|
self->fds = xreallocarray (self->fds, sizeof *self->fds, self->alloc);
|
||||||
self->fds_info = xreallocarray
|
self->fds_data = xreallocarray
|
||||||
(self->fds_info, sizeof *self->fds_info, self->alloc);
|
(self->fds_data, sizeof *self->fds_data, self->alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
poller_set (struct poller *self, int fd, short events,
|
poller_set (struct poller *self, struct poller_fd *fd)
|
||||||
poller_dispatcher_fn dispatcher, void *data)
|
|
||||||
{
|
{
|
||||||
ssize_t index = poller_find_by_fd (self, fd);
|
hard_assert (fd->poller == self);
|
||||||
if (index == -1)
|
if (fd->index == -1)
|
||||||
{
|
{
|
||||||
poller_ensure_space (self);
|
poller_ensure_space (self);
|
||||||
index = self->len++;
|
self->fds_data[fd->index = self->len++] = fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pollfd *new_entry = self->fds + index;
|
struct pollfd *new_entry = self->fds + fd->index;
|
||||||
memset (new_entry, 0, sizeof *new_entry);
|
memset (new_entry, 0, sizeof *new_entry);
|
||||||
new_entry->fd = fd;
|
new_entry->fd = fd->fd;
|
||||||
new_entry->events = events;
|
new_entry->events = fd->events;
|
||||||
|
|
||||||
self->fds_info[index] = (struct poller_info) { dispatcher, data };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
poller_remove_at_index (struct poller *self, size_t index)
|
poller_remove_at_index (struct poller *self, size_t index)
|
||||||
{
|
{
|
||||||
hard_assert (index < self->len);
|
hard_assert (index < self->len);
|
||||||
|
struct poller_fd *fd = self->fds_data[index];
|
||||||
|
fd->index = -1;
|
||||||
|
|
||||||
if (index == --self->len)
|
if (index == --self->len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1327,14 +1284,18 @@ poller_remove_at_index (struct poller *self, size_t index)
|
||||||
{
|
{
|
||||||
memmove (self->fds + index, self->fds + index + 1,
|
memmove (self->fds + index, self->fds + index + 1,
|
||||||
(self->len - index) * sizeof *self->fds);
|
(self->len - index) * sizeof *self->fds);
|
||||||
memmove (self->fds_info + index, self->fds_info + index + 1,
|
memmove (self->fds_data + index, self->fds_data + index + 1,
|
||||||
(self->len - index) * sizeof *self->fds_info);
|
(self->len - index) * sizeof *self->fds_data);
|
||||||
|
for (size_t i = index; i < self->len; i++)
|
||||||
|
self->fds_data[i]->index = i;
|
||||||
|
|
||||||
self->dispatch_next--;
|
self->dispatch_next--;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
self->fds[index] = self->fds [self->len];
|
self->fds[index] = self->fds [self->len];
|
||||||
self->fds_info[index] = self->fds_info[self->len];
|
self->fds_data[index] = self->fds_data[self->len];
|
||||||
|
self->fds_data[index]->index = index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1358,10 +1319,10 @@ poller_run (struct poller *self)
|
||||||
for (int i = 0; i < (int) self->len; )
|
for (int i = 0; i < (int) self->len; )
|
||||||
{
|
{
|
||||||
struct pollfd pfd = self->fds[i];
|
struct pollfd pfd = self->fds[i];
|
||||||
struct poller_info *info = self->fds_info + i;
|
struct poller_fd *fd = self->fds_data[i];
|
||||||
self->dispatch_next = ++i;
|
self->dispatch_next = ++i;
|
||||||
if (pfd.revents)
|
if (pfd.revents)
|
||||||
info->dispatcher (&pfd, info->user_data);
|
fd->dispatcher (&pfd, fd->user_data);
|
||||||
i = self->dispatch_next;
|
i = self->dispatch_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1370,6 +1331,55 @@ poller_run (struct poller *self)
|
||||||
|
|
||||||
#endif // !__linux__
|
#endif // !__linux__
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
static void
|
||||||
|
poller_timer_init(struct poller_timer *self, struct poller *poller)
|
||||||
|
{
|
||||||
|
memset (self, 0, sizeof *self);
|
||||||
|
self->timers = &poller->timers;
|
||||||
|
self->index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
poller_timer_set(struct poller_timer *self, int timeout_ms)
|
||||||
|
{
|
||||||
|
self->when = poller_timers_get_current_time () + timeout_ms;
|
||||||
|
poller_timers_set (self->timers, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
poller_timer_reset(struct poller_timer *self)
|
||||||
|
{
|
||||||
|
if (self->index != -1)
|
||||||
|
poller_timers_remove_at_index (self->timers, self->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
|
static void
|
||||||
|
poller_fd_init(struct poller_fd *self, struct poller *poller, int fd)
|
||||||
|
{
|
||||||
|
memset (self, 0, sizeof *self);
|
||||||
|
self->poller = poller;
|
||||||
|
self->index = -1;
|
||||||
|
self->fd = fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
poller_fd_set(struct poller_fd *self, short events)
|
||||||
|
{
|
||||||
|
self->events = events;
|
||||||
|
poller_set (self->poller, self);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
poller_fd_reset(struct poller_fd *self)
|
||||||
|
{
|
||||||
|
if (self->index != -1)
|
||||||
|
poller_remove_at_index (self->poller, self->index);
|
||||||
|
}
|
||||||
|
|
||||||
// --- Utilities ---------------------------------------------------------------
|
// --- Utilities ---------------------------------------------------------------
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
Loading…
Reference in New Issue