Main Page | Class List | Directories | File List | Class Members | File Members

select-module.c

Go to the documentation of this file.
00001 /* Copyright (c) 2001 John E. Davis
00002  * This file is part of the S-Lang library.
00003  *
00004  * You may distribute under the terms of either the GNU General Public
00005  * License or the Perl Artistic License.
00006  */
00007 #include <stdio.h>
00008 #include <slang.h>
00009 
00010 #include <sys/time.h>
00011 #include <sys/types.h>
00012 #include <unistd.h>
00013 #include <string.h>
00014 #include <errno.h>
00015 
00016 SLANG_MODULE(select);
00017 
00018 static int pop_fd_set (SLang_Array_Type **ats, 
00019                        fd_set **fd_set_p, fd_set *fd_set_buf, 
00020                        int *max_n)
00021 {
00022    unsigned int num, i;
00023    SLang_Array_Type *at;
00024    SLFile_FD_Type **f;
00025 
00026    *ats = NULL;
00027    *fd_set_p = NULL;
00028 
00029    if (SLang_peek_at_stack () == SLANG_NULL_TYPE)
00030      return SLang_pop_null ();
00031 
00032    if (-1 == SLang_pop_array_of_type (&at, SLANG_FILE_FD_TYPE))
00033      return -1;
00034 
00035    FD_ZERO(fd_set_buf);
00036    *fd_set_p = fd_set_buf;
00037 
00038    *ats = at;
00039    num = at->num_elements;
00040    f = (SLFile_FD_Type **) at->data;
00041    
00042    for (i = 0; i < num; i++)
00043      {
00044         int fd;
00045         
00046         if (-1 == SLfile_get_fd (f[i], &fd))
00047           continue;
00048         
00049         if (fd > *max_n)
00050           *max_n = fd;
00051         
00052         FD_SET(fd, fd_set_buf);
00053      }
00054 
00055    return 0;
00056 }
00057 
00058 static SLang_Array_Type *do_fdisset (int nready, SLang_Array_Type *fds, fd_set *fdset)
00059 {
00060    SLang_Array_Type *at;
00061    int i, num;
00062    SLFile_FD_Type **f;
00063    SLindex_Type ind_nready;
00064 
00065    if (fds == NULL)
00066      nready = 0;
00067 
00068    if (nready)
00069      {
00070         nready = 0;
00071         num = fds->num_elements;
00072         f = (SLFile_FD_Type **) fds->data;
00073         for (i = 0; i < num; i++)
00074           {
00075              int fd;
00076         
00077              if (-1 == SLfile_get_fd (f[i], &fd))
00078                continue;
00079         
00080              if (FD_ISSET(fd, fdset))
00081                nready++;
00082           }
00083      }
00084    
00085    ind_nready = (SLindex_Type) nready;
00086    at = SLang_create_array (SLANG_INT_TYPE, 0, NULL, &ind_nready, 1);
00087    if (at == NULL)
00088      return NULL;
00089 
00090    if (nready)
00091      {
00092         int *indx = (int *) at->data;
00093         f = (SLFile_FD_Type **) fds->data;
00094         num = fds->num_elements;
00095         for (i = 0; i < num; i++)
00096           {
00097              int fd;
00098         
00099              if (-1 == SLfile_get_fd (f[i], &fd))
00100                continue;
00101         
00102              if (FD_ISSET(fd, fdset))
00103                *indx++ = (int) i;
00104           }
00105      }
00106    
00107    return at;
00108 }
00109 
00110 static int push_select_struct (int num, 
00111                                SLang_Array_Type *at_read,
00112                                SLang_Array_Type *at_write,
00113                                SLang_Array_Type *at_except,
00114                                fd_set *readfs, fd_set *writefds, fd_set *exceptfds)
00115 {
00116    char *field_names [4];
00117    SLtype field_types[4];
00118    VOID_STAR field_values [4];
00119    SLang_Array_Type *iread, *iwrite, *iexcept;
00120 
00121    iread = iwrite = iexcept = NULL;
00122 
00123    field_names[0] = "nready";
00124    field_names[1] = "iread";
00125    field_names[2] = "iwrite";
00126    field_names[3] = "iexcept";
00127    field_types[0] = SLANG_INT_TYPE;
00128    field_types[1] = SLANG_ARRAY_TYPE;
00129    field_types[2] = SLANG_ARRAY_TYPE;
00130    field_types[3] = SLANG_ARRAY_TYPE;
00131    field_values[0] = &num;
00132    
00133    if ((NULL == (iread = do_fdisset (num, at_read, readfs)))
00134        || (NULL == (iwrite = do_fdisset (num, at_write, writefds)))
00135        || (NULL == (iexcept = do_fdisset (num, at_except, exceptfds))))
00136      {
00137         SLang_free_array (iread);
00138         SLang_free_array (iwrite);
00139         return -1;
00140      }
00141    
00142    field_values[1] = &iread;
00143    field_values[2] = &iwrite;
00144    field_values[3] = &iexcept;
00145 
00146    /* Note: This function call pushes the struct and frees it upon error. */
00147    return SLstruct_create_struct (4, field_names, field_types, field_values);
00148 }
00149 
00150                                
00151 /* Usage: Struct_Type select (R[],W[],E[],TIME) */
00152 
00153 static void select_intrin (double *secsp)
00154 {
00155    SLang_Array_Type *at_read, *at_write, *at_except;
00156    fd_set readfs_buf, writefds_buf, exceptfds_buf;
00157    fd_set readfs_save_buf, writefds_save_buf, exceptfds_save_buf;
00158    fd_set *readfs, *writefds, *exceptfds;
00159    struct timeval tv, *tv_ptr;
00160    double secs;
00161    int ret, n;
00162 
00163    secs = *secsp;
00164    if (secs < 0.0) tv_ptr = NULL;
00165    else
00166      {
00167         tv.tv_sec = (unsigned long) secs;
00168         tv.tv_usec = (unsigned long) ((secs - tv.tv_sec) * 1e6);
00169         tv_ptr = &tv;
00170      }
00171 
00172    n = 0;
00173    if (-1 == pop_fd_set (&at_except, &exceptfds, &exceptfds_buf, &n))
00174      return;
00175    if (-1 == pop_fd_set (&at_write, &writefds, &writefds_buf, &n))
00176      {
00177         SLang_free_array (at_except);
00178         return;
00179      }
00180    if (-1 == pop_fd_set (&at_read, &readfs, &readfs_buf, &n))
00181      goto free_return;
00182 
00183    readfs_save_buf = readfs_buf;
00184    writefds_save_buf = writefds_buf;
00185    exceptfds_save_buf = exceptfds_buf;
00186 
00187    n += 1;
00188    while (-1 == (ret = select (n, readfs, writefds, exceptfds, tv_ptr)))
00189      {
00190 #ifdef EINTR
00191         if (errno == EINTR)
00192           {
00193              readfs_buf = readfs_save_buf;
00194              writefds_buf = writefds_save_buf;
00195              exceptfds_buf = exceptfds_save_buf;
00196              continue;
00197           }
00198 #endif
00199         (void) SLerrno_set_errno (errno);
00200         break;
00201      }
00202    
00203    if (ret == -1)
00204      (void) SLang_push_null ();
00205    else
00206      (void) push_select_struct (ret, at_read, at_write, at_except,
00207                                 readfs, writefds, exceptfds);
00208 
00209    
00210    free_return:
00211    SLang_free_array (at_read);
00212    SLang_free_array (at_write);
00213    SLang_free_array (at_except);
00214 }
00215 
00216 static SLang_Intrin_Fun_Type Select_Intrinsics [] =
00217 {
00218    MAKE_INTRINSIC_1("select", select_intrin, SLANG_VOID_TYPE, SLANG_DOUBLE_TYPE),
00219    SLANG_END_INTRIN_FUN_TABLE
00220 };
00221    
00222 
00223 int init_select_module_ns (char *ns_name)
00224 {
00225    SLang_NameSpace_Type *ns;
00226 
00227    ns = SLns_create_namespace (ns_name);
00228    if (ns == NULL)
00229      return -1;
00230 
00231    if (-1 == SLns_add_intrin_fun_table (ns, Select_Intrinsics, "__SELECT__"))
00232      return -1;
00233 
00234    return 0;
00235 }
00236 
00237 /* This function is optional */
00238 void deinit_select_module (void)
00239 {
00240 }

© sourcejam.com 2005-2008