Cygwin: FIFO: update select
Add static functions peek_fifo, thread_fifo, start_thread_fifo, and fifo_cleanup to select.cc. These are based on the corresponding pipe functions, the main difference being that peek_fifo loops through the connected clients to see if any of them have data available for reading. Add the fhandler_fifo methods select_read, select_write, and select_except. Add accessor methods get_nclients, get_handle, and is_connected that are needed by peek_fifo.
This commit is contained in:
parent
1aa438a94c
commit
ee394c311e
|
@ -1278,6 +1278,10 @@ class fhandler_fifo: public fhandler_base
|
|||
public:
|
||||
fhandler_fifo ();
|
||||
bool hit_eof ();
|
||||
int get_nclients () const { return nclients; }
|
||||
HANDLE& get_handle () { return fhandler_base::get_handle (); }
|
||||
HANDLE get_handle (int i) const { return client[i].fh->get_handle (); }
|
||||
bool is_connected (int i) const { return client[i].state == fc_connected; }
|
||||
PUNICODE_STRING get_pipe_name ();
|
||||
DWORD listen_client_thread ();
|
||||
void fifo_client_lock () { _fifo_client_lock.lock (); }
|
||||
|
|
|
@ -822,17 +822,148 @@ fhandler_pipe::select_except (select_stuff *ss)
|
|||
return s;
|
||||
}
|
||||
|
||||
static int
|
||||
peek_fifo (select_record *s, bool from_select)
|
||||
{
|
||||
if (cygheap->fdtab.not_open (s->fd))
|
||||
{
|
||||
s->thread_errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int gotone = 0;
|
||||
fhandler_fifo *fh = (fhandler_fifo *) s->fh;
|
||||
|
||||
if (s->read_selected)
|
||||
{
|
||||
if (s->read_ready)
|
||||
{
|
||||
select_printf ("%s, already ready for read", fh->get_name ());
|
||||
gotone = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fh->get_readahead_valid ())
|
||||
{
|
||||
select_printf ("readahead");
|
||||
gotone = s->read_ready = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (fh->hit_eof ())
|
||||
{
|
||||
select_printf ("read: %s, saw EOF", fh->get_name ());
|
||||
gotone = s->read_ready = true;
|
||||
if (s->except_selected)
|
||||
gotone += s->except_ready = true;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fh->fifo_client_lock ();
|
||||
for (int i = 0; i < fh->get_nclients (); i++)
|
||||
if (fh->is_connected (i))
|
||||
{
|
||||
int n = pipe_data_available (s->fd, fh, fh->get_handle (i),
|
||||
false);
|
||||
if (n > 0)
|
||||
{
|
||||
select_printf ("read: %s, ready for read: avail %d, client %d",
|
||||
fh->get_name (), n, i);
|
||||
fh->fifo_client_unlock ();
|
||||
gotone += s->read_ready = true;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
fh->fifo_client_unlock ();
|
||||
}
|
||||
out:
|
||||
if (s->write_selected)
|
||||
{
|
||||
gotone += s->write_ready
|
||||
= pipe_data_available (s->fd, fh, fh->get_handle (), true);
|
||||
select_printf ("write: %s, gotone %d", fh->get_name (), gotone);
|
||||
}
|
||||
return gotone;
|
||||
}
|
||||
|
||||
static int start_thread_fifo (select_record *me, select_stuff *stuff);
|
||||
|
||||
static DWORD WINAPI
|
||||
thread_fifo (void *arg)
|
||||
{
|
||||
select_fifo_info *pi = (select_fifo_info *) arg;
|
||||
DWORD sleep_time = 0;
|
||||
bool looping = true;
|
||||
|
||||
while (looping)
|
||||
{
|
||||
for (select_record *s = pi->start; (s = s->next); )
|
||||
if (s->startup == start_thread_fifo)
|
||||
{
|
||||
if (peek_fifo (s, true))
|
||||
looping = false;
|
||||
if (pi->stop_thread)
|
||||
{
|
||||
select_printf ("stopping");
|
||||
looping = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!looping)
|
||||
break;
|
||||
Sleep (sleep_time >> 3);
|
||||
if (sleep_time < 80)
|
||||
++sleep_time;
|
||||
if (pi->stop_thread)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
start_thread_fifo (select_record *me, select_stuff *stuff)
|
||||
{
|
||||
select_fifo_info *pi = stuff->device_specific_fifo;
|
||||
if (pi->start)
|
||||
me->h = *((select_fifo_info *) stuff->device_specific_fifo)->thread;
|
||||
else
|
||||
{
|
||||
pi->start = &stuff->start;
|
||||
pi->stop_thread = false;
|
||||
pi->thread = new cygthread (thread_fifo, pi, "fifosel");
|
||||
me->h = *pi->thread;
|
||||
if (!me->h)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
fifo_cleanup (select_record *, select_stuff *stuff)
|
||||
{
|
||||
select_fifo_info *pi = (select_fifo_info *) stuff->device_specific_fifo;
|
||||
if (!pi)
|
||||
return;
|
||||
if (pi->thread)
|
||||
{
|
||||
pi->stop_thread = true;
|
||||
pi->thread->detach ();
|
||||
}
|
||||
delete pi;
|
||||
stuff->device_specific_fifo = NULL;
|
||||
}
|
||||
|
||||
select_record *
|
||||
fhandler_fifo::select_read (select_stuff *ss)
|
||||
{
|
||||
if (!ss->device_specific_pipe
|
||||
&& (ss->device_specific_pipe = new select_pipe_info) == NULL)
|
||||
if (!ss->device_specific_fifo
|
||||
&& (ss->device_specific_fifo = new select_fifo_info) == NULL)
|
||||
return NULL;
|
||||
select_record *s = ss->start.next;
|
||||
s->startup = start_thread_pipe;
|
||||
s->peek = peek_pipe;
|
||||
s->startup = start_thread_fifo;
|
||||
s->peek = peek_fifo;
|
||||
s->verify = verify_ok;
|
||||
s->cleanup = pipe_cleanup;
|
||||
s->cleanup = fifo_cleanup;
|
||||
s->read_selected = true;
|
||||
s->read_ready = false;
|
||||
return s;
|
||||
|
@ -841,14 +972,14 @@ fhandler_fifo::select_read (select_stuff *ss)
|
|||
select_record *
|
||||
fhandler_fifo::select_write (select_stuff *ss)
|
||||
{
|
||||
if (!ss->device_specific_pipe
|
||||
&& (ss->device_specific_pipe = new select_pipe_info) == NULL)
|
||||
if (!ss->device_specific_fifo
|
||||
&& (ss->device_specific_fifo = new select_fifo_info) == NULL)
|
||||
return NULL;
|
||||
select_record *s = ss->start.next;
|
||||
s->startup = start_thread_pipe;
|
||||
s->peek = peek_pipe;
|
||||
s->startup = start_thread_fifo;
|
||||
s->peek = peek_fifo;
|
||||
s->verify = verify_ok;
|
||||
s->cleanup = pipe_cleanup;
|
||||
s->cleanup = fifo_cleanup;
|
||||
s->write_selected = true;
|
||||
s->write_ready = false;
|
||||
return s;
|
||||
|
@ -857,14 +988,14 @@ fhandler_fifo::select_write (select_stuff *ss)
|
|||
select_record *
|
||||
fhandler_fifo::select_except (select_stuff *ss)
|
||||
{
|
||||
if (!ss->device_specific_pipe
|
||||
&& (ss->device_specific_pipe = new select_pipe_info) == NULL)
|
||||
if (!ss->device_specific_fifo
|
||||
&& (ss->device_specific_fifo = new select_fifo_info) == NULL)
|
||||
return NULL;
|
||||
select_record *s = ss->start.next;
|
||||
s->startup = start_thread_pipe;
|
||||
s->peek = peek_pipe;
|
||||
s->startup = start_thread_fifo;
|
||||
s->peek = peek_fifo;
|
||||
s->verify = verify_ok;
|
||||
s->cleanup = pipe_cleanup;
|
||||
s->cleanup = fifo_cleanup;
|
||||
s->except_selected = true;
|
||||
s->except_ready = false;
|
||||
return s;
|
||||
|
|
|
@ -53,6 +53,11 @@ struct select_pipe_info: public select_info
|
|||
select_pipe_info (): select_info () {}
|
||||
};
|
||||
|
||||
struct select_fifo_info: public select_info
|
||||
{
|
||||
select_fifo_info (): select_info () {}
|
||||
};
|
||||
|
||||
struct select_socket_info: public select_info
|
||||
{
|
||||
int num_w4;
|
||||
|
@ -89,6 +94,7 @@ public:
|
|||
select_record start;
|
||||
|
||||
select_pipe_info *device_specific_pipe;
|
||||
select_fifo_info *device_specific_fifo;
|
||||
select_socket_info *device_specific_socket;
|
||||
select_serial_info *device_specific_serial;
|
||||
select_signalfd_info *device_specific_signalfd;
|
||||
|
@ -102,6 +108,7 @@ public:
|
|||
select_stuff (): return_on_signal (false), always_ready (false),
|
||||
windows_used (false), start (),
|
||||
device_specific_pipe (NULL),
|
||||
device_specific_fifo (NULL),
|
||||
device_specific_socket (NULL),
|
||||
device_specific_serial (NULL),
|
||||
device_specific_signalfd (NULL) {}
|
||||
|
|
Loading…
Reference in New Issue