1 #include <unistd.h>
2 #include <sys/time.h>
3 #include <errno.h>
4 #include "io_internal.h"
5 
6 #ifdef __MINGW32__
7 #include <stdio.h>
8 #endif
9 
10 void io_wantread_really(int64 d, io_entry* e);
11 
io_canread()12 int64 io_canread() {
13   io_entry* e;
14 
15 #if defined(HAVE_SIGIO)
16   /* We promise that the user can call io_canread() and read, and
17     * the user uses io_tryread or calls io_eagain_read to signal if
18     * there is no more data to read. That means if the user does not
19     * call io_eagain_read, we need to know which fd it was so we can
20     * keep it in the alternative queue. */
21   if (alt_curread!=-1) {
22     e=iarray_get(&io_fds,alt_curread);
23     e->next_read=alt_firstread;
24     alt_firstread=alt_curread;
25     alt_curread=-1;
26   }
27 #endif
28 
29   if (first_readable==-1)
30 #if defined(HAVE_SIGIO)
31   {
32     if (alt_firstread>=0 && (e=iarray_get(&io_fds,alt_firstread)) && e->canread) {
33       debug_printf(("io_canread: normal read queue is empty, swapping in alt read queue (starting with %ld)\n",alt_firstread));
34       first_readable=alt_firstread;
35       alt_firstread=-1;
36     } else
37       return -1;
38   }
39 #else
40     return -1;
41 #endif
42   for (;;) {
43     int64 r;
44     e=iarray_get(&io_fds,first_readable);
45     if (!e) break;
46     r=first_readable;
47     first_readable=e->next_read;
48     e->next_read=-1;
49     debug_printf(("io_canread: dequeue %lld from normal read queue (next is %ld)\n",r,first_readable));
50 
51     if (e->closed) {
52       /* The fd was previously closed, but there were still open events on it.
53        * To prevent race conditions, we did not actually close the fd
54        * but only marked it as closed, so we can skip this event here
55        * and really closed it now. */
56       io_close(r);
57       continue;
58     }
59 
60 #ifdef __MINGW32__
61 //    printf("event on %d: wr %d rq %d aq %d\n",(int)r,e->wantread,e->readqueued,e->acceptqueued);
62 #endif
63 
64     if (e->wantread &&
65 #ifdef __MINGW32__
66 		       (e->canread || e->acceptqueued==1 || e->readqueued==1)
67 #else
68 			e->canread
69 #endif
70 				  ) {
71 #if defined(HAVE_SIGIO)
72 #if 0
73       /* this code violates an invariant that the other code has, namely
74        * that e->next_read is -1 once the fd is dequeued. */
75       e->next_read=alt_firstread;
76       alt_firstread=r;
77       debug_printf(("io_canread: enqueue %ld in alt read queue (next is %ld)\n",alt_firstread,e->next_read));
78 #else
79       alt_curread=r;
80 #endif
81       if (io_waitmode!=_SIGIO)
82 #endif
83 	e->canread=0;
84       if (!e->kernelwantread)
85 	io_wantread_really(r,e);
86       return r;
87     }
88   }
89   return -1;
90 }
91