/* * Ivy, C interface * * Copyright (C) 1997-2000 * Centre d'Études de la Navigation Aérienne * * Main loop based on select * * Authors: François-Régis Colin * Stéphane Chatty * * $Id$ * * Please refer to file version.h for the * copyright notice regarding this software */ #ifdef WIN32 #include #endif #include #include #include #include #include #ifndef WIN32 #include #include #include #include #include #include #include #include #endif #include "list.h" #include "ivychannel.h" #include "ivyloop.h" #include "timer.h" struct _channel { Channel next; HANDLE fd; void *data; int tobedeleted; ChannelHandleDelete handle_delete; ChannelHandleRead handle_read; }; static Channel channels_list = NULL; static int channel_initialized = 0; static fd_set open_fds; static int MainLoop = 1; #ifdef WIN32 WSADATA WsaData; #endif void IvyChannelRemove (Channel channel) { channel->tobedeleted = 1; } static void IvyChannelDelete (Channel channel) { if (channel->handle_delete) (*channel->handle_delete) (channel->data); FD_CLR (channel->fd, &open_fds); IVY_LIST_REMOVE (channels_list, channel); } static void ChannelDefferedDelete () { Channel channel, next; IVY_LIST_EACH_SAFE (channels_list, channel,next) { if (channel->tobedeleted ) { IvyChannelDelete (channel); } } } Channel IvyChannelAdd (HANDLE fd, void *data, ChannelHandleDelete handle_delete, ChannelHandleRead handle_read ) { Channel channel; IVY_LIST_ADD_START (channels_list, channel) channel->fd = fd; channel->tobedeleted = 0; channel->handle_delete = handle_delete; channel->handle_read = handle_read; channel->data = data; IVY_LIST_ADD_END (channels_list, channel) FD_SET (channel->fd, &open_fds); return channel; } static void IvyChannelHandleRead (fd_set *current) { Channel channel, next; IVY_LIST_EACH_SAFE (channels_list, channel, next) { if (FD_ISSET (channel->fd, current)) { (*channel->handle_read)(channel,channel->fd,channel->data); } } } static void IvyChannelHandleExcpt (fd_set *current) { Channel channel,next; IVY_LIST_EACH_SAFE (channels_list, channel, next) { if (FD_ISSET (channel->fd, current)) { if (channel->handle_delete) (*channel->handle_delete)(channel->data); /* IvyChannelClose (channel); */ } } } void IvyChannelInit (void) { #ifdef WIN32 int error; #else /* pour eviter les plantages quand les autres applis font core-dump */ signal (SIGPIPE, SIG_IGN); #endif if (channel_initialized) return; FD_ZERO (&open_fds); #ifdef WIN32 error = WSAStartup (0x0101, &WsaData); if (error == SOCKET_ERROR) { printf ("WSAStartup failed.\n"); } #endif channel_initialized = 1; } void IvyChannelStop (void) { MainLoop = 0; } void IvyMainLoop(void(*BeforeSelect)(void),void(*AfterSelect)(void)) { fd_set rdset; fd_set exset; int ready; while (MainLoop) { ChannelDefferedDelete(); if (BeforeSelect) (*BeforeSelect)(); rdset = open_fds; exset = open_fds; ready = select(64, &rdset, 0, &exset, TimerGetSmallestTimeout()); /* for compatibility with older version we test also the first parameter */ if (BeforeSelect && AfterSelect) (*AfterSelect)(); if (ready < 0 && (errno != EINTR)) { fprintf (stderr, "select error %d\n",errno); perror("select"); return; } TimerScan(); if (ready > 0) { IvyChannelHandleExcpt(&exset); IvyChannelHandleRead(&rdset); } } } void IvyIdle() { fd_set rdset; fd_set exset; int ready; struct timeval timeout = {0,0}; ChannelDefferedDelete(); rdset = open_fds; exset = open_fds; ready = select(64, &rdset, 0, &exset, &timeout); if (ready < 0 && (errno != EINTR)) { fprintf (stderr, "select error %d\n",errno); perror("select"); return; } if (ready > 0) { IvyChannelHandleExcpt(&exset); IvyChannelHandleRead(&rdset); } }