]> sourceware.org Git - newlib-cygwin.git/commitdiff
Cygwin: FIFO: update select
authorKen Brown <kbrown@cornell.edu>
Fri, 22 Mar 2019 19:30:41 +0000 (19:30 +0000)
committerCorinna Vinschen <corinna@vinschen.de>
Wed, 27 Mar 2019 13:01:45 +0000 (14:01 +0100)
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.

winsup/cygwin/fhandler.h
winsup/cygwin/select.cc
winsup/cygwin/select.h

index 0ebc44e0ddf36dbb3e9212a85390f855131144c4..f6982f0ba96d54afcf601332889d5475193fd8cd 100644 (file)
@@ -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 (); }
index 59325860d8c80f08003eafea947c096a4937bb15..991494aa88f9734e7ebabebe5df24d6937f9e4ec 100644 (file)
@@ -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;
index 71821f76cfb0e665291b84c5b26bb4f182279774..19f9d7dc24349b1ed3015f60fd20cc59a8f783f8 100644 (file)
@@ -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) {}
This page took 0.04141 seconds and 5 git commands to generate.