factor/native/iomux.c

165 lines
2.9 KiB
C

#include "factor.h"
void init_io_tasks(fd_set* fdset, IO_TASK* io_tasks)
{
int i;
FD_ZERO(fdset);
for(i = 0; i < FD_SETSIZE; i++)
{
read_io_tasks[i].port = F;
read_io_tasks[i].callback = F;
}
}
void init_iomux(void)
{
read_fd_count = 0;
init_io_tasks(&read_fd_set,read_io_tasks);
write_fd_count = 0;
init_io_tasks(&write_fd_set,write_io_tasks);
}
IO_TASK* add_io_task_impl(
IO_TASK_TYPE type,
PORT* port,
CELL callback,
IO_TASK* io_tasks,
int* fd_count)
{
int fd = port->fd;
io_tasks[fd].type = type;
io_tasks[fd].port = tag_object(port);
io_tasks[fd].callback = callback;
if(fd >= *fd_count)
*fd_count = fd + 1;
return &io_tasks[fd];
}
IO_TASK* add_io_task(IO_TASK_TYPE type, PORT* port, CELL callback)
{
switch(type)
{
case IO_TASK_READ_LINE:
case IO_TASK_READ_COUNT:
return add_io_task_impl(type,port,callback,
read_io_tasks,&read_fd_count);
case IO_TASK_WRITE:
return add_io_task_impl(type,port,callback,
write_io_tasks,&write_fd_count);
default:
fatal_error("Invalid IO_TASK_TYPE",type);
return NULL;
}
}
void remove_io_task_impl(
IO_TASK_TYPE type,
PORT* port,
IO_TASK* io_tasks,
int* fd_count)
{
int fd = port->fd;
io_tasks[fd].port = F;
io_tasks[fd].callback = F;
if(fd == *fd_count - 1)
*fd_count = *fd_count - 1;
}
void remove_io_task(IO_TASK_TYPE type, PORT* port)
{
switch(type)
{
case IO_TASK_READ_LINE:
case IO_TASK_READ_COUNT:
remove_io_task_impl(type,port,read_io_tasks,&read_fd_count);
break;
case IO_TASK_WRITE:
remove_io_task_impl(type,port,write_io_tasks,&write_fd_count);
break;
}
}
void perform_io_task(IO_TASK* task)
{
if(task->port == F)
return;
switch(task->type)
{
case IO_TASK_READ_LINE:
break;
case IO_TASK_WRITE:
write_step(untag_port(task->port));
break;
default:
critical_error("Bad I/O task",task->type);
break;
}
}
bool set_up_fd_set(fd_set* fdset, IO_TASK* io_tasks)
{
bool retval = false;
int i;
for(i = 0; i < read_fd_count; i++)
{
if(read_io_tasks[i].port != F)
{
retval = true;
FD_SET(i,&read_fd_set);
}
}
return retval;
}
/* Wait for I/O and return a callback. */
CELL iomux(void)
{
bool reading = set_up_fd_set(&read_fd_set,read_io_tasks);
bool writing = set_up_fd_set(&write_fd_set,write_io_tasks);
if(!reading && !writing)
fatal_error("iomux() called with no IO tasks",0);
select(read_fd_count > write_fd_count
? read_fd_count : write_fd_count,
(reading ? &read_fd_set : NULL),
(writing ? &write_fd_set : NULL),
NULL,NULL);
/* for(i = 0; i < read_fd_count; i++)
perform_io_task(&read_io_tasks[i]);
for(i = 0; i < write_fd_count; i++)
perform_io_task(&write_io_tasks[i]); */
return F;
}
void collect_io_tasks(void)
{
int i;
for(i = 0; i < FD_SETSIZE; i++)
{
copy_object(&read_io_tasks[i].port);
copy_object(&read_io_tasks[i].callback);
}
for(i = 0; i < FD_SETSIZE; i++)
{
copy_object(&write_io_tasks[i].port);
copy_object(&write_io_tasks[i].callback);
}
}