[Gpg4win-commits] r105 - in trunk: . patches patches/glib-2.8.4

scm-commit at wald.intevation.org scm-commit at wald.intevation.org
Tue Jan 3 14:56:27 CET 2006


Author: marcus
Date: 2006-01-03 14:56:27 +0100 (Tue, 03 Jan 2006)
New Revision: 105

Added:
   trunk/patches/glib-2.8.4/
   trunk/patches/glib-2.8.4/01-giowin32.patch
Modified:
   trunk/ChangeLog
Log:
2006-01-03  Marcus Brinkmann  <marcus at g10code.de>

	* patches/glib-2.8.4/01-giowin32.patch: New file.


Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2005-12-31 12:45:27 UTC (rev 104)
+++ trunk/ChangeLog	2006-01-03 13:56:27 UTC (rev 105)
@@ -1,3 +1,7 @@
+2006-01-03  Marcus Brinkmann  <marcus at g10code.de>
+
+	* patches/glib-2.8.4/01-giowin32.patch: New file.
+
 2005-12-31  Marcus Brinkmann  <marcus at g10code.de>
 
 	* glib/02-windres.patch: New file.

Added: trunk/patches/glib-2.8.4/01-giowin32.patch
===================================================================
--- trunk/patches/glib-2.8.4/01-giowin32.patch	2005-12-31 12:45:27 UTC (rev 104)
+++ trunk/patches/glib-2.8.4/01-giowin32.patch	2006-01-03 13:56:27 UTC (rev 105)
@@ -0,0 +1,338 @@
+#! /bin/sh
+patch -p1 -f $* < $0
+exit $?
+
+Implement write support for fd I/O channels in glib on W32 targets.
+
+(no changelog yet)
+
+diff -rup glib-2.8.4-old/glib/giowin32.c glib-2.8.4/glib/giowin32.c
+--- glib-2.8.4-old/glib/giowin32.c	2005-11-08 09:35:50.000000000 +0100
++++ glib-2.8.4/glib/giowin32.c	2006-01-03 14:51:04.000000000 +0100
+@@ -90,7 +90,8 @@ struct _GIOWin32Channel {
+   gushort revents;
+ 
+   /* Following fields used by fd channels for input */
+-  
++  int direction;
++
+   /* Data is kept in a circular buffer. To be able to distinguish between
+    * empty and full buffer, we cannot fill it completely, but have to
+    * leave a one character gap.
+@@ -376,6 +377,7 @@ create_events (GIOWin32Channel *channel)
+     }
+ }
+ 
++
+ static unsigned __stdcall
+ read_thread (void *parameter)
+ {
+@@ -392,6 +394,7 @@ read_thread (void *parameter)
+ 	     (guint) channel->data_avail_event,
+ 	     (guint) channel->space_avail_event);
+   
++  channel->direction = 0;
+   channel->buffer = g_malloc (BUFFER_SIZE);
+   channel->rdp = channel->wrp = 0;
+   channel->running = TRUE;
+@@ -437,7 +440,12 @@ read_thread (void *parameter)
+       UNLOCK (channel->mutex);
+ 
+       nbytes = read (channel->fd, buffer, nbytes);
+-      
++      //      {
++      //	DWORD nb;
++      //	ReadFile (_get_osfhandle (channel->fd), buffer, nbytes, &nb, NULL);
++      //	nbytes = nb;
++      //      }
++
+       LOCK (channel->mutex);
+ 
+       channel->revents = G_IO_IN;
+@@ -486,6 +494,121 @@ read_thread (void *parameter)
+   return 0;
+ }
+ 
++
++static unsigned __stdcall
++write_thread (void *parameter)
++{
++  GIOWin32Channel *channel = parameter;
++  guchar *buffer;
++  guint nbytes;
++
++  g_io_channel_ref ((GIOChannel *)channel);
++
++  if (channel->debug)
++    g_print ("write_thread %#x: start fd:%d, data_avail:%#x space_avail:%#x\n",
++	     channel->thread_id,
++	     channel->fd,
++	     (guint) channel->data_avail_event,
++	     (guint) channel->space_avail_event);
++  
++  channel->direction = 1;
++  channel->buffer = g_malloc (BUFFER_SIZE);
++  channel->rdp = channel->wrp = 0;
++  channel->running = TRUE;
++
++  SetEvent (channel->space_avail_event);
++  
++  LOCK (channel->mutex);
++  while (channel->running)
++    {
++      if (channel->debug)
++	g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
++		 channel->thread_id, channel->rdp, channel->wrp);
++      if (channel->wrp == channel->rdp)
++	{
++	  /* Buffer is empty.  */
++	  if (channel->debug)
++	    g_print ("write_thread %#x: resetting space_avail\n",
++		     channel->thread_id);
++	  ResetEvent (channel->space_avail_event);
++	  if (channel->debug)
++	    g_print ("write_thread %#x: waiting for data\n",
++		     channel->thread_id);
++	  channel->revents = G_IO_OUT;
++	  SetEvent (channel->data_avail_event);
++	  UNLOCK (channel->mutex);
++	  WaitForSingleObject (channel->space_avail_event, INFINITE);
++
++	  LOCK (channel->mutex);
++	  if (channel->debug)
++	    g_print ("write_thread %#x: rdp=%d, wrp=%d\n",
++		     channel->thread_id, channel->rdp, channel->wrp);
++	}
++      
++      buffer = channel->buffer + channel->rdp;
++      if (channel->rdp < channel->wrp)
++	nbytes = channel->wrp - channel->rdp;
++      else
++	nbytes = BUFFER_SIZE - channel->rdp;
++
++      if (channel->debug)
++	g_print ("write_thread %#x: calling write() for %d bytes\n",
++		 channel->thread_id, nbytes);
++
++      UNLOCK (channel->mutex);
++      nbytes = write (channel->fd, buffer, nbytes);
++      //      {
++      //	DWORD nb;
++      //	WriteFile (_get_osfhandle (channel->fd), buffer, nbytes, &nb, NULL);
++      //	nbytes = nb;
++      //      }
++
++      LOCK (channel->mutex);
++
++      if (channel->debug)
++	g_print ("write_thread %#x: write(%i) returned %d, rdp=%d, wrp=%d\n",
++		 channel->thread_id, channel->fd, nbytes, channel->rdp, channel->wrp);
++
++      channel->revents = 0;
++      if (nbytes > 0)
++	channel->revents |= G_IO_OUT;
++      else if (nbytes <= 0)
++	channel->revents |= G_IO_ERR;
++
++      channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
++
++      if (nbytes <= 0)
++	break;
++
++      if (channel->debug)
++	g_print ("write_thread: setting data_avail for thread %#x\n",
++		 channel->thread_id);
++      SetEvent (channel->data_avail_event);
++    }
++  
++  channel->running = FALSE;
++  if (channel->needs_close)
++    {
++      if (channel->debug)
++	g_print ("write_thread %#x: channel fd %d needs closing\n",
++		 channel->thread_id, channel->fd);
++      close (channel->fd);
++      channel->fd = -1;
++    }
++
++  UNLOCK (channel->mutex);
++  
++  g_io_channel_unref ((GIOChannel *)channel);
++  
++  /* No need to call _endthreadex(), the actual thread starter routine
++   * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
++   * _endthreadex() for us.
++   */
++
++  return 0;
++}
++
++
+ static void
+ create_thread (GIOWin32Channel     *channel,
+ 	       GIOCondition         condition,
+@@ -502,6 +625,8 @@ create_thread (GIOWin32Channel     *chan
+     g_warning (G_STRLOC ": Error closing thread handle: %s\n",
+ 	       g_win32_error_message (GetLastError ()));
+ 
++  SetThreadPriority (thread_handle, THREAD_PRIORITY_HIGHEST);
++
+   WaitForSingleObject (channel->space_avail_event, INFINITE);
+ }
+ 
+@@ -575,6 +700,79 @@ buffer_read (GIOWin32Channel *channel,
+   return (*bytes_read > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
+ }
+ 
++static GIOStatus
++buffer_write (GIOWin32Channel *channel,
++	      const guchar    *dest,
++	      gsize            count,
++	      gsize           *bytes_written,
++	      GError         **err)
++{
++  guint nbytes;
++  guint left = count;
++  
++  LOCK (channel->mutex);
++  if (channel->debug)
++    g_print ("buffer_write: writing to thread %#x %d bytes, rdp=%d, wrp=%d\n",
++	     channel->thread_id, count, channel->rdp, channel->wrp);
++  
++  if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
++    {
++      /* Buffer is full */
++      if (channel->debug)
++	g_print ("buffer_write: tid %#x: resetting data_avail\n",
++		 channel->thread_id);
++      ResetEvent (channel->data_avail_event);
++      if (channel->debug)
++	g_print ("buffer_write: tid %#x: waiting for space\n",
++		 channel->thread_id);
++      UNLOCK (channel->mutex);
++      WaitForSingleObject (channel->data_avail_event, INFINITE);
++      LOCK (channel->mutex);
++      if (channel->debug)
++	g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d\n",
++		 channel->thread_id, channel->rdp, channel->wrp);
++    }
++   
++
++  /* Always leave at least one byte unused gap to be able to
++     distinguish between the full and empty condition.  */
++  nbytes = MIN ((channel->rdp + BUFFER_SIZE - channel->wrp - 1) % BUFFER_SIZE,
++		BUFFER_SIZE - channel->wrp);
++
++  UNLOCK (channel->mutex);
++  nbytes = MIN (left, nbytes);
++  if (channel->debug)
++    g_print ("buffer_write: tid %#x: writing %d bytes\n",
++	     channel->thread_id, nbytes);
++  memcpy (channel->buffer + channel->wrp, dest, nbytes);
++  dest += nbytes;
++  left -= nbytes;
++  LOCK (channel->mutex);
++
++  channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
++  if (channel->debug)
++    g_print ("buffer_write: tid %#x: rdp=%d, wrp=%d, setting space_avail\n",
++	     channel->thread_id, channel->rdp, channel->wrp);
++  SetEvent (channel->space_avail_event);
++
++  if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
++    {
++      /* Buffer is full */
++      if (channel->debug)
++	g_print ("buffer_write: tid %#x: resetting data_avail\n",
++		 channel->thread_id);
++      ResetEvent (channel->data_avail_event);
++    }
++
++  UNLOCK (channel->mutex);
++  
++  /* We have no way to indicate any errors form the actual
++     write() call in the writer thread. Should we have?  */
++  *bytes_written = count - left;
++  return (*bytes_written > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
++}
++
++
+ static gboolean
+ g_io_win32_prepare (GSource *source,
+ 		    gint    *timeout)
+@@ -601,13 +799,27 @@ g_io_win32_prepare (GSource *source,
+ 		 condition_to_string (channel->revents));
+       
+       LOCK (channel->mutex);
+-      if (channel->running && channel->wrp == channel->rdp)
++      if (channel->running)
+ 	{
+-	  if (channel->debug)
+-	    g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = 0\n",
+-		     channel->thread_id);
+-	  channel->revents = 0;
++	  if (channel->direction == 0 && channel->wrp == channel->rdp)
++	    {
++	      if (channel->debug)
++		g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = 0\n",
++			 channel->thread_id);
++	      channel->revents = 0;
++	    }
+ 	}
++      else
++	{
++	  if (channel->direction == 1
++	      && (channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
++	    {
++	      if (channel->debug)
++		g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = %i\n",
++			 channel->thread_id, 0);
++	      channel->revents = 0;
++	    }
++	}	  
+       UNLOCK (channel->mutex);
+       break;
+ 
+@@ -965,6 +1177,12 @@ g_io_win32_fd_write (GIOChannel  *channe
+   GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
+   gint result;
+   
++  if (win32_channel->thread_id)
++    {
++      return buffer_write (win32_channel, buf, count, bytes_written, err);
++    }
++
++
+   result = write (win32_channel->fd, buf, count);
+   if (win32_channel->debug)
+     g_print ("g_io_win32_fd_write: fd=%d count=%d => %d\n",
+@@ -1105,7 +1323,12 @@ g_io_win32_fd_create_watch (GIOChannel  
+ 
+   LOCK (win32_channel->mutex);
+   if (win32_channel->thread_id == 0)
+-    create_thread (win32_channel, condition, read_thread);
++    {
++      if (condition & G_IO_IN)
++	create_thread (win32_channel, condition, read_thread);
++      else
++	create_thread (win32_channel, condition, write_thread);
++    }
+ 
+   g_source_add_poll (source, &watch->pollfd);
+   UNLOCK (win32_channel->mutex);
+@@ -1715,8 +1938,13 @@ g_io_channel_win32_make_pollfd (GIOChann
+ 
+       fd->fd = (gint) win32_channel->data_avail_event;
+ 
+-      if (win32_channel->thread_id == 0 && (condition & G_IO_IN))
+-	create_thread (win32_channel, condition, read_thread);
++      if (win32_channel->thread_id == 0)
++	{
++	  if (condition & G_IO_IN)
++	    create_thread (win32_channel, condition, read_thread);
++	  else
++	    create_thread (win32_channel, condition, write_thread);
++	}
+       break;
+ 
+     case G_IO_WIN32_SOCKET:



More information about the Gpg4win-commits mailing list