blob: 30ae2c1c24ad572be635d49fa1398757b6862765 [file] [log] [blame]
/*
* Twin - A Tiny Window System
* Copyright © 2004 Keith Packard <keithp@keithp.com>
* All rights reserved.
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with the Twin Library; see the file COPYING. If not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "twinint.h"
#include <sys/poll.h>
#include <assert.h>
#include <unistd.h>
static twin_queue_t *head;
static twin_order_t
_twin_file_order (twin_queue_t *a, twin_queue_t *b)
{
twin_file_t *af = (twin_file_t *) a;
twin_file_t *bf = (twin_file_t *) b;
if (af->file < bf->file)
return TWIN_BEFORE;
if (af->file > bf->file)
return TWIN_AFTER;
return TWIN_AT;
}
void
_twin_run_file (twin_time_t delay)
{
twin_file_t *first;
twin_file_t *file;
int n;
int i;
int r;
short events;
twin_file_op_t op;
struct pollfd *polls;
first = (twin_file_t *) _twin_queue_set_order (&head);
if (first)
{
for (file = first, n = 0; file; file = (twin_file_t *) file->queue.order, n++);
polls = malloc (n * sizeof (struct pollfd));
if (!polls)
return;
for (file = first, i = 0; file; file = (twin_file_t *) file->queue.order, i++)
{
short events = 0;
if (file->ops & TWIN_READ)
events |= POLLIN;
if (file->ops & TWIN_WRITE)
events |= POLLOUT;
polls[i].fd = file->file;
polls[i].events = events;
}
r = poll (polls, n, delay);
if (r > 0)
for (file = first, i = 0; file; file = (twin_file_t *) file->queue.order, i++)
{
events = polls[i].revents;
assert (polls[i].fd == file->file);
op = 0;
if (events & POLLIN)
op |= TWIN_READ;
if (events & POLLOUT)
op |= TWIN_WRITE;
if (op && !(*file->proc) (file->file, op, file->closure))
_twin_queue_delete (&head, &file->queue);
}
_twin_queue_review_order (&first->queue);
free (polls);
}
else
{
if (delay > 0)
usleep (delay * 1000);
}
}
twin_file_t *
twin_set_file (twin_file_proc_t file_proc,
int fd,
twin_file_op_t ops,
void *closure)
{
twin_file_t *file = malloc (sizeof (twin_file_t));
if (!file)
return 0;
file->file = fd;
file->proc = file_proc;
file->ops = ops;
file->closure = closure;
_twin_queue_insert (&head, _twin_file_order, &file->queue);
return file;
}
void
twin_clear_file (twin_file_t *file)
{
_twin_queue_delete (&head, &file->queue);
}