mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-15 23:07:16 +01:00
Socket support rewritten. It was utterly broken, and untested in fact. We
2001-01-25 Tor Lillqvist <tml@iki.fi> * giowin32.c: Socket support rewritten. It was utterly broken, and untested in fact. We still do use a thread for each socket being watched, but instead of blocking in recv() (which of course was plain stupid for sockets being liste()ed on), we block in select(). The read method for sockets calls recv(). It is now possible for the application to call accept(), recv() or send() in the callback, just like on Unix. Tested with code kindly provided by Andrew Lanoix. Rename g_io_channel_win32_new_stream_socket() to g_io_channel_win32_new_socket() as it isn't restricted to stream sockets. * gmain.c (g_poll): Related changes in the Win32 version of g_poll(). When polling for messages, always do a PeekMessage() first. We used to miss messages if several were posted between calls to g_poll(). * giochannel.h: Improve Win32-related comments. * gutf8.c: (Win32) Include <stdio.h> for sprintf. * tests/gio-test.c: (Win32) Add tests for polling for Windows messages. * tests/makefile.mingw.in: Remove superfluous compilation command line.
This commit is contained in:
parent
9f9ad36031
commit
8a0df0a71c
30
ChangeLog
30
ChangeLog
@ -1,3 +1,33 @@
|
|||||||
|
2001-01-25 Tor Lillqvist <tml@iki.fi>
|
||||||
|
|
||||||
|
* giowin32.c: Socket support rewritten. It was utterly broken, and
|
||||||
|
untested in fact. We still do use a thread for each socket being
|
||||||
|
watched, but instead of blocking in recv() (which of course was
|
||||||
|
plain stupid for sockets being liste()ed on), we block in
|
||||||
|
select(). The read method for sockets calls recv(). It is now
|
||||||
|
possible for the application to call accept(), recv() or send() in
|
||||||
|
the callback, just like on Unix. Tested with code kindly provided
|
||||||
|
by Andrew Lanoix.
|
||||||
|
|
||||||
|
Rename g_io_channel_win32_new_stream_socket() to
|
||||||
|
g_io_channel_win32_new_socket() as it isn't restricted to stream
|
||||||
|
sockets.
|
||||||
|
|
||||||
|
* gmain.c (g_poll): Related changes in the Win32 version of
|
||||||
|
g_poll(). When polling for messages, always do a PeekMessage()
|
||||||
|
first. We used to miss messages if several were posted between
|
||||||
|
calls to g_poll().
|
||||||
|
|
||||||
|
* giochannel.h: Improve Win32-related comments.
|
||||||
|
|
||||||
|
* gutf8.c: (Win32) Include <stdio.h> for sprintf.
|
||||||
|
|
||||||
|
* tests/gio-test.c: (Win32) Add tests for polling for Windows
|
||||||
|
messages.
|
||||||
|
|
||||||
|
* tests/makefile.mingw.in: Remove superfluous compilation command
|
||||||
|
line.
|
||||||
|
|
||||||
2001-01-23 <alexl@redhat.com>
|
2001-01-23 <alexl@redhat.com>
|
||||||
|
|
||||||
* gmain.c (g_source_callback_unref): Free the callback
|
* gmain.c (g_source_callback_unref): Free the callback
|
||||||
|
@ -1,3 +1,33 @@
|
|||||||
|
2001-01-25 Tor Lillqvist <tml@iki.fi>
|
||||||
|
|
||||||
|
* giowin32.c: Socket support rewritten. It was utterly broken, and
|
||||||
|
untested in fact. We still do use a thread for each socket being
|
||||||
|
watched, but instead of blocking in recv() (which of course was
|
||||||
|
plain stupid for sockets being liste()ed on), we block in
|
||||||
|
select(). The read method for sockets calls recv(). It is now
|
||||||
|
possible for the application to call accept(), recv() or send() in
|
||||||
|
the callback, just like on Unix. Tested with code kindly provided
|
||||||
|
by Andrew Lanoix.
|
||||||
|
|
||||||
|
Rename g_io_channel_win32_new_stream_socket() to
|
||||||
|
g_io_channel_win32_new_socket() as it isn't restricted to stream
|
||||||
|
sockets.
|
||||||
|
|
||||||
|
* gmain.c (g_poll): Related changes in the Win32 version of
|
||||||
|
g_poll(). When polling for messages, always do a PeekMessage()
|
||||||
|
first. We used to miss messages if several were posted between
|
||||||
|
calls to g_poll().
|
||||||
|
|
||||||
|
* giochannel.h: Improve Win32-related comments.
|
||||||
|
|
||||||
|
* gutf8.c: (Win32) Include <stdio.h> for sprintf.
|
||||||
|
|
||||||
|
* tests/gio-test.c: (Win32) Add tests for polling for Windows
|
||||||
|
messages.
|
||||||
|
|
||||||
|
* tests/makefile.mingw.in: Remove superfluous compilation command
|
||||||
|
line.
|
||||||
|
|
||||||
2001-01-23 <alexl@redhat.com>
|
2001-01-23 <alexl@redhat.com>
|
||||||
|
|
||||||
* gmain.c (g_source_callback_unref): Free the callback
|
* gmain.c (g_source_callback_unref): Free the callback
|
||||||
|
@ -1,3 +1,33 @@
|
|||||||
|
2001-01-25 Tor Lillqvist <tml@iki.fi>
|
||||||
|
|
||||||
|
* giowin32.c: Socket support rewritten. It was utterly broken, and
|
||||||
|
untested in fact. We still do use a thread for each socket being
|
||||||
|
watched, but instead of blocking in recv() (which of course was
|
||||||
|
plain stupid for sockets being liste()ed on), we block in
|
||||||
|
select(). The read method for sockets calls recv(). It is now
|
||||||
|
possible for the application to call accept(), recv() or send() in
|
||||||
|
the callback, just like on Unix. Tested with code kindly provided
|
||||||
|
by Andrew Lanoix.
|
||||||
|
|
||||||
|
Rename g_io_channel_win32_new_stream_socket() to
|
||||||
|
g_io_channel_win32_new_socket() as it isn't restricted to stream
|
||||||
|
sockets.
|
||||||
|
|
||||||
|
* gmain.c (g_poll): Related changes in the Win32 version of
|
||||||
|
g_poll(). When polling for messages, always do a PeekMessage()
|
||||||
|
first. We used to miss messages if several were posted between
|
||||||
|
calls to g_poll().
|
||||||
|
|
||||||
|
* giochannel.h: Improve Win32-related comments.
|
||||||
|
|
||||||
|
* gutf8.c: (Win32) Include <stdio.h> for sprintf.
|
||||||
|
|
||||||
|
* tests/gio-test.c: (Win32) Add tests for polling for Windows
|
||||||
|
messages.
|
||||||
|
|
||||||
|
* tests/makefile.mingw.in: Remove superfluous compilation command
|
||||||
|
line.
|
||||||
|
|
||||||
2001-01-23 <alexl@redhat.com>
|
2001-01-23 <alexl@redhat.com>
|
||||||
|
|
||||||
* gmain.c (g_source_callback_unref): Free the callback
|
* gmain.c (g_source_callback_unref): Free the callback
|
||||||
|
@ -1,3 +1,33 @@
|
|||||||
|
2001-01-25 Tor Lillqvist <tml@iki.fi>
|
||||||
|
|
||||||
|
* giowin32.c: Socket support rewritten. It was utterly broken, and
|
||||||
|
untested in fact. We still do use a thread for each socket being
|
||||||
|
watched, but instead of blocking in recv() (which of course was
|
||||||
|
plain stupid for sockets being liste()ed on), we block in
|
||||||
|
select(). The read method for sockets calls recv(). It is now
|
||||||
|
possible for the application to call accept(), recv() or send() in
|
||||||
|
the callback, just like on Unix. Tested with code kindly provided
|
||||||
|
by Andrew Lanoix.
|
||||||
|
|
||||||
|
Rename g_io_channel_win32_new_stream_socket() to
|
||||||
|
g_io_channel_win32_new_socket() as it isn't restricted to stream
|
||||||
|
sockets.
|
||||||
|
|
||||||
|
* gmain.c (g_poll): Related changes in the Win32 version of
|
||||||
|
g_poll(). When polling for messages, always do a PeekMessage()
|
||||||
|
first. We used to miss messages if several were posted between
|
||||||
|
calls to g_poll().
|
||||||
|
|
||||||
|
* giochannel.h: Improve Win32-related comments.
|
||||||
|
|
||||||
|
* gutf8.c: (Win32) Include <stdio.h> for sprintf.
|
||||||
|
|
||||||
|
* tests/gio-test.c: (Win32) Add tests for polling for Windows
|
||||||
|
messages.
|
||||||
|
|
||||||
|
* tests/makefile.mingw.in: Remove superfluous compilation command
|
||||||
|
line.
|
||||||
|
|
||||||
2001-01-23 <alexl@redhat.com>
|
2001-01-23 <alexl@redhat.com>
|
||||||
|
|
||||||
* gmain.c (g_source_callback_unref): Free the callback
|
* gmain.c (g_source_callback_unref): Free the callback
|
||||||
|
@ -1,3 +1,33 @@
|
|||||||
|
2001-01-25 Tor Lillqvist <tml@iki.fi>
|
||||||
|
|
||||||
|
* giowin32.c: Socket support rewritten. It was utterly broken, and
|
||||||
|
untested in fact. We still do use a thread for each socket being
|
||||||
|
watched, but instead of blocking in recv() (which of course was
|
||||||
|
plain stupid for sockets being liste()ed on), we block in
|
||||||
|
select(). The read method for sockets calls recv(). It is now
|
||||||
|
possible for the application to call accept(), recv() or send() in
|
||||||
|
the callback, just like on Unix. Tested with code kindly provided
|
||||||
|
by Andrew Lanoix.
|
||||||
|
|
||||||
|
Rename g_io_channel_win32_new_stream_socket() to
|
||||||
|
g_io_channel_win32_new_socket() as it isn't restricted to stream
|
||||||
|
sockets.
|
||||||
|
|
||||||
|
* gmain.c (g_poll): Related changes in the Win32 version of
|
||||||
|
g_poll(). When polling for messages, always do a PeekMessage()
|
||||||
|
first. We used to miss messages if several were posted between
|
||||||
|
calls to g_poll().
|
||||||
|
|
||||||
|
* giochannel.h: Improve Win32-related comments.
|
||||||
|
|
||||||
|
* gutf8.c: (Win32) Include <stdio.h> for sprintf.
|
||||||
|
|
||||||
|
* tests/gio-test.c: (Win32) Add tests for polling for Windows
|
||||||
|
messages.
|
||||||
|
|
||||||
|
* tests/makefile.mingw.in: Remove superfluous compilation command
|
||||||
|
line.
|
||||||
|
|
||||||
2001-01-23 <alexl@redhat.com>
|
2001-01-23 <alexl@redhat.com>
|
||||||
|
|
||||||
* gmain.c (g_source_callback_unref): Free the callback
|
* gmain.c (g_source_callback_unref): Free the callback
|
||||||
|
@ -1,3 +1,33 @@
|
|||||||
|
2001-01-25 Tor Lillqvist <tml@iki.fi>
|
||||||
|
|
||||||
|
* giowin32.c: Socket support rewritten. It was utterly broken, and
|
||||||
|
untested in fact. We still do use a thread for each socket being
|
||||||
|
watched, but instead of blocking in recv() (which of course was
|
||||||
|
plain stupid for sockets being liste()ed on), we block in
|
||||||
|
select(). The read method for sockets calls recv(). It is now
|
||||||
|
possible for the application to call accept(), recv() or send() in
|
||||||
|
the callback, just like on Unix. Tested with code kindly provided
|
||||||
|
by Andrew Lanoix.
|
||||||
|
|
||||||
|
Rename g_io_channel_win32_new_stream_socket() to
|
||||||
|
g_io_channel_win32_new_socket() as it isn't restricted to stream
|
||||||
|
sockets.
|
||||||
|
|
||||||
|
* gmain.c (g_poll): Related changes in the Win32 version of
|
||||||
|
g_poll(). When polling for messages, always do a PeekMessage()
|
||||||
|
first. We used to miss messages if several were posted between
|
||||||
|
calls to g_poll().
|
||||||
|
|
||||||
|
* giochannel.h: Improve Win32-related comments.
|
||||||
|
|
||||||
|
* gutf8.c: (Win32) Include <stdio.h> for sprintf.
|
||||||
|
|
||||||
|
* tests/gio-test.c: (Win32) Add tests for polling for Windows
|
||||||
|
messages.
|
||||||
|
|
||||||
|
* tests/makefile.mingw.in: Remove superfluous compilation command
|
||||||
|
line.
|
||||||
|
|
||||||
2001-01-23 <alexl@redhat.com>
|
2001-01-23 <alexl@redhat.com>
|
||||||
|
|
||||||
* gmain.c (g_source_callback_unref): Free the callback
|
* gmain.c (g_source_callback_unref): Free the callback
|
||||||
|
@ -1,3 +1,33 @@
|
|||||||
|
2001-01-25 Tor Lillqvist <tml@iki.fi>
|
||||||
|
|
||||||
|
* giowin32.c: Socket support rewritten. It was utterly broken, and
|
||||||
|
untested in fact. We still do use a thread for each socket being
|
||||||
|
watched, but instead of blocking in recv() (which of course was
|
||||||
|
plain stupid for sockets being liste()ed on), we block in
|
||||||
|
select(). The read method for sockets calls recv(). It is now
|
||||||
|
possible for the application to call accept(), recv() or send() in
|
||||||
|
the callback, just like on Unix. Tested with code kindly provided
|
||||||
|
by Andrew Lanoix.
|
||||||
|
|
||||||
|
Rename g_io_channel_win32_new_stream_socket() to
|
||||||
|
g_io_channel_win32_new_socket() as it isn't restricted to stream
|
||||||
|
sockets.
|
||||||
|
|
||||||
|
* gmain.c (g_poll): Related changes in the Win32 version of
|
||||||
|
g_poll(). When polling for messages, always do a PeekMessage()
|
||||||
|
first. We used to miss messages if several were posted between
|
||||||
|
calls to g_poll().
|
||||||
|
|
||||||
|
* giochannel.h: Improve Win32-related comments.
|
||||||
|
|
||||||
|
* gutf8.c: (Win32) Include <stdio.h> for sprintf.
|
||||||
|
|
||||||
|
* tests/gio-test.c: (Win32) Add tests for polling for Windows
|
||||||
|
messages.
|
||||||
|
|
||||||
|
* tests/makefile.mingw.in: Remove superfluous compilation command
|
||||||
|
line.
|
||||||
|
|
||||||
2001-01-23 <alexl@redhat.com>
|
2001-01-23 <alexl@redhat.com>
|
||||||
|
|
||||||
* gmain.c (g_source_callback_unref): Free the callback
|
* gmain.c (g_source_callback_unref): Free the callback
|
||||||
|
@ -1,3 +1,33 @@
|
|||||||
|
2001-01-25 Tor Lillqvist <tml@iki.fi>
|
||||||
|
|
||||||
|
* giowin32.c: Socket support rewritten. It was utterly broken, and
|
||||||
|
untested in fact. We still do use a thread for each socket being
|
||||||
|
watched, but instead of blocking in recv() (which of course was
|
||||||
|
plain stupid for sockets being liste()ed on), we block in
|
||||||
|
select(). The read method for sockets calls recv(). It is now
|
||||||
|
possible for the application to call accept(), recv() or send() in
|
||||||
|
the callback, just like on Unix. Tested with code kindly provided
|
||||||
|
by Andrew Lanoix.
|
||||||
|
|
||||||
|
Rename g_io_channel_win32_new_stream_socket() to
|
||||||
|
g_io_channel_win32_new_socket() as it isn't restricted to stream
|
||||||
|
sockets.
|
||||||
|
|
||||||
|
* gmain.c (g_poll): Related changes in the Win32 version of
|
||||||
|
g_poll(). When polling for messages, always do a PeekMessage()
|
||||||
|
first. We used to miss messages if several were posted between
|
||||||
|
calls to g_poll().
|
||||||
|
|
||||||
|
* giochannel.h: Improve Win32-related comments.
|
||||||
|
|
||||||
|
* gutf8.c: (Win32) Include <stdio.h> for sprintf.
|
||||||
|
|
||||||
|
* tests/gio-test.c: (Win32) Add tests for polling for Windows
|
||||||
|
messages.
|
||||||
|
|
||||||
|
* tests/makefile.mingw.in: Remove superfluous compilation command
|
||||||
|
line.
|
||||||
|
|
||||||
2001-01-23 <alexl@redhat.com>
|
2001-01-23 <alexl@redhat.com>
|
||||||
|
|
||||||
* gmain.c (g_source_callback_unref): Free the callback
|
* gmain.c (g_source_callback_unref): Free the callback
|
||||||
|
42
giochannel.h
42
giochannel.h
@ -120,14 +120,20 @@ guint g_io_add_watch (GIOChannel *channel,
|
|||||||
/* On Unix, IO channels created with this function for any file
|
/* On Unix, IO channels created with this function for any file
|
||||||
* descriptor or socket.
|
* descriptor or socket.
|
||||||
*
|
*
|
||||||
* On Win32, use this only for files opened with the MSVCRT (the
|
* On Win32, this can be used either for files opened with the MSVCRT
|
||||||
* Microsoft run-time C library) _open() or _pipe, including file
|
* (the Microsoft run-time C library) _open() or _pipe, including file
|
||||||
* descriptors 0, 1 and 2 (corresponding to stdin, stdout and stderr).
|
* descriptors 0, 1 and 2 (corresponding to stdin, stdout and stderr),
|
||||||
|
* or for Winsock SOCKETs. If the parameter is a legal file
|
||||||
|
* descriptor, it is assumed to be such, otherwise it should be a
|
||||||
|
* SOCKET. This relies on SOCKETs and file descriptors not
|
||||||
|
* overlapping. If you want to be certain, call either
|
||||||
|
* g_io_channel_win32_new_fd() or g_io_channel_win32_new_socket()
|
||||||
|
* instead as appropriate.
|
||||||
*
|
*
|
||||||
* The term file descriptor as used in the context of Win32 refers to
|
* The term file descriptor as used in the context of Win32 refers to
|
||||||
* the emulated Unix-like file descriptors MSVCRT provides. The native
|
* the emulated Unix-like file descriptors MSVCRT provides. The native
|
||||||
* corresponding concept is file HANDLE. There isn't as of yet a way to
|
* corresponding concept is file HANDLE. There isn't as of yet a way to
|
||||||
* get GIOChannels for file HANDLEs.
|
* get GIOChannels for Win32 file HANDLEs.
|
||||||
*/
|
*/
|
||||||
GIOChannel* g_io_channel_unix_new (int fd);
|
GIOChannel* g_io_channel_unix_new (int fd);
|
||||||
gint g_io_channel_unix_get_fd (GIOChannel *channel);
|
gint g_io_channel_unix_get_fd (GIOChannel *channel);
|
||||||
@ -139,7 +145,8 @@ gint g_io_channel_unix_get_fd (GIOChannel *channel);
|
|||||||
/* Use this to get a GPollFD from a GIOChannel, so that you can call
|
/* Use this to get a GPollFD from a GIOChannel, so that you can call
|
||||||
* g_io_channel_win32_poll(). After calling this you should only use
|
* g_io_channel_win32_poll(). After calling this you should only use
|
||||||
* g_io_channel_read() to read from the GIOChannel, i.e. never read()
|
* g_io_channel_read() to read from the GIOChannel, i.e. never read()
|
||||||
* or recv() from the underlying file descriptor or SOCKET.
|
* from the underlying file descriptor. For SOCKETs, it is possible to call
|
||||||
|
* recv().
|
||||||
*/
|
*/
|
||||||
void g_io_channel_win32_make_pollfd (GIOChannel *channel,
|
void g_io_channel_win32_make_pollfd (GIOChannel *channel,
|
||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
@ -147,7 +154,6 @@ void g_io_channel_win32_make_pollfd (GIOChannel *channel,
|
|||||||
|
|
||||||
/* This can be used to wait a until at least one of the channels is readable.
|
/* This can be used to wait a until at least one of the channels is readable.
|
||||||
* On Unix you would do a select() on the file descriptors of the channels.
|
* On Unix you would do a select() on the file descriptors of the channels.
|
||||||
* This should probably be available for all platforms?
|
|
||||||
*/
|
*/
|
||||||
gint g_io_channel_win32_poll (GPollFD *fds,
|
gint g_io_channel_win32_poll (GPollFD *fds,
|
||||||
gint n_fds,
|
gint n_fds,
|
||||||
@ -160,25 +166,29 @@ void g_main_poll_win32_msg_add (gint priority,
|
|||||||
GPollFD *fd,
|
GPollFD *fd,
|
||||||
guint hwnd);
|
guint hwnd);
|
||||||
|
|
||||||
/* An IO channel for Windows messages for window handle hwnd. */
|
/* Create an IO channel for Windows messages for window handle hwnd. */
|
||||||
GIOChannel *g_io_channel_win32_new_messages (guint hwnd);
|
GIOChannel *g_io_channel_win32_new_messages (guint hwnd);
|
||||||
|
|
||||||
/* An IO channel for C runtime (emulated Unix-like) file
|
/* Create an IO channel for C runtime (emulated Unix-like) file
|
||||||
* descriptors. Identical to g_io_channel_unix_new above.
|
* descriptors. After calling g_io_add_watch() on a IO channel
|
||||||
* After calling g_io_add_watch() on a IO channel returned
|
* returned by this function, you shouldn't call read() on the file
|
||||||
* by this function, you shouldn't call read() on the file
|
* descriptor. This is because adding polling for a file descriptor is
|
||||||
* descriptor.
|
* implemented on Win32 by starting a thread that sits blocked in a
|
||||||
|
* read() from the file descriptor most of the time. All reads from
|
||||||
|
* the file descriptor should be done by this internal GLib
|
||||||
|
* thread. Your code should call only g_io_channel_read().
|
||||||
*/
|
*/
|
||||||
GIOChannel* g_io_channel_win32_new_fd (int fd);
|
GIOChannel* g_io_channel_win32_new_fd (int fd);
|
||||||
|
|
||||||
/* Get the C runtime file descriptor of a channel. */
|
/* Get the C runtime file descriptor of a channel. */
|
||||||
gint g_io_channel_win32_get_fd (GIOChannel *channel);
|
gint g_io_channel_win32_get_fd (GIOChannel *channel);
|
||||||
|
|
||||||
/* An IO channel for a SOCK_STREAM winsock socket. The parameter
|
/* Create an IO channel for a winsock socket. The parameter should be
|
||||||
* should be a SOCKET. After calling g_io_add_watch() on a IO channel
|
* a SOCKET. Contrary to IO channels for file descriptors (on *Win32),
|
||||||
* returned by this function, you shouldn't call recv() on the SOCKET.
|
* you can use normal recv() or recvfrom() on sockets even if GLib
|
||||||
|
* is polling them.
|
||||||
*/
|
*/
|
||||||
GIOChannel *g_io_channel_win32_new_stream_socket (int socket);
|
GIOChannel *g_io_channel_win32_new_socket (int socket);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
431
giowin32.c
431
giowin32.c
@ -48,13 +48,13 @@ typedef struct _GIOWin32Watch GIOWin32Watch;
|
|||||||
#define BUFFER_SIZE 4096
|
#define BUFFER_SIZE 4096
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
G_IO_WINDOWS_MESSAGES, /* Windows messages */
|
G_IO_WIN32_WINDOWS_MESSAGES, /* Windows messages */
|
||||||
G_IO_FILE_DESC, /* Unix-like file descriptors from
|
G_IO_WIN32_FILE_DESC, /* Unix-like file descriptors from
|
||||||
* _open() or _pipe(). Read with read().
|
* _open() or _pipe(). Read with read().
|
||||||
* Have to create separate thread to read.
|
* Have to create separate thread to read.
|
||||||
*/
|
*/
|
||||||
G_IO_STREAM_SOCKET /* Stream sockets. Similar as fds, but
|
G_IO_WIN32_SOCKET /* Sockets. A separate thread is blocked
|
||||||
* read with recv().
|
* in select() most of the time.
|
||||||
*/
|
*/
|
||||||
} GIOWin32ChannelType;
|
} GIOWin32ChannelType;
|
||||||
|
|
||||||
@ -68,10 +68,26 @@ struct _GIOWin32Channel {
|
|||||||
|
|
||||||
gboolean debug;
|
gboolean debug;
|
||||||
|
|
||||||
/* This is used by G_IO_WINDOWS_MESSAGES channels */
|
CRITICAL_SECTION mutex;
|
||||||
|
|
||||||
|
/* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
|
||||||
HWND hwnd; /* handle of window, or NULL */
|
HWND hwnd; /* handle of window, or NULL */
|
||||||
|
|
||||||
/* Following fields used by fd and socket channels for input */
|
/* Following fields are used by both fd and socket channels. */
|
||||||
|
gboolean running; /* Is reader thread running. FALSE if
|
||||||
|
* EOF has been reached.
|
||||||
|
*/
|
||||||
|
gboolean needs_close; /* If the channel has been closed while
|
||||||
|
* the reader thread was still running.
|
||||||
|
*/
|
||||||
|
guint thread_id; /* If non-NULL has a reader thread, or has
|
||||||
|
* had.*/
|
||||||
|
HANDLE thread_handle;
|
||||||
|
HANDLE data_avail_event;
|
||||||
|
|
||||||
|
gushort revents;
|
||||||
|
|
||||||
|
/* Following fields used by fd channels for input */
|
||||||
|
|
||||||
/* Data is kept in a circular buffer. To be able to distinguish between
|
/* 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
|
* empty and full buffer, we cannot fill it completely, but have to
|
||||||
@ -85,21 +101,11 @@ struct _GIOWin32Channel {
|
|||||||
*/
|
*/
|
||||||
guchar *buffer; /* (Circular) buffer */
|
guchar *buffer; /* (Circular) buffer */
|
||||||
gint wrp, rdp; /* Buffer indices for writing and reading */
|
gint wrp, rdp; /* Buffer indices for writing and reading */
|
||||||
gboolean running; /* Is reader thread running. FALSE if
|
|
||||||
* EOF has been reached.
|
|
||||||
*/
|
|
||||||
gboolean needs_close; /* If the channel has been closed while
|
|
||||||
* the reader thread was still running.
|
|
||||||
*/
|
|
||||||
guint thread_id; /* If non-NULL has a reader thread, or has
|
|
||||||
* had.*/
|
|
||||||
HANDLE thread_handle;
|
|
||||||
HANDLE data_avail_event;
|
|
||||||
HANDLE space_avail_event;
|
HANDLE space_avail_event;
|
||||||
CRITICAL_SECTION mutex;
|
|
||||||
|
|
||||||
/* Function that actually reads from fd */
|
/* Following fields used by socket channels */
|
||||||
int (*reader) (int fd, guchar *buf, int len);
|
GSList *watches;
|
||||||
|
HANDLE data_avail_noticed_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LOCK(mutex) EnterCriticalSection (&mutex)
|
#define LOCK(mutex) EnterCriticalSection (&mutex)
|
||||||
@ -129,7 +135,10 @@ g_io_channel_win32_init (GIOWin32Channel *channel)
|
|||||||
channel->needs_close = FALSE;
|
channel->needs_close = FALSE;
|
||||||
channel->thread_id = 0;
|
channel->thread_id = 0;
|
||||||
channel->data_avail_event = NULL;
|
channel->data_avail_event = NULL;
|
||||||
|
channel->revents = 0;
|
||||||
channel->space_avail_event = NULL;
|
channel->space_avail_event = NULL;
|
||||||
|
channel->data_avail_noticed_event = NULL;
|
||||||
|
channel->watches = NULL;
|
||||||
InitializeCriticalSection (&channel->mutex);
|
InitializeCriticalSection (&channel->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +155,8 @@ create_events (GIOWin32Channel *channel)
|
|||||||
* is automatic reset.
|
* is automatic reset.
|
||||||
*/
|
*/
|
||||||
if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
|
if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
|
||||||
|| !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
|
|| !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))
|
||||||
|
|| !(channel->data_avail_noticed_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
|
||||||
{
|
{
|
||||||
gchar *msg = g_win32_error_message (GetLastError ());
|
gchar *msg = g_win32_error_message (GetLastError ());
|
||||||
g_error ("Error creating event: %s", msg);
|
g_error ("Error creating event: %s", msg);
|
||||||
@ -154,18 +164,18 @@ create_events (GIOWin32Channel *channel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned __stdcall
|
static unsigned __stdcall
|
||||||
reader_thread (void *parameter)
|
read_thread (void *parameter)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *channel = parameter;
|
GIOWin32Channel *channel = parameter;
|
||||||
|
GSList *tmp;
|
||||||
guchar *buffer;
|
guchar *buffer;
|
||||||
guint nbytes;
|
guint nbytes;
|
||||||
|
|
||||||
g_io_channel_ref ((GIOChannel *) channel);
|
g_io_channel_ref ((GIOChannel *)channel);
|
||||||
|
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: starting. pid:%#x, fd:%d, data_avail:%#x, space_avail:%#x\n",
|
g_print ("read_thread %#x: start fd:%d, data_avail:%#x, space_avail:%#x\n",
|
||||||
channel->thread_id,
|
channel->thread_id,
|
||||||
(guint) GetCurrentProcessId (),
|
|
||||||
channel->fd,
|
channel->fd,
|
||||||
(guint) channel->data_avail_event,
|
(guint) channel->data_avail_event,
|
||||||
(guint) channel->space_avail_event);
|
(guint) channel->space_avail_event);
|
||||||
@ -180,22 +190,23 @@ reader_thread (void *parameter)
|
|||||||
{
|
{
|
||||||
LOCK (channel->mutex);
|
LOCK (channel->mutex);
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: rdp=%d, wrp=%d\n",
|
g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
channel->thread_id, channel->rdp, channel->wrp);
|
||||||
if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
|
if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
|
||||||
{
|
{
|
||||||
/* Buffer is full */
|
/* Buffer is full */
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: resetting space_available\n",
|
g_print ("read_thread %#x: resetting space_avail\n",
|
||||||
channel->thread_id);
|
channel->thread_id);
|
||||||
ResetEvent (channel->space_avail_event);
|
ResetEvent (channel->space_avail_event);
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: waiting for space\n", channel->thread_id);
|
g_print ("read_thread %#x: waiting for space\n",
|
||||||
|
channel->thread_id);
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
WaitForSingleObject (channel->space_avail_event, INFINITE);
|
WaitForSingleObject (channel->space_avail_event, INFINITE);
|
||||||
LOCK (channel->mutex);
|
LOCK (channel->mutex);
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: rdp=%d, wrp=%d\n",
|
g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
channel->thread_id, channel->rdp, channel->wrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,17 +219,23 @@ reader_thread (void *parameter)
|
|||||||
BUFFER_SIZE - channel->wrp);
|
BUFFER_SIZE - channel->wrp);
|
||||||
|
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: calling reader for %d bytes\n",
|
g_print ("read_thread %#x: calling read() for %d bytes\n",
|
||||||
channel->thread_id, nbytes);
|
channel->thread_id, nbytes);
|
||||||
|
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
|
|
||||||
nbytes = (*channel->reader) (channel->fd, buffer, nbytes);
|
nbytes = read (channel->fd, buffer, nbytes);
|
||||||
|
|
||||||
LOCK (channel->mutex);
|
LOCK (channel->mutex);
|
||||||
|
|
||||||
|
channel->revents = G_IO_IN;
|
||||||
|
if (nbytes == 0)
|
||||||
|
channel->revents |= G_IO_HUP;
|
||||||
|
else if (nbytes < 0)
|
||||||
|
channel->revents |= G_IO_ERR;
|
||||||
|
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: got %d bytes, rdp=%d, wrp=%d\n",
|
g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
|
||||||
channel->thread_id, nbytes, channel->rdp, channel->wrp);
|
channel->thread_id, nbytes, channel->rdp, channel->wrp);
|
||||||
|
|
||||||
if (nbytes <= 0)
|
if (nbytes <= 0)
|
||||||
@ -226,33 +243,29 @@ reader_thread (void *parameter)
|
|||||||
|
|
||||||
channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
|
channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: rdp=%d, wrp=%d, setting data available\n",
|
g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
channel->thread_id, channel->rdp, channel->wrp);
|
||||||
SetEvent (channel->data_avail_event);
|
SetEvent (channel->data_avail_event);
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
channel->running = FALSE;
|
channel->running = FALSE;
|
||||||
if (channel->debug)
|
|
||||||
g_print ("thread %#x: got EOF, rdp=%d, wrp=%d, setting data available\n",
|
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
|
||||||
|
|
||||||
if (channel->needs_close)
|
if (channel->needs_close)
|
||||||
{
|
{
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: channel fd %d needs closing\n",
|
g_print ("read_thread %#x: channel fd %d needs closing\n",
|
||||||
channel->thread_id, channel->fd);
|
channel->thread_id, channel->fd);
|
||||||
if (channel->type == G_IO_FILE_DESC)
|
|
||||||
close (channel->fd);
|
close (channel->fd);
|
||||||
else if (channel->type == G_IO_STREAM_SOCKET)
|
|
||||||
closesocket (channel->fd);
|
|
||||||
channel->fd = -1;
|
channel->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
|
||||||
|
channel->thread_id, channel->rdp, channel->wrp);
|
||||||
SetEvent (channel->data_avail_event);
|
SetEvent (channel->data_avail_event);
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
|
|
||||||
g_io_channel_unref((GIOChannel *) channel);
|
g_io_channel_unref((GIOChannel *)channel);
|
||||||
|
|
||||||
/* No need to call _endthreadex(), the actual thread starter routine
|
/* No need to call _endthreadex(), the actual thread starter routine
|
||||||
* in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
|
* in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
|
||||||
@ -265,13 +278,12 @@ reader_thread (void *parameter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_reader_thread (GIOWin32Channel *channel,
|
create_thread (GIOWin32Channel *channel,
|
||||||
gpointer reader)
|
GIOCondition condition,
|
||||||
|
unsigned (__stdcall *thread) (void *parameter))
|
||||||
{
|
{
|
||||||
channel->reader = reader;
|
|
||||||
|
|
||||||
if ((channel->thread_handle =
|
if ((channel->thread_handle =
|
||||||
(HANDLE) _beginthreadex (NULL, 0, reader_thread, channel, 0,
|
(HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
|
||||||
&channel->thread_id)) == 0)
|
&channel->thread_id)) == 0)
|
||||||
g_warning ("Error creating reader thread: %s", strerror (errno));
|
g_warning ("Error creating reader thread: %s", strerror (errno));
|
||||||
WaitForSingleObject (channel->space_avail_event, INFINITE);
|
WaitForSingleObject (channel->space_avail_event, INFINITE);
|
||||||
@ -291,7 +303,7 @@ buffer_read (GIOWin32Channel *channel,
|
|||||||
g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
|
g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
|
||||||
channel->thread_id, count, channel->rdp, channel->wrp);
|
channel->thread_id, count, channel->rdp, channel->wrp);
|
||||||
|
|
||||||
if (channel->rdp == channel->wrp)
|
if (channel->wrp == channel->rdp)
|
||||||
{
|
{
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
@ -300,7 +312,7 @@ buffer_read (GIOWin32Channel *channel,
|
|||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("done waiting for data from thread %#x\n", channel->thread_id);
|
g_print ("done waiting for data from thread %#x\n", channel->thread_id);
|
||||||
LOCK (channel->mutex);
|
LOCK (channel->mutex);
|
||||||
if (channel->rdp == channel->wrp && !channel->running)
|
if (channel->wrp == channel->rdp && !channel->running)
|
||||||
{
|
{
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
return 0;
|
return 0;
|
||||||
@ -322,15 +334,15 @@ buffer_read (GIOWin32Channel *channel,
|
|||||||
LOCK (channel->mutex);
|
LOCK (channel->mutex);
|
||||||
channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
|
channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("setting space available for thread %#x\n", channel->thread_id);
|
g_print ("setting space_avail for thread %#x\n", channel->thread_id);
|
||||||
SetEvent (channel->space_avail_event);
|
SetEvent (channel->space_avail_event);
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("for thread %#x: rdp=%d, wrp=%d\n",
|
g_print ("for thread %#x: rdp=%d, wrp=%d\n",
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
channel->thread_id, channel->rdp, channel->wrp);
|
||||||
if (channel->running && channel->rdp == channel->wrp)
|
if (channel->running && channel->wrp == channel->rdp)
|
||||||
{
|
{
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("resetting data_available of thread %#x\n",
|
g_print ("resetting data_avail of thread %#x\n",
|
||||||
channel->thread_id);
|
channel->thread_id);
|
||||||
ResetEvent (channel->data_avail_event);
|
ResetEvent (channel->data_avail_event);
|
||||||
};
|
};
|
||||||
@ -343,12 +355,154 @@ buffer_read (GIOWin32Channel *channel,
|
|||||||
return count - left;
|
return count - left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned __stdcall
|
||||||
|
select_thread (void *parameter)
|
||||||
|
{
|
||||||
|
GIOWin32Channel *channel = parameter;
|
||||||
|
fd_set read_fds, write_fds, except_fds;
|
||||||
|
GSList *tmp;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
g_io_channel_ref ((GIOChannel *)channel);
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: start fd:%d,\n\tdata_avail:%#x, data_avail_noticed:%#x\n",
|
||||||
|
channel->thread_id,
|
||||||
|
channel->fd,
|
||||||
|
(guint) channel->data_avail_event,
|
||||||
|
(guint) channel->data_avail_noticed_event);
|
||||||
|
|
||||||
|
channel->rdp = channel->wrp = 0;
|
||||||
|
channel->running = TRUE;
|
||||||
|
|
||||||
|
SetEvent (channel->space_avail_event);
|
||||||
|
|
||||||
|
while (channel->running)
|
||||||
|
{
|
||||||
|
FD_ZERO (&read_fds);
|
||||||
|
FD_ZERO (&write_fds);
|
||||||
|
FD_ZERO (&except_fds);
|
||||||
|
|
||||||
|
tmp = channel->watches;
|
||||||
|
while (tmp)
|
||||||
|
{
|
||||||
|
GIOWin32Watch *watch = (GIOWin32Watch *)tmp->data;
|
||||||
|
|
||||||
|
if (watch->condition & (G_IO_IN | G_IO_HUP))
|
||||||
|
FD_SET (channel->fd, &read_fds);
|
||||||
|
if (watch->condition & G_IO_OUT)
|
||||||
|
FD_SET (channel->fd, &write_fds);
|
||||||
|
if (watch->condition & G_IO_ERR)
|
||||||
|
FD_SET (channel->fd, &except_fds);
|
||||||
|
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: calling select() for%s%s%s\n",
|
||||||
|
channel->thread_id,
|
||||||
|
(FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
|
||||||
|
(FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
|
||||||
|
(FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
|
||||||
|
|
||||||
|
n = select (1, &read_fds, &write_fds, &except_fds, NULL);
|
||||||
|
|
||||||
|
if (n == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
|
||||||
|
channel->thread_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: got%s%s%s\n",
|
||||||
|
channel->thread_id,
|
||||||
|
(FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
|
||||||
|
(FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
|
||||||
|
(FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
|
||||||
|
|
||||||
|
if (FD_ISSET (channel->fd, &read_fds))
|
||||||
|
channel->revents |= G_IO_IN;
|
||||||
|
if (FD_ISSET (channel->fd, &write_fds))
|
||||||
|
channel->revents |= G_IO_OUT;
|
||||||
|
if (FD_ISSET (channel->fd, &except_fds))
|
||||||
|
channel->revents |= G_IO_ERR;
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: resetting data_avail_noticed,\n"
|
||||||
|
"\tsetting data_avail\n",
|
||||||
|
channel->thread_id);
|
||||||
|
ResetEvent (channel->data_avail_noticed_event);
|
||||||
|
SetEvent (channel->data_avail_event);
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: waiting for data_avail_noticed\n",
|
||||||
|
channel->thread_id);
|
||||||
|
|
||||||
|
WaitForSingleObject (channel->data_avail_noticed_event, INFINITE);
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: got data_avail_noticed\n",
|
||||||
|
channel->thread_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
channel->running = FALSE;
|
||||||
|
LOCK (channel->mutex);
|
||||||
|
if (channel->needs_close)
|
||||||
|
{
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: channel fd %d needs closing\n",
|
||||||
|
channel->thread_id, channel->fd);
|
||||||
|
closesocket (channel->fd);
|
||||||
|
channel->fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: got error, setting data_avail\n",
|
||||||
|
channel->thread_id);
|
||||||
|
SetEvent (channel->data_avail_event);
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
CloseHandle (channel->thread_handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
g_io_win32_prepare (GSource *source,
|
g_io_win32_prepare (GSource *source,
|
||||||
gint *timeout)
|
gint *timeout)
|
||||||
{
|
{
|
||||||
|
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
||||||
|
GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
|
||||||
|
|
||||||
*timeout = -1;
|
*timeout = -1;
|
||||||
|
|
||||||
|
if (channel->type == G_IO_WIN32_FILE_DESC)
|
||||||
|
{
|
||||||
|
LOCK (channel->mutex);
|
||||||
|
if (channel->running && channel->wrp == channel->rdp)
|
||||||
|
channel->revents = 0;
|
||||||
|
UNLOCK (channel->mutex);
|
||||||
|
}
|
||||||
|
else if (channel->type == G_IO_WIN32_SOCKET)
|
||||||
|
{
|
||||||
|
channel->revents = 0;
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("g_io_win32_prepare: thread %#x, setting data_avail_noticed\n",
|
||||||
|
channel->thread_id);
|
||||||
|
SetEvent (channel->data_avail_noticed_event);
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("g_io_win32_prepare: thread %#x, there.\n",
|
||||||
|
channel->thread_id);
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,18 +510,26 @@ static gboolean
|
|||||||
g_io_win32_check (GSource *source)
|
g_io_win32_check (GSource *source)
|
||||||
{
|
{
|
||||||
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
||||||
GIOWin32Channel *channel = (GIOWin32Channel *) watch->channel;
|
GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
|
||||||
|
|
||||||
/* If the thread has died, we have encountered EOF. If the buffer
|
if (channel->debug)
|
||||||
* also is emtpty set the HUP bit.
|
g_print ("g_io_win32_check: for thread %#x:\n"
|
||||||
*/
|
"\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
|
||||||
if (!channel->running && channel->rdp == channel->wrp)
|
channel->thread_id,
|
||||||
|
watch->pollfd.events, watch->pollfd.revents, channel->revents);
|
||||||
|
|
||||||
|
if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
|
||||||
|
watch->pollfd.revents = (watch->pollfd.events & channel->revents);
|
||||||
|
|
||||||
|
if (channel->type == G_IO_WIN32_SOCKET)
|
||||||
{
|
{
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("g_io_win32_check: setting G_IO_HUP thread %#x rdp=%d wrp=%d\n",
|
g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
channel->thread_id);
|
||||||
watch->pollfd.revents |= G_IO_HUP;
|
ResetEvent (channel->data_avail_event);
|
||||||
return TRUE;
|
if (channel->debug)
|
||||||
|
g_print ("g_io_win32_check: thread %#x, there.\n",
|
||||||
|
channel->thread_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (watch->pollfd.revents & watch->condition);
|
return (watch->pollfd.revents & watch->condition);
|
||||||
@ -397,6 +559,13 @@ static void
|
|||||||
g_io_win32_destroy (GSource *source)
|
g_io_win32_destroy (GSource *source)
|
||||||
{
|
{
|
||||||
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
||||||
|
GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("g_io_win32_destroy: channel with thread %#x\n",
|
||||||
|
channel->thread_id);
|
||||||
|
|
||||||
|
channel->watches = g_slist_remove (channel->watches, watch);
|
||||||
|
|
||||||
g_io_channel_unref (watch->channel);
|
g_io_channel_unref (watch->channel);
|
||||||
}
|
}
|
||||||
@ -411,9 +580,9 @@ static GSourceFuncs win32_watch_funcs = {
|
|||||||
static GSource *
|
static GSource *
|
||||||
g_io_win32_create_watch (GIOChannel *channel,
|
g_io_win32_create_watch (GIOChannel *channel,
|
||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
int (*reader) (int, guchar *, int))
|
unsigned (__stdcall *thread) (void *parameter))
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
GIOWin32Watch *watch;
|
GIOWin32Watch *watch;
|
||||||
GSource *source;
|
GSource *source;
|
||||||
|
|
||||||
@ -432,11 +601,13 @@ g_io_win32_create_watch (GIOChannel *channel,
|
|||||||
watch->pollfd.events = condition;
|
watch->pollfd.events = condition;
|
||||||
|
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("g_io_win32_create_watch: fd:%d handle:%#x\n",
|
g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
|
||||||
win32_channel->fd, watch->pollfd.fd);
|
win32_channel->fd, condition, watch->pollfd.fd);
|
||||||
|
|
||||||
|
win32_channel->watches = g_slist_append (win32_channel->watches, watch);
|
||||||
|
|
||||||
if (win32_channel->thread_id == 0)
|
if (win32_channel->thread_id == 0)
|
||||||
create_reader_thread (win32_channel, reader);
|
create_thread (win32_channel, condition, thread);
|
||||||
|
|
||||||
g_source_add_poll (source, &watch->pollfd);
|
g_source_add_poll (source, &watch->pollfd);
|
||||||
|
|
||||||
@ -449,12 +620,15 @@ g_io_win32_msg_read (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_read)
|
guint *bytes_read)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
MSG msg; /* In case of alignment problems */
|
MSG msg; /* In case of alignment problems */
|
||||||
|
|
||||||
if (count < sizeof (MSG))
|
if (count < sizeof (MSG))
|
||||||
return G_IO_ERROR_INVAL;
|
return G_IO_ERROR_INVAL;
|
||||||
|
|
||||||
|
if (win32_channel->debug)
|
||||||
|
g_print ("g_io_win32_msg_read: for %#x\n",
|
||||||
|
win32_channel->hwnd);
|
||||||
if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
|
if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
|
||||||
return G_IO_ERROR_AGAIN;
|
return G_IO_ERROR_AGAIN;
|
||||||
|
|
||||||
@ -469,7 +643,7 @@ g_io_win32_msg_write (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_written)
|
guint *bytes_written)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
if (count != sizeof (MSG))
|
if (count != sizeof (MSG))
|
||||||
@ -501,21 +675,23 @@ g_io_win32_msg_close (GIOChannel *channel)
|
|||||||
static void
|
static void
|
||||||
g_io_win32_free (GIOChannel *channel)
|
g_io_win32_free (GIOChannel *channel)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("thread %#x: freeing channel, fd: %d\n",
|
g_print ("thread %#x: freeing channel, fd: %d\n",
|
||||||
win32_channel->thread_id,
|
win32_channel->thread_id,
|
||||||
win32_channel->fd);
|
win32_channel->fd);
|
||||||
|
|
||||||
if (win32_channel->buffer)
|
if (win32_channel->data_avail_event)
|
||||||
{
|
|
||||||
CloseHandle (win32_channel->data_avail_event);
|
CloseHandle (win32_channel->data_avail_event);
|
||||||
|
if (win32_channel->space_avail_event)
|
||||||
CloseHandle (win32_channel->space_avail_event);
|
CloseHandle (win32_channel->space_avail_event);
|
||||||
|
if (win32_channel->data_avail_noticed_event)
|
||||||
|
CloseHandle (win32_channel->data_avail_noticed_event);
|
||||||
DeleteCriticalSection (&win32_channel->mutex);
|
DeleteCriticalSection (&win32_channel->mutex);
|
||||||
}
|
|
||||||
|
|
||||||
g_free (win32_channel->buffer);
|
g_free (win32_channel->buffer);
|
||||||
|
g_slist_free (win32_channel->watches);
|
||||||
g_free (win32_channel);
|
g_free (win32_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,7 +724,7 @@ g_io_win32_fd_read (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_read)
|
guint *bytes_read)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
gint result;
|
gint result;
|
||||||
GIOError error;
|
GIOError error;
|
||||||
|
|
||||||
@ -594,7 +770,7 @@ g_io_win32_fd_write (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_written)
|
guint *bytes_written)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
gint result;
|
gint result;
|
||||||
|
|
||||||
result = write (win32_channel->fd, buf, count);
|
result = write (win32_channel->fd, buf, count);
|
||||||
@ -627,7 +803,7 @@ g_io_win32_fd_seek (GIOChannel *channel,
|
|||||||
gint offset,
|
gint offset,
|
||||||
GSeekType type)
|
GSeekType type)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
int whence;
|
int whence;
|
||||||
off_t result;
|
off_t result;
|
||||||
|
|
||||||
@ -666,7 +842,7 @@ g_io_win32_fd_seek (GIOChannel *channel,
|
|||||||
static void
|
static void
|
||||||
g_io_win32_fd_close (GIOChannel *channel)
|
g_io_win32_fd_close (GIOChannel *channel)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("thread %#x: closing fd %d\n",
|
g_print ("thread %#x: closing fd %d\n",
|
||||||
@ -695,19 +871,11 @@ g_io_win32_fd_close (GIOChannel *channel)
|
|||||||
UNLOCK (win32_channel->mutex);
|
UNLOCK (win32_channel->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
fd_reader (int fd,
|
|
||||||
guchar *buf,
|
|
||||||
int len)
|
|
||||||
{
|
|
||||||
return read (fd, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GSource *
|
static GSource *
|
||||||
g_io_win32_fd_create_watch (GIOChannel *channel,
|
g_io_win32_fd_create_watch (GIOChannel *channel,
|
||||||
GIOCondition condition)
|
GIOCondition condition)
|
||||||
{
|
{
|
||||||
return g_io_win32_create_watch (channel, condition, fd_reader);
|
return g_io_win32_create_watch (channel, condition, read_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GIOError
|
static GIOError
|
||||||
@ -716,32 +884,33 @@ g_io_win32_sock_read (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_read)
|
guint *bytes_read)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
gint result;
|
gint result;
|
||||||
GIOError error;
|
GIOError error;
|
||||||
|
|
||||||
if (win32_channel->thread_id)
|
if (win32_channel->debug)
|
||||||
{
|
g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
|
||||||
result = buffer_read (win32_channel, buf, count, &error);
|
win32_channel->fd, count);
|
||||||
if (result < 0)
|
|
||||||
{
|
|
||||||
*bytes_read = 0;
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*bytes_read = result;
|
|
||||||
return G_IO_ERROR_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = recv (win32_channel->fd, buf, count, 0);
|
result = recv (win32_channel->fd, buf, count, 0);
|
||||||
|
|
||||||
if (result < 0)
|
if (win32_channel->debug)
|
||||||
|
g_print ("g_io_win32_sock_read: recv:%d\n", result);
|
||||||
|
|
||||||
|
if (result == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
*bytes_read = 0;
|
*bytes_read = 0;
|
||||||
|
switch (WSAGetLastError ())
|
||||||
|
{
|
||||||
|
case WSAEINVAL:
|
||||||
|
return G_IO_ERROR_INVAL;
|
||||||
|
case WSAEWOULDBLOCK:
|
||||||
|
case WSAEINTR:
|
||||||
|
return G_IO_ERROR_AGAIN;
|
||||||
|
default:
|
||||||
return G_IO_ERROR_UNKNOWN;
|
return G_IO_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*bytes_read = result;
|
*bytes_read = result;
|
||||||
@ -755,11 +924,18 @@ g_io_win32_sock_write (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_written)
|
guint *bytes_written)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
gint result;
|
gint result;
|
||||||
|
|
||||||
|
if (win32_channel->debug)
|
||||||
|
g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
|
||||||
|
win32_channel->fd, count);
|
||||||
|
|
||||||
result = send (win32_channel->fd, buf, count, 0);
|
result = send (win32_channel->fd, buf, count, 0);
|
||||||
|
|
||||||
|
if (win32_channel->debug)
|
||||||
|
g_print ("g_io_win32_sock_write: send:%d\n", result);
|
||||||
|
|
||||||
if (result == SOCKET_ERROR)
|
if (result == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
*bytes_written = 0;
|
*bytes_written = 0;
|
||||||
@ -784,7 +960,7 @@ g_io_win32_sock_write (GIOChannel *channel,
|
|||||||
static void
|
static void
|
||||||
g_io_win32_sock_close (GIOChannel *channel)
|
g_io_win32_sock_close (GIOChannel *channel)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("thread %#x: closing socket %d\n",
|
g_print ("thread %#x: closing socket %d\n",
|
||||||
@ -794,19 +970,11 @@ g_io_win32_sock_close (GIOChannel *channel)
|
|||||||
win32_channel->fd = -1;
|
win32_channel->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
sock_reader (int fd,
|
|
||||||
guchar *buf,
|
|
||||||
int len)
|
|
||||||
{
|
|
||||||
return recv (fd, buf, len, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GSource *
|
static GSource *
|
||||||
g_io_win32_sock_create_watch (GIOChannel *channel,
|
g_io_win32_sock_create_watch (GIOChannel *channel,
|
||||||
GIOCondition condition)
|
GIOCondition condition)
|
||||||
{
|
{
|
||||||
return g_io_win32_create_watch (channel, condition, sock_reader);
|
return g_io_win32_create_watch (channel, condition, select_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GIOFuncs win32_channel_msg_funcs = {
|
static GIOFuncs win32_channel_msg_funcs = {
|
||||||
@ -840,14 +1008,14 @@ GIOChannel *
|
|||||||
g_io_channel_win32_new_messages (guint hwnd)
|
g_io_channel_win32_new_messages (guint hwnd)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
|
GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
|
||||||
GIOChannel *channel = (GIOChannel *) win32_channel;
|
GIOChannel *channel = (GIOChannel *)win32_channel;
|
||||||
|
|
||||||
g_io_channel_init (channel);
|
g_io_channel_init (channel);
|
||||||
g_io_channel_win32_init (win32_channel);
|
g_io_channel_win32_init (win32_channel);
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
|
g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
|
||||||
channel->funcs = &win32_channel_msg_funcs;
|
channel->funcs = &win32_channel_msg_funcs;
|
||||||
win32_channel->type = G_IO_WINDOWS_MESSAGES;
|
win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
|
||||||
win32_channel->hwnd = (HWND) hwnd;
|
win32_channel->hwnd = (HWND) hwnd;
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
@ -867,14 +1035,14 @@ g_io_channel_win32_new_fd (gint fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
win32_channel = g_new (GIOWin32Channel, 1);
|
win32_channel = g_new (GIOWin32Channel, 1);
|
||||||
channel = (GIOChannel *) win32_channel;
|
channel = (GIOChannel *)win32_channel;
|
||||||
|
|
||||||
g_io_channel_init (channel);
|
g_io_channel_init (channel);
|
||||||
g_io_channel_win32_init (win32_channel);
|
g_io_channel_win32_init (win32_channel);
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
|
g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
|
||||||
channel->funcs = &win32_channel_fd_funcs;
|
channel->funcs = &win32_channel_fd_funcs;
|
||||||
win32_channel->type = G_IO_FILE_DESC;
|
win32_channel->type = G_IO_WIN32_FILE_DESC;
|
||||||
win32_channel->fd = fd;
|
win32_channel->fd = fd;
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
@ -883,23 +1051,23 @@ g_io_channel_win32_new_fd (gint fd)
|
|||||||
gint
|
gint
|
||||||
g_io_channel_win32_get_fd (GIOChannel *channel)
|
g_io_channel_win32_get_fd (GIOChannel *channel)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
return win32_channel->fd;
|
return win32_channel->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
GIOChannel *
|
GIOChannel *
|
||||||
g_io_channel_win32_new_stream_socket (int socket)
|
g_io_channel_win32_new_socket (int socket)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
|
GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
|
||||||
GIOChannel *channel = (GIOChannel *) win32_channel;
|
GIOChannel *channel = (GIOChannel *)win32_channel;
|
||||||
|
|
||||||
g_io_channel_init (channel);
|
g_io_channel_init (channel);
|
||||||
g_io_channel_win32_init (win32_channel);
|
g_io_channel_win32_init (win32_channel);
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("g_io_channel_win32_new_stream_socket: socket = %d\n", socket);
|
g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
|
||||||
channel->funcs = &win32_channel_sock_funcs;
|
channel->funcs = &win32_channel_sock_funcs;
|
||||||
win32_channel->type = G_IO_STREAM_SOCKET;
|
win32_channel->type = G_IO_WIN32_SOCKET;
|
||||||
win32_channel->fd = socket;
|
win32_channel->fd = socket;
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
@ -914,9 +1082,9 @@ g_io_channel_unix_new (gint fd)
|
|||||||
return g_io_channel_win32_new_fd (fd);
|
return g_io_channel_win32_new_fd (fd);
|
||||||
|
|
||||||
if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
|
if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
|
||||||
return g_io_channel_win32_new_stream_socket(fd);
|
return g_io_channel_win32_new_socket(fd);
|
||||||
|
|
||||||
g_warning ("%d isn't a file descriptor or a socket", fd);
|
g_warning ("%d is neither a file descriptor or a socket", fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -930,7 +1098,7 @@ void
|
|||||||
g_io_channel_win32_set_debug (GIOChannel *channel,
|
g_io_channel_win32_set_debug (GIOChannel *channel,
|
||||||
gboolean flag)
|
gboolean flag)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
win32_channel->debug = flag;
|
win32_channel->debug = flag;
|
||||||
}
|
}
|
||||||
@ -954,7 +1122,7 @@ g_io_channel_win32_make_pollfd (GIOChannel *channel,
|
|||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
GPollFD *fd)
|
GPollFD *fd)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
if (win32_channel->data_avail_event == NULL)
|
if (win32_channel->data_avail_event == NULL)
|
||||||
create_events (win32_channel);
|
create_events (win32_channel);
|
||||||
@ -963,8 +1131,15 @@ g_io_channel_win32_make_pollfd (GIOChannel *channel,
|
|||||||
fd->events = condition;
|
fd->events = condition;
|
||||||
|
|
||||||
if (win32_channel->thread_id == 0)
|
if (win32_channel->thread_id == 0)
|
||||||
if (win32_channel->type == G_IO_FILE_DESC)
|
if ((condition & G_IO_IN) && win32_channel->type == G_IO_WIN32_FILE_DESC)
|
||||||
create_reader_thread (win32_channel, fd_reader);
|
create_thread (win32_channel, condition, read_thread);
|
||||||
else if (win32_channel->type == G_IO_STREAM_SOCKET)
|
else if (win32_channel->type == G_IO_WIN32_SOCKET)
|
||||||
create_reader_thread (win32_channel, sock_reader);
|
create_thread (win32_channel, condition, select_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Binary compatibility */
|
||||||
|
GIOChannel *
|
||||||
|
g_io_channel_win32_new_stream_socket (int socket)
|
||||||
|
{
|
||||||
|
return g_io_channel_win32_new_socket (socket);
|
||||||
}
|
}
|
||||||
|
1
glib.def
1
glib.def
@ -180,6 +180,7 @@ EXPORTS
|
|||||||
g_io_channel_win32_make_pollfd
|
g_io_channel_win32_make_pollfd
|
||||||
g_io_channel_win32_new_fd
|
g_io_channel_win32_new_fd
|
||||||
g_io_channel_win32_new_messages
|
g_io_channel_win32_new_messages
|
||||||
|
g_io_channel_win32_new_socket
|
||||||
g_io_channel_win32_new_stream_socket
|
g_io_channel_win32_new_stream_socket
|
||||||
g_io_channel_win32_poll
|
g_io_channel_win32_poll
|
||||||
g_io_channel_win32_set_debug
|
g_io_channel_win32_set_debug
|
||||||
|
@ -120,14 +120,20 @@ guint g_io_add_watch (GIOChannel *channel,
|
|||||||
/* On Unix, IO channels created with this function for any file
|
/* On Unix, IO channels created with this function for any file
|
||||||
* descriptor or socket.
|
* descriptor or socket.
|
||||||
*
|
*
|
||||||
* On Win32, use this only for files opened with the MSVCRT (the
|
* On Win32, this can be used either for files opened with the MSVCRT
|
||||||
* Microsoft run-time C library) _open() or _pipe, including file
|
* (the Microsoft run-time C library) _open() or _pipe, including file
|
||||||
* descriptors 0, 1 and 2 (corresponding to stdin, stdout and stderr).
|
* descriptors 0, 1 and 2 (corresponding to stdin, stdout and stderr),
|
||||||
|
* or for Winsock SOCKETs. If the parameter is a legal file
|
||||||
|
* descriptor, it is assumed to be such, otherwise it should be a
|
||||||
|
* SOCKET. This relies on SOCKETs and file descriptors not
|
||||||
|
* overlapping. If you want to be certain, call either
|
||||||
|
* g_io_channel_win32_new_fd() or g_io_channel_win32_new_socket()
|
||||||
|
* instead as appropriate.
|
||||||
*
|
*
|
||||||
* The term file descriptor as used in the context of Win32 refers to
|
* The term file descriptor as used in the context of Win32 refers to
|
||||||
* the emulated Unix-like file descriptors MSVCRT provides. The native
|
* the emulated Unix-like file descriptors MSVCRT provides. The native
|
||||||
* corresponding concept is file HANDLE. There isn't as of yet a way to
|
* corresponding concept is file HANDLE. There isn't as of yet a way to
|
||||||
* get GIOChannels for file HANDLEs.
|
* get GIOChannels for Win32 file HANDLEs.
|
||||||
*/
|
*/
|
||||||
GIOChannel* g_io_channel_unix_new (int fd);
|
GIOChannel* g_io_channel_unix_new (int fd);
|
||||||
gint g_io_channel_unix_get_fd (GIOChannel *channel);
|
gint g_io_channel_unix_get_fd (GIOChannel *channel);
|
||||||
@ -139,7 +145,8 @@ gint g_io_channel_unix_get_fd (GIOChannel *channel);
|
|||||||
/* Use this to get a GPollFD from a GIOChannel, so that you can call
|
/* Use this to get a GPollFD from a GIOChannel, so that you can call
|
||||||
* g_io_channel_win32_poll(). After calling this you should only use
|
* g_io_channel_win32_poll(). After calling this you should only use
|
||||||
* g_io_channel_read() to read from the GIOChannel, i.e. never read()
|
* g_io_channel_read() to read from the GIOChannel, i.e. never read()
|
||||||
* or recv() from the underlying file descriptor or SOCKET.
|
* from the underlying file descriptor. For SOCKETs, it is possible to call
|
||||||
|
* recv().
|
||||||
*/
|
*/
|
||||||
void g_io_channel_win32_make_pollfd (GIOChannel *channel,
|
void g_io_channel_win32_make_pollfd (GIOChannel *channel,
|
||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
@ -147,7 +154,6 @@ void g_io_channel_win32_make_pollfd (GIOChannel *channel,
|
|||||||
|
|
||||||
/* This can be used to wait a until at least one of the channels is readable.
|
/* This can be used to wait a until at least one of the channels is readable.
|
||||||
* On Unix you would do a select() on the file descriptors of the channels.
|
* On Unix you would do a select() on the file descriptors of the channels.
|
||||||
* This should probably be available for all platforms?
|
|
||||||
*/
|
*/
|
||||||
gint g_io_channel_win32_poll (GPollFD *fds,
|
gint g_io_channel_win32_poll (GPollFD *fds,
|
||||||
gint n_fds,
|
gint n_fds,
|
||||||
@ -160,25 +166,29 @@ void g_main_poll_win32_msg_add (gint priority,
|
|||||||
GPollFD *fd,
|
GPollFD *fd,
|
||||||
guint hwnd);
|
guint hwnd);
|
||||||
|
|
||||||
/* An IO channel for Windows messages for window handle hwnd. */
|
/* Create an IO channel for Windows messages for window handle hwnd. */
|
||||||
GIOChannel *g_io_channel_win32_new_messages (guint hwnd);
|
GIOChannel *g_io_channel_win32_new_messages (guint hwnd);
|
||||||
|
|
||||||
/* An IO channel for C runtime (emulated Unix-like) file
|
/* Create an IO channel for C runtime (emulated Unix-like) file
|
||||||
* descriptors. Identical to g_io_channel_unix_new above.
|
* descriptors. After calling g_io_add_watch() on a IO channel
|
||||||
* After calling g_io_add_watch() on a IO channel returned
|
* returned by this function, you shouldn't call read() on the file
|
||||||
* by this function, you shouldn't call read() on the file
|
* descriptor. This is because adding polling for a file descriptor is
|
||||||
* descriptor.
|
* implemented on Win32 by starting a thread that sits blocked in a
|
||||||
|
* read() from the file descriptor most of the time. All reads from
|
||||||
|
* the file descriptor should be done by this internal GLib
|
||||||
|
* thread. Your code should call only g_io_channel_read().
|
||||||
*/
|
*/
|
||||||
GIOChannel* g_io_channel_win32_new_fd (int fd);
|
GIOChannel* g_io_channel_win32_new_fd (int fd);
|
||||||
|
|
||||||
/* Get the C runtime file descriptor of a channel. */
|
/* Get the C runtime file descriptor of a channel. */
|
||||||
gint g_io_channel_win32_get_fd (GIOChannel *channel);
|
gint g_io_channel_win32_get_fd (GIOChannel *channel);
|
||||||
|
|
||||||
/* An IO channel for a SOCK_STREAM winsock socket. The parameter
|
/* Create an IO channel for a winsock socket. The parameter should be
|
||||||
* should be a SOCKET. After calling g_io_add_watch() on a IO channel
|
* a SOCKET. Contrary to IO channels for file descriptors (on *Win32),
|
||||||
* returned by this function, you shouldn't call recv() on the SOCKET.
|
* you can use normal recv() or recvfrom() on sockets even if GLib
|
||||||
|
* is polling them.
|
||||||
*/
|
*/
|
||||||
GIOChannel *g_io_channel_win32_new_stream_socket (int socket);
|
GIOChannel *g_io_channel_win32_new_socket (int socket);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
431
glib/giowin32.c
431
glib/giowin32.c
@ -48,13 +48,13 @@ typedef struct _GIOWin32Watch GIOWin32Watch;
|
|||||||
#define BUFFER_SIZE 4096
|
#define BUFFER_SIZE 4096
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
G_IO_WINDOWS_MESSAGES, /* Windows messages */
|
G_IO_WIN32_WINDOWS_MESSAGES, /* Windows messages */
|
||||||
G_IO_FILE_DESC, /* Unix-like file descriptors from
|
G_IO_WIN32_FILE_DESC, /* Unix-like file descriptors from
|
||||||
* _open() or _pipe(). Read with read().
|
* _open() or _pipe(). Read with read().
|
||||||
* Have to create separate thread to read.
|
* Have to create separate thread to read.
|
||||||
*/
|
*/
|
||||||
G_IO_STREAM_SOCKET /* Stream sockets. Similar as fds, but
|
G_IO_WIN32_SOCKET /* Sockets. A separate thread is blocked
|
||||||
* read with recv().
|
* in select() most of the time.
|
||||||
*/
|
*/
|
||||||
} GIOWin32ChannelType;
|
} GIOWin32ChannelType;
|
||||||
|
|
||||||
@ -68,10 +68,26 @@ struct _GIOWin32Channel {
|
|||||||
|
|
||||||
gboolean debug;
|
gboolean debug;
|
||||||
|
|
||||||
/* This is used by G_IO_WINDOWS_MESSAGES channels */
|
CRITICAL_SECTION mutex;
|
||||||
|
|
||||||
|
/* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
|
||||||
HWND hwnd; /* handle of window, or NULL */
|
HWND hwnd; /* handle of window, or NULL */
|
||||||
|
|
||||||
/* Following fields used by fd and socket channels for input */
|
/* Following fields are used by both fd and socket channels. */
|
||||||
|
gboolean running; /* Is reader thread running. FALSE if
|
||||||
|
* EOF has been reached.
|
||||||
|
*/
|
||||||
|
gboolean needs_close; /* If the channel has been closed while
|
||||||
|
* the reader thread was still running.
|
||||||
|
*/
|
||||||
|
guint thread_id; /* If non-NULL has a reader thread, or has
|
||||||
|
* had.*/
|
||||||
|
HANDLE thread_handle;
|
||||||
|
HANDLE data_avail_event;
|
||||||
|
|
||||||
|
gushort revents;
|
||||||
|
|
||||||
|
/* Following fields used by fd channels for input */
|
||||||
|
|
||||||
/* Data is kept in a circular buffer. To be able to distinguish between
|
/* 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
|
* empty and full buffer, we cannot fill it completely, but have to
|
||||||
@ -85,21 +101,11 @@ struct _GIOWin32Channel {
|
|||||||
*/
|
*/
|
||||||
guchar *buffer; /* (Circular) buffer */
|
guchar *buffer; /* (Circular) buffer */
|
||||||
gint wrp, rdp; /* Buffer indices for writing and reading */
|
gint wrp, rdp; /* Buffer indices for writing and reading */
|
||||||
gboolean running; /* Is reader thread running. FALSE if
|
|
||||||
* EOF has been reached.
|
|
||||||
*/
|
|
||||||
gboolean needs_close; /* If the channel has been closed while
|
|
||||||
* the reader thread was still running.
|
|
||||||
*/
|
|
||||||
guint thread_id; /* If non-NULL has a reader thread, or has
|
|
||||||
* had.*/
|
|
||||||
HANDLE thread_handle;
|
|
||||||
HANDLE data_avail_event;
|
|
||||||
HANDLE space_avail_event;
|
HANDLE space_avail_event;
|
||||||
CRITICAL_SECTION mutex;
|
|
||||||
|
|
||||||
/* Function that actually reads from fd */
|
/* Following fields used by socket channels */
|
||||||
int (*reader) (int fd, guchar *buf, int len);
|
GSList *watches;
|
||||||
|
HANDLE data_avail_noticed_event;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define LOCK(mutex) EnterCriticalSection (&mutex)
|
#define LOCK(mutex) EnterCriticalSection (&mutex)
|
||||||
@ -129,7 +135,10 @@ g_io_channel_win32_init (GIOWin32Channel *channel)
|
|||||||
channel->needs_close = FALSE;
|
channel->needs_close = FALSE;
|
||||||
channel->thread_id = 0;
|
channel->thread_id = 0;
|
||||||
channel->data_avail_event = NULL;
|
channel->data_avail_event = NULL;
|
||||||
|
channel->revents = 0;
|
||||||
channel->space_avail_event = NULL;
|
channel->space_avail_event = NULL;
|
||||||
|
channel->data_avail_noticed_event = NULL;
|
||||||
|
channel->watches = NULL;
|
||||||
InitializeCriticalSection (&channel->mutex);
|
InitializeCriticalSection (&channel->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +155,8 @@ create_events (GIOWin32Channel *channel)
|
|||||||
* is automatic reset.
|
* is automatic reset.
|
||||||
*/
|
*/
|
||||||
if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
|
if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
|
||||||
|| !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
|
|| !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))
|
||||||
|
|| !(channel->data_avail_noticed_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
|
||||||
{
|
{
|
||||||
gchar *msg = g_win32_error_message (GetLastError ());
|
gchar *msg = g_win32_error_message (GetLastError ());
|
||||||
g_error ("Error creating event: %s", msg);
|
g_error ("Error creating event: %s", msg);
|
||||||
@ -154,18 +164,18 @@ create_events (GIOWin32Channel *channel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned __stdcall
|
static unsigned __stdcall
|
||||||
reader_thread (void *parameter)
|
read_thread (void *parameter)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *channel = parameter;
|
GIOWin32Channel *channel = parameter;
|
||||||
|
GSList *tmp;
|
||||||
guchar *buffer;
|
guchar *buffer;
|
||||||
guint nbytes;
|
guint nbytes;
|
||||||
|
|
||||||
g_io_channel_ref ((GIOChannel *) channel);
|
g_io_channel_ref ((GIOChannel *)channel);
|
||||||
|
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: starting. pid:%#x, fd:%d, data_avail:%#x, space_avail:%#x\n",
|
g_print ("read_thread %#x: start fd:%d, data_avail:%#x, space_avail:%#x\n",
|
||||||
channel->thread_id,
|
channel->thread_id,
|
||||||
(guint) GetCurrentProcessId (),
|
|
||||||
channel->fd,
|
channel->fd,
|
||||||
(guint) channel->data_avail_event,
|
(guint) channel->data_avail_event,
|
||||||
(guint) channel->space_avail_event);
|
(guint) channel->space_avail_event);
|
||||||
@ -180,22 +190,23 @@ reader_thread (void *parameter)
|
|||||||
{
|
{
|
||||||
LOCK (channel->mutex);
|
LOCK (channel->mutex);
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: rdp=%d, wrp=%d\n",
|
g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
channel->thread_id, channel->rdp, channel->wrp);
|
||||||
if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
|
if ((channel->wrp + 1) % BUFFER_SIZE == channel->rdp)
|
||||||
{
|
{
|
||||||
/* Buffer is full */
|
/* Buffer is full */
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: resetting space_available\n",
|
g_print ("read_thread %#x: resetting space_avail\n",
|
||||||
channel->thread_id);
|
channel->thread_id);
|
||||||
ResetEvent (channel->space_avail_event);
|
ResetEvent (channel->space_avail_event);
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: waiting for space\n", channel->thread_id);
|
g_print ("read_thread %#x: waiting for space\n",
|
||||||
|
channel->thread_id);
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
WaitForSingleObject (channel->space_avail_event, INFINITE);
|
WaitForSingleObject (channel->space_avail_event, INFINITE);
|
||||||
LOCK (channel->mutex);
|
LOCK (channel->mutex);
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: rdp=%d, wrp=%d\n",
|
g_print ("read_thread %#x: rdp=%d, wrp=%d\n",
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
channel->thread_id, channel->rdp, channel->wrp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,17 +219,23 @@ reader_thread (void *parameter)
|
|||||||
BUFFER_SIZE - channel->wrp);
|
BUFFER_SIZE - channel->wrp);
|
||||||
|
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: calling reader for %d bytes\n",
|
g_print ("read_thread %#x: calling read() for %d bytes\n",
|
||||||
channel->thread_id, nbytes);
|
channel->thread_id, nbytes);
|
||||||
|
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
|
|
||||||
nbytes = (*channel->reader) (channel->fd, buffer, nbytes);
|
nbytes = read (channel->fd, buffer, nbytes);
|
||||||
|
|
||||||
LOCK (channel->mutex);
|
LOCK (channel->mutex);
|
||||||
|
|
||||||
|
channel->revents = G_IO_IN;
|
||||||
|
if (nbytes == 0)
|
||||||
|
channel->revents |= G_IO_HUP;
|
||||||
|
else if (nbytes < 0)
|
||||||
|
channel->revents |= G_IO_ERR;
|
||||||
|
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: got %d bytes, rdp=%d, wrp=%d\n",
|
g_print ("read_thread %#x: read() returned %d, rdp=%d, wrp=%d\n",
|
||||||
channel->thread_id, nbytes, channel->rdp, channel->wrp);
|
channel->thread_id, nbytes, channel->rdp, channel->wrp);
|
||||||
|
|
||||||
if (nbytes <= 0)
|
if (nbytes <= 0)
|
||||||
@ -226,33 +243,29 @@ reader_thread (void *parameter)
|
|||||||
|
|
||||||
channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
|
channel->wrp = (channel->wrp + nbytes) % BUFFER_SIZE;
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: rdp=%d, wrp=%d, setting data available\n",
|
g_print ("read_thread %#x: rdp=%d, wrp=%d, setting data_avail\n",
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
channel->thread_id, channel->rdp, channel->wrp);
|
||||||
SetEvent (channel->data_avail_event);
|
SetEvent (channel->data_avail_event);
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
channel->running = FALSE;
|
channel->running = FALSE;
|
||||||
if (channel->debug)
|
|
||||||
g_print ("thread %#x: got EOF, rdp=%d, wrp=%d, setting data available\n",
|
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
|
||||||
|
|
||||||
if (channel->needs_close)
|
if (channel->needs_close)
|
||||||
{
|
{
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("thread %#x: channel fd %d needs closing\n",
|
g_print ("read_thread %#x: channel fd %d needs closing\n",
|
||||||
channel->thread_id, channel->fd);
|
channel->thread_id, channel->fd);
|
||||||
if (channel->type == G_IO_FILE_DESC)
|
|
||||||
close (channel->fd);
|
close (channel->fd);
|
||||||
else if (channel->type == G_IO_STREAM_SOCKET)
|
|
||||||
closesocket (channel->fd);
|
|
||||||
channel->fd = -1;
|
channel->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("read_thread %#x: EOF, rdp=%d, wrp=%d, setting data_avail\n",
|
||||||
|
channel->thread_id, channel->rdp, channel->wrp);
|
||||||
SetEvent (channel->data_avail_event);
|
SetEvent (channel->data_avail_event);
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
|
|
||||||
g_io_channel_unref((GIOChannel *) channel);
|
g_io_channel_unref((GIOChannel *)channel);
|
||||||
|
|
||||||
/* No need to call _endthreadex(), the actual thread starter routine
|
/* No need to call _endthreadex(), the actual thread starter routine
|
||||||
* in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
|
* in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
|
||||||
@ -265,13 +278,12 @@ reader_thread (void *parameter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_reader_thread (GIOWin32Channel *channel,
|
create_thread (GIOWin32Channel *channel,
|
||||||
gpointer reader)
|
GIOCondition condition,
|
||||||
|
unsigned (__stdcall *thread) (void *parameter))
|
||||||
{
|
{
|
||||||
channel->reader = reader;
|
|
||||||
|
|
||||||
if ((channel->thread_handle =
|
if ((channel->thread_handle =
|
||||||
(HANDLE) _beginthreadex (NULL, 0, reader_thread, channel, 0,
|
(HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
|
||||||
&channel->thread_id)) == 0)
|
&channel->thread_id)) == 0)
|
||||||
g_warning ("Error creating reader thread: %s", strerror (errno));
|
g_warning ("Error creating reader thread: %s", strerror (errno));
|
||||||
WaitForSingleObject (channel->space_avail_event, INFINITE);
|
WaitForSingleObject (channel->space_avail_event, INFINITE);
|
||||||
@ -291,7 +303,7 @@ buffer_read (GIOWin32Channel *channel,
|
|||||||
g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
|
g_print ("reading from thread %#x %d bytes, rdp=%d, wrp=%d\n",
|
||||||
channel->thread_id, count, channel->rdp, channel->wrp);
|
channel->thread_id, count, channel->rdp, channel->wrp);
|
||||||
|
|
||||||
if (channel->rdp == channel->wrp)
|
if (channel->wrp == channel->rdp)
|
||||||
{
|
{
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
@ -300,7 +312,7 @@ buffer_read (GIOWin32Channel *channel,
|
|||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("done waiting for data from thread %#x\n", channel->thread_id);
|
g_print ("done waiting for data from thread %#x\n", channel->thread_id);
|
||||||
LOCK (channel->mutex);
|
LOCK (channel->mutex);
|
||||||
if (channel->rdp == channel->wrp && !channel->running)
|
if (channel->wrp == channel->rdp && !channel->running)
|
||||||
{
|
{
|
||||||
UNLOCK (channel->mutex);
|
UNLOCK (channel->mutex);
|
||||||
return 0;
|
return 0;
|
||||||
@ -322,15 +334,15 @@ buffer_read (GIOWin32Channel *channel,
|
|||||||
LOCK (channel->mutex);
|
LOCK (channel->mutex);
|
||||||
channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
|
channel->rdp = (channel->rdp + nbytes) % BUFFER_SIZE;
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("setting space available for thread %#x\n", channel->thread_id);
|
g_print ("setting space_avail for thread %#x\n", channel->thread_id);
|
||||||
SetEvent (channel->space_avail_event);
|
SetEvent (channel->space_avail_event);
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("for thread %#x: rdp=%d, wrp=%d\n",
|
g_print ("for thread %#x: rdp=%d, wrp=%d\n",
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
channel->thread_id, channel->rdp, channel->wrp);
|
||||||
if (channel->running && channel->rdp == channel->wrp)
|
if (channel->running && channel->wrp == channel->rdp)
|
||||||
{
|
{
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("resetting data_available of thread %#x\n",
|
g_print ("resetting data_avail of thread %#x\n",
|
||||||
channel->thread_id);
|
channel->thread_id);
|
||||||
ResetEvent (channel->data_avail_event);
|
ResetEvent (channel->data_avail_event);
|
||||||
};
|
};
|
||||||
@ -343,12 +355,154 @@ buffer_read (GIOWin32Channel *channel,
|
|||||||
return count - left;
|
return count - left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned __stdcall
|
||||||
|
select_thread (void *parameter)
|
||||||
|
{
|
||||||
|
GIOWin32Channel *channel = parameter;
|
||||||
|
fd_set read_fds, write_fds, except_fds;
|
||||||
|
GSList *tmp;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
g_io_channel_ref ((GIOChannel *)channel);
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: start fd:%d,\n\tdata_avail:%#x, data_avail_noticed:%#x\n",
|
||||||
|
channel->thread_id,
|
||||||
|
channel->fd,
|
||||||
|
(guint) channel->data_avail_event,
|
||||||
|
(guint) channel->data_avail_noticed_event);
|
||||||
|
|
||||||
|
channel->rdp = channel->wrp = 0;
|
||||||
|
channel->running = TRUE;
|
||||||
|
|
||||||
|
SetEvent (channel->space_avail_event);
|
||||||
|
|
||||||
|
while (channel->running)
|
||||||
|
{
|
||||||
|
FD_ZERO (&read_fds);
|
||||||
|
FD_ZERO (&write_fds);
|
||||||
|
FD_ZERO (&except_fds);
|
||||||
|
|
||||||
|
tmp = channel->watches;
|
||||||
|
while (tmp)
|
||||||
|
{
|
||||||
|
GIOWin32Watch *watch = (GIOWin32Watch *)tmp->data;
|
||||||
|
|
||||||
|
if (watch->condition & (G_IO_IN | G_IO_HUP))
|
||||||
|
FD_SET (channel->fd, &read_fds);
|
||||||
|
if (watch->condition & G_IO_OUT)
|
||||||
|
FD_SET (channel->fd, &write_fds);
|
||||||
|
if (watch->condition & G_IO_ERR)
|
||||||
|
FD_SET (channel->fd, &except_fds);
|
||||||
|
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: calling select() for%s%s%s\n",
|
||||||
|
channel->thread_id,
|
||||||
|
(FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
|
||||||
|
(FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
|
||||||
|
(FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
|
||||||
|
|
||||||
|
n = select (1, &read_fds, &write_fds, &except_fds, NULL);
|
||||||
|
|
||||||
|
if (n == SOCKET_ERROR)
|
||||||
|
{
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
|
||||||
|
channel->thread_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: got%s%s%s\n",
|
||||||
|
channel->thread_id,
|
||||||
|
(FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
|
||||||
|
(FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
|
||||||
|
(FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
|
||||||
|
|
||||||
|
if (FD_ISSET (channel->fd, &read_fds))
|
||||||
|
channel->revents |= G_IO_IN;
|
||||||
|
if (FD_ISSET (channel->fd, &write_fds))
|
||||||
|
channel->revents |= G_IO_OUT;
|
||||||
|
if (FD_ISSET (channel->fd, &except_fds))
|
||||||
|
channel->revents |= G_IO_ERR;
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: resetting data_avail_noticed,\n"
|
||||||
|
"\tsetting data_avail\n",
|
||||||
|
channel->thread_id);
|
||||||
|
ResetEvent (channel->data_avail_noticed_event);
|
||||||
|
SetEvent (channel->data_avail_event);
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: waiting for data_avail_noticed\n",
|
||||||
|
channel->thread_id);
|
||||||
|
|
||||||
|
WaitForSingleObject (channel->data_avail_noticed_event, INFINITE);
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: got data_avail_noticed\n",
|
||||||
|
channel->thread_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
channel->running = FALSE;
|
||||||
|
LOCK (channel->mutex);
|
||||||
|
if (channel->needs_close)
|
||||||
|
{
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: channel fd %d needs closing\n",
|
||||||
|
channel->thread_id, channel->fd);
|
||||||
|
closesocket (channel->fd);
|
||||||
|
channel->fd = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("select_thread %#x: got error, setting data_avail\n",
|
||||||
|
channel->thread_id);
|
||||||
|
SetEvent (channel->data_avail_event);
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
CloseHandle (channel->thread_handle);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
g_io_win32_prepare (GSource *source,
|
g_io_win32_prepare (GSource *source,
|
||||||
gint *timeout)
|
gint *timeout)
|
||||||
{
|
{
|
||||||
|
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
||||||
|
GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
|
||||||
|
|
||||||
*timeout = -1;
|
*timeout = -1;
|
||||||
|
|
||||||
|
if (channel->type == G_IO_WIN32_FILE_DESC)
|
||||||
|
{
|
||||||
|
LOCK (channel->mutex);
|
||||||
|
if (channel->running && channel->wrp == channel->rdp)
|
||||||
|
channel->revents = 0;
|
||||||
|
UNLOCK (channel->mutex);
|
||||||
|
}
|
||||||
|
else if (channel->type == G_IO_WIN32_SOCKET)
|
||||||
|
{
|
||||||
|
channel->revents = 0;
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("g_io_win32_prepare: thread %#x, setting data_avail_noticed\n",
|
||||||
|
channel->thread_id);
|
||||||
|
SetEvent (channel->data_avail_noticed_event);
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("g_io_win32_prepare: thread %#x, there.\n",
|
||||||
|
channel->thread_id);
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,18 +510,26 @@ static gboolean
|
|||||||
g_io_win32_check (GSource *source)
|
g_io_win32_check (GSource *source)
|
||||||
{
|
{
|
||||||
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
||||||
GIOWin32Channel *channel = (GIOWin32Channel *) watch->channel;
|
GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
|
||||||
|
|
||||||
/* If the thread has died, we have encountered EOF. If the buffer
|
if (channel->debug)
|
||||||
* also is emtpty set the HUP bit.
|
g_print ("g_io_win32_check: for thread %#x:\n"
|
||||||
*/
|
"\twatch->pollfd.events:%#x, watch->pollfd.revents:%#x, channel->revents:%#x\n",
|
||||||
if (!channel->running && channel->rdp == channel->wrp)
|
channel->thread_id,
|
||||||
|
watch->pollfd.events, watch->pollfd.revents, channel->revents);
|
||||||
|
|
||||||
|
if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
|
||||||
|
watch->pollfd.revents = (watch->pollfd.events & channel->revents);
|
||||||
|
|
||||||
|
if (channel->type == G_IO_WIN32_SOCKET)
|
||||||
{
|
{
|
||||||
if (channel->debug)
|
if (channel->debug)
|
||||||
g_print ("g_io_win32_check: setting G_IO_HUP thread %#x rdp=%d wrp=%d\n",
|
g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
|
||||||
channel->thread_id, channel->rdp, channel->wrp);
|
channel->thread_id);
|
||||||
watch->pollfd.revents |= G_IO_HUP;
|
ResetEvent (channel->data_avail_event);
|
||||||
return TRUE;
|
if (channel->debug)
|
||||||
|
g_print ("g_io_win32_check: thread %#x, there.\n",
|
||||||
|
channel->thread_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (watch->pollfd.revents & watch->condition);
|
return (watch->pollfd.revents & watch->condition);
|
||||||
@ -397,6 +559,13 @@ static void
|
|||||||
g_io_win32_destroy (GSource *source)
|
g_io_win32_destroy (GSource *source)
|
||||||
{
|
{
|
||||||
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
GIOWin32Watch *watch = (GIOWin32Watch *)source;
|
||||||
|
GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
|
||||||
|
|
||||||
|
if (channel->debug)
|
||||||
|
g_print ("g_io_win32_destroy: channel with thread %#x\n",
|
||||||
|
channel->thread_id);
|
||||||
|
|
||||||
|
channel->watches = g_slist_remove (channel->watches, watch);
|
||||||
|
|
||||||
g_io_channel_unref (watch->channel);
|
g_io_channel_unref (watch->channel);
|
||||||
}
|
}
|
||||||
@ -411,9 +580,9 @@ static GSourceFuncs win32_watch_funcs = {
|
|||||||
static GSource *
|
static GSource *
|
||||||
g_io_win32_create_watch (GIOChannel *channel,
|
g_io_win32_create_watch (GIOChannel *channel,
|
||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
int (*reader) (int, guchar *, int))
|
unsigned (__stdcall *thread) (void *parameter))
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
GIOWin32Watch *watch;
|
GIOWin32Watch *watch;
|
||||||
GSource *source;
|
GSource *source;
|
||||||
|
|
||||||
@ -432,11 +601,13 @@ g_io_win32_create_watch (GIOChannel *channel,
|
|||||||
watch->pollfd.events = condition;
|
watch->pollfd.events = condition;
|
||||||
|
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("g_io_win32_create_watch: fd:%d handle:%#x\n",
|
g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
|
||||||
win32_channel->fd, watch->pollfd.fd);
|
win32_channel->fd, condition, watch->pollfd.fd);
|
||||||
|
|
||||||
|
win32_channel->watches = g_slist_append (win32_channel->watches, watch);
|
||||||
|
|
||||||
if (win32_channel->thread_id == 0)
|
if (win32_channel->thread_id == 0)
|
||||||
create_reader_thread (win32_channel, reader);
|
create_thread (win32_channel, condition, thread);
|
||||||
|
|
||||||
g_source_add_poll (source, &watch->pollfd);
|
g_source_add_poll (source, &watch->pollfd);
|
||||||
|
|
||||||
@ -449,12 +620,15 @@ g_io_win32_msg_read (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_read)
|
guint *bytes_read)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
MSG msg; /* In case of alignment problems */
|
MSG msg; /* In case of alignment problems */
|
||||||
|
|
||||||
if (count < sizeof (MSG))
|
if (count < sizeof (MSG))
|
||||||
return G_IO_ERROR_INVAL;
|
return G_IO_ERROR_INVAL;
|
||||||
|
|
||||||
|
if (win32_channel->debug)
|
||||||
|
g_print ("g_io_win32_msg_read: for %#x\n",
|
||||||
|
win32_channel->hwnd);
|
||||||
if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
|
if (!PeekMessage (&msg, win32_channel->hwnd, 0, 0, PM_REMOVE))
|
||||||
return G_IO_ERROR_AGAIN;
|
return G_IO_ERROR_AGAIN;
|
||||||
|
|
||||||
@ -469,7 +643,7 @@ g_io_win32_msg_write (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_written)
|
guint *bytes_written)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
if (count != sizeof (MSG))
|
if (count != sizeof (MSG))
|
||||||
@ -501,21 +675,23 @@ g_io_win32_msg_close (GIOChannel *channel)
|
|||||||
static void
|
static void
|
||||||
g_io_win32_free (GIOChannel *channel)
|
g_io_win32_free (GIOChannel *channel)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("thread %#x: freeing channel, fd: %d\n",
|
g_print ("thread %#x: freeing channel, fd: %d\n",
|
||||||
win32_channel->thread_id,
|
win32_channel->thread_id,
|
||||||
win32_channel->fd);
|
win32_channel->fd);
|
||||||
|
|
||||||
if (win32_channel->buffer)
|
if (win32_channel->data_avail_event)
|
||||||
{
|
|
||||||
CloseHandle (win32_channel->data_avail_event);
|
CloseHandle (win32_channel->data_avail_event);
|
||||||
|
if (win32_channel->space_avail_event)
|
||||||
CloseHandle (win32_channel->space_avail_event);
|
CloseHandle (win32_channel->space_avail_event);
|
||||||
|
if (win32_channel->data_avail_noticed_event)
|
||||||
|
CloseHandle (win32_channel->data_avail_noticed_event);
|
||||||
DeleteCriticalSection (&win32_channel->mutex);
|
DeleteCriticalSection (&win32_channel->mutex);
|
||||||
}
|
|
||||||
|
|
||||||
g_free (win32_channel->buffer);
|
g_free (win32_channel->buffer);
|
||||||
|
g_slist_free (win32_channel->watches);
|
||||||
g_free (win32_channel);
|
g_free (win32_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,7 +724,7 @@ g_io_win32_fd_read (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_read)
|
guint *bytes_read)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
gint result;
|
gint result;
|
||||||
GIOError error;
|
GIOError error;
|
||||||
|
|
||||||
@ -594,7 +770,7 @@ g_io_win32_fd_write (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_written)
|
guint *bytes_written)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
gint result;
|
gint result;
|
||||||
|
|
||||||
result = write (win32_channel->fd, buf, count);
|
result = write (win32_channel->fd, buf, count);
|
||||||
@ -627,7 +803,7 @@ g_io_win32_fd_seek (GIOChannel *channel,
|
|||||||
gint offset,
|
gint offset,
|
||||||
GSeekType type)
|
GSeekType type)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
int whence;
|
int whence;
|
||||||
off_t result;
|
off_t result;
|
||||||
|
|
||||||
@ -666,7 +842,7 @@ g_io_win32_fd_seek (GIOChannel *channel,
|
|||||||
static void
|
static void
|
||||||
g_io_win32_fd_close (GIOChannel *channel)
|
g_io_win32_fd_close (GIOChannel *channel)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("thread %#x: closing fd %d\n",
|
g_print ("thread %#x: closing fd %d\n",
|
||||||
@ -695,19 +871,11 @@ g_io_win32_fd_close (GIOChannel *channel)
|
|||||||
UNLOCK (win32_channel->mutex);
|
UNLOCK (win32_channel->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
fd_reader (int fd,
|
|
||||||
guchar *buf,
|
|
||||||
int len)
|
|
||||||
{
|
|
||||||
return read (fd, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GSource *
|
static GSource *
|
||||||
g_io_win32_fd_create_watch (GIOChannel *channel,
|
g_io_win32_fd_create_watch (GIOChannel *channel,
|
||||||
GIOCondition condition)
|
GIOCondition condition)
|
||||||
{
|
{
|
||||||
return g_io_win32_create_watch (channel, condition, fd_reader);
|
return g_io_win32_create_watch (channel, condition, read_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GIOError
|
static GIOError
|
||||||
@ -716,32 +884,33 @@ g_io_win32_sock_read (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_read)
|
guint *bytes_read)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
gint result;
|
gint result;
|
||||||
GIOError error;
|
GIOError error;
|
||||||
|
|
||||||
if (win32_channel->thread_id)
|
if (win32_channel->debug)
|
||||||
{
|
g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
|
||||||
result = buffer_read (win32_channel, buf, count, &error);
|
win32_channel->fd, count);
|
||||||
if (result < 0)
|
|
||||||
{
|
|
||||||
*bytes_read = 0;
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*bytes_read = result;
|
|
||||||
return G_IO_ERROR_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = recv (win32_channel->fd, buf, count, 0);
|
result = recv (win32_channel->fd, buf, count, 0);
|
||||||
|
|
||||||
if (result < 0)
|
if (win32_channel->debug)
|
||||||
|
g_print ("g_io_win32_sock_read: recv:%d\n", result);
|
||||||
|
|
||||||
|
if (result == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
*bytes_read = 0;
|
*bytes_read = 0;
|
||||||
|
switch (WSAGetLastError ())
|
||||||
|
{
|
||||||
|
case WSAEINVAL:
|
||||||
|
return G_IO_ERROR_INVAL;
|
||||||
|
case WSAEWOULDBLOCK:
|
||||||
|
case WSAEINTR:
|
||||||
|
return G_IO_ERROR_AGAIN;
|
||||||
|
default:
|
||||||
return G_IO_ERROR_UNKNOWN;
|
return G_IO_ERROR_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*bytes_read = result;
|
*bytes_read = result;
|
||||||
@ -755,11 +924,18 @@ g_io_win32_sock_write (GIOChannel *channel,
|
|||||||
guint count,
|
guint count,
|
||||||
guint *bytes_written)
|
guint *bytes_written)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
gint result;
|
gint result;
|
||||||
|
|
||||||
|
if (win32_channel->debug)
|
||||||
|
g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
|
||||||
|
win32_channel->fd, count);
|
||||||
|
|
||||||
result = send (win32_channel->fd, buf, count, 0);
|
result = send (win32_channel->fd, buf, count, 0);
|
||||||
|
|
||||||
|
if (win32_channel->debug)
|
||||||
|
g_print ("g_io_win32_sock_write: send:%d\n", result);
|
||||||
|
|
||||||
if (result == SOCKET_ERROR)
|
if (result == SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
*bytes_written = 0;
|
*bytes_written = 0;
|
||||||
@ -784,7 +960,7 @@ g_io_win32_sock_write (GIOChannel *channel,
|
|||||||
static void
|
static void
|
||||||
g_io_win32_sock_close (GIOChannel *channel)
|
g_io_win32_sock_close (GIOChannel *channel)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("thread %#x: closing socket %d\n",
|
g_print ("thread %#x: closing socket %d\n",
|
||||||
@ -794,19 +970,11 @@ g_io_win32_sock_close (GIOChannel *channel)
|
|||||||
win32_channel->fd = -1;
|
win32_channel->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
sock_reader (int fd,
|
|
||||||
guchar *buf,
|
|
||||||
int len)
|
|
||||||
{
|
|
||||||
return recv (fd, buf, len, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GSource *
|
static GSource *
|
||||||
g_io_win32_sock_create_watch (GIOChannel *channel,
|
g_io_win32_sock_create_watch (GIOChannel *channel,
|
||||||
GIOCondition condition)
|
GIOCondition condition)
|
||||||
{
|
{
|
||||||
return g_io_win32_create_watch (channel, condition, sock_reader);
|
return g_io_win32_create_watch (channel, condition, select_thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GIOFuncs win32_channel_msg_funcs = {
|
static GIOFuncs win32_channel_msg_funcs = {
|
||||||
@ -840,14 +1008,14 @@ GIOChannel *
|
|||||||
g_io_channel_win32_new_messages (guint hwnd)
|
g_io_channel_win32_new_messages (guint hwnd)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
|
GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
|
||||||
GIOChannel *channel = (GIOChannel *) win32_channel;
|
GIOChannel *channel = (GIOChannel *)win32_channel;
|
||||||
|
|
||||||
g_io_channel_init (channel);
|
g_io_channel_init (channel);
|
||||||
g_io_channel_win32_init (win32_channel);
|
g_io_channel_win32_init (win32_channel);
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
|
g_print ("g_io_channel_win32_new_messages: hwnd = %ud\n", hwnd);
|
||||||
channel->funcs = &win32_channel_msg_funcs;
|
channel->funcs = &win32_channel_msg_funcs;
|
||||||
win32_channel->type = G_IO_WINDOWS_MESSAGES;
|
win32_channel->type = G_IO_WIN32_WINDOWS_MESSAGES;
|
||||||
win32_channel->hwnd = (HWND) hwnd;
|
win32_channel->hwnd = (HWND) hwnd;
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
@ -867,14 +1035,14 @@ g_io_channel_win32_new_fd (gint fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
win32_channel = g_new (GIOWin32Channel, 1);
|
win32_channel = g_new (GIOWin32Channel, 1);
|
||||||
channel = (GIOChannel *) win32_channel;
|
channel = (GIOChannel *)win32_channel;
|
||||||
|
|
||||||
g_io_channel_init (channel);
|
g_io_channel_init (channel);
|
||||||
g_io_channel_win32_init (win32_channel);
|
g_io_channel_win32_init (win32_channel);
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
|
g_print ("g_io_channel_win32_new_fd: fd = %d\n", fd);
|
||||||
channel->funcs = &win32_channel_fd_funcs;
|
channel->funcs = &win32_channel_fd_funcs;
|
||||||
win32_channel->type = G_IO_FILE_DESC;
|
win32_channel->type = G_IO_WIN32_FILE_DESC;
|
||||||
win32_channel->fd = fd;
|
win32_channel->fd = fd;
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
@ -883,23 +1051,23 @@ g_io_channel_win32_new_fd (gint fd)
|
|||||||
gint
|
gint
|
||||||
g_io_channel_win32_get_fd (GIOChannel *channel)
|
g_io_channel_win32_get_fd (GIOChannel *channel)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
return win32_channel->fd;
|
return win32_channel->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
GIOChannel *
|
GIOChannel *
|
||||||
g_io_channel_win32_new_stream_socket (int socket)
|
g_io_channel_win32_new_socket (int socket)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
|
GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
|
||||||
GIOChannel *channel = (GIOChannel *) win32_channel;
|
GIOChannel *channel = (GIOChannel *)win32_channel;
|
||||||
|
|
||||||
g_io_channel_init (channel);
|
g_io_channel_init (channel);
|
||||||
g_io_channel_win32_init (win32_channel);
|
g_io_channel_win32_init (win32_channel);
|
||||||
if (win32_channel->debug)
|
if (win32_channel->debug)
|
||||||
g_print ("g_io_channel_win32_new_stream_socket: socket = %d\n", socket);
|
g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
|
||||||
channel->funcs = &win32_channel_sock_funcs;
|
channel->funcs = &win32_channel_sock_funcs;
|
||||||
win32_channel->type = G_IO_STREAM_SOCKET;
|
win32_channel->type = G_IO_WIN32_SOCKET;
|
||||||
win32_channel->fd = socket;
|
win32_channel->fd = socket;
|
||||||
|
|
||||||
return channel;
|
return channel;
|
||||||
@ -914,9 +1082,9 @@ g_io_channel_unix_new (gint fd)
|
|||||||
return g_io_channel_win32_new_fd (fd);
|
return g_io_channel_win32_new_fd (fd);
|
||||||
|
|
||||||
if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
|
if (getsockopt (fd, SOL_SOCKET, SO_TYPE, NULL, NULL) != SO_ERROR)
|
||||||
return g_io_channel_win32_new_stream_socket(fd);
|
return g_io_channel_win32_new_socket(fd);
|
||||||
|
|
||||||
g_warning ("%d isn't a file descriptor or a socket", fd);
|
g_warning ("%d is neither a file descriptor or a socket", fd);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -930,7 +1098,7 @@ void
|
|||||||
g_io_channel_win32_set_debug (GIOChannel *channel,
|
g_io_channel_win32_set_debug (GIOChannel *channel,
|
||||||
gboolean flag)
|
gboolean flag)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
win32_channel->debug = flag;
|
win32_channel->debug = flag;
|
||||||
}
|
}
|
||||||
@ -954,7 +1122,7 @@ g_io_channel_win32_make_pollfd (GIOChannel *channel,
|
|||||||
GIOCondition condition,
|
GIOCondition condition,
|
||||||
GPollFD *fd)
|
GPollFD *fd)
|
||||||
{
|
{
|
||||||
GIOWin32Channel *win32_channel = (GIOWin32Channel *) channel;
|
GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
|
||||||
|
|
||||||
if (win32_channel->data_avail_event == NULL)
|
if (win32_channel->data_avail_event == NULL)
|
||||||
create_events (win32_channel);
|
create_events (win32_channel);
|
||||||
@ -963,8 +1131,15 @@ g_io_channel_win32_make_pollfd (GIOChannel *channel,
|
|||||||
fd->events = condition;
|
fd->events = condition;
|
||||||
|
|
||||||
if (win32_channel->thread_id == 0)
|
if (win32_channel->thread_id == 0)
|
||||||
if (win32_channel->type == G_IO_FILE_DESC)
|
if ((condition & G_IO_IN) && win32_channel->type == G_IO_WIN32_FILE_DESC)
|
||||||
create_reader_thread (win32_channel, fd_reader);
|
create_thread (win32_channel, condition, read_thread);
|
||||||
else if (win32_channel->type == G_IO_STREAM_SOCKET)
|
else if (win32_channel->type == G_IO_WIN32_SOCKET)
|
||||||
create_reader_thread (win32_channel, sock_reader);
|
create_thread (win32_channel, condition, select_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Binary compatibility */
|
||||||
|
GIOChannel *
|
||||||
|
g_io_channel_win32_new_stream_socket (int socket)
|
||||||
|
{
|
||||||
|
return g_io_channel_win32_new_socket (socket);
|
||||||
}
|
}
|
||||||
|
@ -180,6 +180,7 @@ EXPORTS
|
|||||||
g_io_channel_win32_make_pollfd
|
g_io_channel_win32_make_pollfd
|
||||||
g_io_channel_win32_new_fd
|
g_io_channel_win32_new_fd
|
||||||
g_io_channel_win32_new_messages
|
g_io_channel_win32_new_messages
|
||||||
|
g_io_channel_win32_new_socket
|
||||||
g_io_channel_win32_new_stream_socket
|
g_io_channel_win32_new_stream_socket
|
||||||
g_io_channel_win32_poll
|
g_io_channel_win32_poll
|
||||||
g_io_channel_win32_set_debug
|
g_io_channel_win32_set_debug
|
||||||
|
73
glib/gmain.c
73
glib/gmain.c
@ -272,48 +272,45 @@ g_poll (GPollFD *fds,
|
|||||||
|
|
||||||
if (poll_msgs)
|
if (poll_msgs)
|
||||||
{
|
{
|
||||||
/* Waiting for messages, and maybe events */
|
/* Waiting for messages, and maybe events
|
||||||
if (nhandles == 0)
|
* -> First PeekMessage
|
||||||
{
|
|
||||||
if (timeout == INFINITE)
|
|
||||||
{
|
|
||||||
/* Waiting just for messages, infinite timeout
|
|
||||||
* -> Use PeekMessage, then WaitMessage
|
|
||||||
*/
|
|
||||||
#ifdef G_MAIN_POLL_DEBUG
|
|
||||||
g_print ("PeekMessage, then WaitMessage\n");
|
|
||||||
#endif
|
|
||||||
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
|
||||||
ready = WAIT_OBJECT_0;
|
|
||||||
else if (!WaitMessage ())
|
|
||||||
g_warning ("g_poll: WaitMessage failed");
|
|
||||||
ready = WAIT_OBJECT_0;
|
|
||||||
}
|
|
||||||
else if (timeout == 0)
|
|
||||||
{
|
|
||||||
/* Waiting just for messages, zero timeout
|
|
||||||
* -> Use PeekMessage
|
|
||||||
*/
|
*/
|
||||||
#ifdef G_MAIN_POLL_DEBUG
|
#ifdef G_MAIN_POLL_DEBUG
|
||||||
g_print ("PeekMessage\n");
|
g_print ("PeekMessage\n");
|
||||||
#endif
|
#endif
|
||||||
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
||||||
ready = WAIT_OBJECT_0;
|
ready = WAIT_OBJECT_0 + nhandles;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (nhandles == 0)
|
||||||
|
{
|
||||||
|
/* Waiting just for messages */
|
||||||
|
if (timeout == INFINITE)
|
||||||
|
{
|
||||||
|
/* Infinite timeout
|
||||||
|
* -> WaitMessage
|
||||||
|
*/
|
||||||
|
#ifdef G_MAIN_POLL_DEBUG
|
||||||
|
g_print ("WaitMessage\n");
|
||||||
|
#endif
|
||||||
|
if (!WaitMessage ())
|
||||||
|
g_warning ("g_poll: WaitMessage failed");
|
||||||
|
ready = WAIT_OBJECT_0 + nhandles;
|
||||||
|
}
|
||||||
|
else if (timeout == 0)
|
||||||
|
{
|
||||||
|
/* Waiting just for messages, zero timeout.
|
||||||
|
* If we got here, there was no message
|
||||||
|
*/
|
||||||
ready = WAIT_TIMEOUT;
|
ready = WAIT_TIMEOUT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Waiting just for messages, some timeout
|
/* Waiting just for messages, some timeout
|
||||||
* -> First try PeekMessage, then set a timer, wait for message,
|
* -> Set a timer, wait for message,
|
||||||
* kill timer, use PeekMessage
|
* kill timer, use PeekMessage
|
||||||
*/
|
*/
|
||||||
#ifdef G_MAIN_POLL_DEBUG
|
if ((timer = SetTimer (NULL, 0, timeout, NULL)) == 0)
|
||||||
g_print ("PeekMessage\n");
|
|
||||||
#endif
|
|
||||||
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
|
||||||
ready = WAIT_OBJECT_0;
|
|
||||||
else if ((timer = SetTimer (NULL, 0, timeout, NULL)) == 0)
|
|
||||||
g_warning ("g_poll: SetTimer failed");
|
g_warning ("g_poll: SetTimer failed");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -322,6 +319,9 @@ g_poll (GPollFD *fds,
|
|||||||
#endif
|
#endif
|
||||||
WaitMessage ();
|
WaitMessage ();
|
||||||
KillTimer (NULL, timer);
|
KillTimer (NULL, timer);
|
||||||
|
#ifdef G_MAIN_POLL_DEBUG
|
||||||
|
g_print ("PeekMessage\n");
|
||||||
|
#endif
|
||||||
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)
|
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)
|
||||||
&& msg.message != WM_TIMER)
|
&& msg.message != WM_TIMER)
|
||||||
ready = WAIT_OBJECT_0;
|
ready = WAIT_OBJECT_0;
|
||||||
@ -345,6 +345,7 @@ g_poll (GPollFD *fds,
|
|||||||
g_warning ("g_poll: MsgWaitForMultipleObjects failed");
|
g_warning ("g_poll: MsgWaitForMultipleObjects failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (nhandles == 0)
|
else if (nhandles == 0)
|
||||||
{
|
{
|
||||||
/* Wait for nothing (huh?) */
|
/* Wait for nothing (huh?) */
|
||||||
@ -363,6 +364,13 @@ g_poll (GPollFD *fds,
|
|||||||
g_warning ("g_poll: WaitForMultipleObjects failed");
|
g_warning ("g_poll: WaitForMultipleObjects failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef G_MAIN_POLL_DEBUG
|
||||||
|
g_print ("wait returns %d%s\n",
|
||||||
|
ready,
|
||||||
|
(ready == WAIT_FAILED ? " (WAIT_FAILED)" :
|
||||||
|
(ready == WAIT_TIMEOUT ? " (WAIT_TIMEOUT)" :
|
||||||
|
(poll_msgs && ready == WAIT_OBJECT_0 + nhandles ? " (msg)" : ""))));
|
||||||
|
#endif
|
||||||
for (f = fds; f < &fds[nfds]; ++f)
|
for (f = fds; f < &fds[nfds]; ++f)
|
||||||
f->revents = 0;
|
f->revents = 0;
|
||||||
|
|
||||||
@ -380,6 +388,7 @@ g_poll (GPollFD *fds,
|
|||||||
f->revents |= G_IO_IN;
|
f->revents |= G_IO_IN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if TEST_WITHOUT_THIS
|
||||||
else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
|
else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
|
||||||
for (f = fds; f < &fds[nfds]; ++f)
|
for (f = fds; f < &fds[nfds]; ++f)
|
||||||
{
|
{
|
||||||
@ -395,11 +404,9 @@ g_poll (GPollFD *fds,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
|
return 1;
|
||||||
return ready - WAIT_OBJECT_0 + 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !G_OS_WIN32 */
|
#else /* !G_OS_WIN32 */
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
|
#include <stdio.h>
|
||||||
|
#define STRICT
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
73
gmain.c
73
gmain.c
@ -272,48 +272,45 @@ g_poll (GPollFD *fds,
|
|||||||
|
|
||||||
if (poll_msgs)
|
if (poll_msgs)
|
||||||
{
|
{
|
||||||
/* Waiting for messages, and maybe events */
|
/* Waiting for messages, and maybe events
|
||||||
if (nhandles == 0)
|
* -> First PeekMessage
|
||||||
{
|
|
||||||
if (timeout == INFINITE)
|
|
||||||
{
|
|
||||||
/* Waiting just for messages, infinite timeout
|
|
||||||
* -> Use PeekMessage, then WaitMessage
|
|
||||||
*/
|
|
||||||
#ifdef G_MAIN_POLL_DEBUG
|
|
||||||
g_print ("PeekMessage, then WaitMessage\n");
|
|
||||||
#endif
|
|
||||||
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
|
||||||
ready = WAIT_OBJECT_0;
|
|
||||||
else if (!WaitMessage ())
|
|
||||||
g_warning ("g_poll: WaitMessage failed");
|
|
||||||
ready = WAIT_OBJECT_0;
|
|
||||||
}
|
|
||||||
else if (timeout == 0)
|
|
||||||
{
|
|
||||||
/* Waiting just for messages, zero timeout
|
|
||||||
* -> Use PeekMessage
|
|
||||||
*/
|
*/
|
||||||
#ifdef G_MAIN_POLL_DEBUG
|
#ifdef G_MAIN_POLL_DEBUG
|
||||||
g_print ("PeekMessage\n");
|
g_print ("PeekMessage\n");
|
||||||
#endif
|
#endif
|
||||||
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
||||||
ready = WAIT_OBJECT_0;
|
ready = WAIT_OBJECT_0 + nhandles;
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (nhandles == 0)
|
||||||
|
{
|
||||||
|
/* Waiting just for messages */
|
||||||
|
if (timeout == INFINITE)
|
||||||
|
{
|
||||||
|
/* Infinite timeout
|
||||||
|
* -> WaitMessage
|
||||||
|
*/
|
||||||
|
#ifdef G_MAIN_POLL_DEBUG
|
||||||
|
g_print ("WaitMessage\n");
|
||||||
|
#endif
|
||||||
|
if (!WaitMessage ())
|
||||||
|
g_warning ("g_poll: WaitMessage failed");
|
||||||
|
ready = WAIT_OBJECT_0 + nhandles;
|
||||||
|
}
|
||||||
|
else if (timeout == 0)
|
||||||
|
{
|
||||||
|
/* Waiting just for messages, zero timeout.
|
||||||
|
* If we got here, there was no message
|
||||||
|
*/
|
||||||
ready = WAIT_TIMEOUT;
|
ready = WAIT_TIMEOUT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Waiting just for messages, some timeout
|
/* Waiting just for messages, some timeout
|
||||||
* -> First try PeekMessage, then set a timer, wait for message,
|
* -> Set a timer, wait for message,
|
||||||
* kill timer, use PeekMessage
|
* kill timer, use PeekMessage
|
||||||
*/
|
*/
|
||||||
#ifdef G_MAIN_POLL_DEBUG
|
if ((timer = SetTimer (NULL, 0, timeout, NULL)) == 0)
|
||||||
g_print ("PeekMessage\n");
|
|
||||||
#endif
|
|
||||||
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
|
|
||||||
ready = WAIT_OBJECT_0;
|
|
||||||
else if ((timer = SetTimer (NULL, 0, timeout, NULL)) == 0)
|
|
||||||
g_warning ("g_poll: SetTimer failed");
|
g_warning ("g_poll: SetTimer failed");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -322,6 +319,9 @@ g_poll (GPollFD *fds,
|
|||||||
#endif
|
#endif
|
||||||
WaitMessage ();
|
WaitMessage ();
|
||||||
KillTimer (NULL, timer);
|
KillTimer (NULL, timer);
|
||||||
|
#ifdef G_MAIN_POLL_DEBUG
|
||||||
|
g_print ("PeekMessage\n");
|
||||||
|
#endif
|
||||||
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)
|
if (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)
|
||||||
&& msg.message != WM_TIMER)
|
&& msg.message != WM_TIMER)
|
||||||
ready = WAIT_OBJECT_0;
|
ready = WAIT_OBJECT_0;
|
||||||
@ -345,6 +345,7 @@ g_poll (GPollFD *fds,
|
|||||||
g_warning ("g_poll: MsgWaitForMultipleObjects failed");
|
g_warning ("g_poll: MsgWaitForMultipleObjects failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (nhandles == 0)
|
else if (nhandles == 0)
|
||||||
{
|
{
|
||||||
/* Wait for nothing (huh?) */
|
/* Wait for nothing (huh?) */
|
||||||
@ -363,6 +364,13 @@ g_poll (GPollFD *fds,
|
|||||||
g_warning ("g_poll: WaitForMultipleObjects failed");
|
g_warning ("g_poll: WaitForMultipleObjects failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef G_MAIN_POLL_DEBUG
|
||||||
|
g_print ("wait returns %d%s\n",
|
||||||
|
ready,
|
||||||
|
(ready == WAIT_FAILED ? " (WAIT_FAILED)" :
|
||||||
|
(ready == WAIT_TIMEOUT ? " (WAIT_TIMEOUT)" :
|
||||||
|
(poll_msgs && ready == WAIT_OBJECT_0 + nhandles ? " (msg)" : ""))));
|
||||||
|
#endif
|
||||||
for (f = fds; f < &fds[nfds]; ++f)
|
for (f = fds; f < &fds[nfds]; ++f)
|
||||||
f->revents = 0;
|
f->revents = 0;
|
||||||
|
|
||||||
@ -380,6 +388,7 @@ g_poll (GPollFD *fds,
|
|||||||
f->revents |= G_IO_IN;
|
f->revents |= G_IO_IN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if TEST_WITHOUT_THIS
|
||||||
else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
|
else if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
|
||||||
for (f = fds; f < &fds[nfds]; ++f)
|
for (f = fds; f < &fds[nfds]; ++f)
|
||||||
{
|
{
|
||||||
@ -395,11 +404,9 @@ g_poll (GPollFD *fds,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (ready >= WAIT_OBJECT_0 && ready < WAIT_OBJECT_0 + nhandles)
|
return 1;
|
||||||
return ready - WAIT_OBJECT_0 + 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* !G_OS_WIN32 */
|
#else /* !G_OS_WIN32 */
|
||||||
|
2
gutf8.c
2
gutf8.c
@ -30,6 +30,8 @@
|
|||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
|
#include <stdio.h>
|
||||||
|
#define STRICT
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
127
tests/gio-test.c
127
tests/gio-test.c
@ -34,6 +34,8 @@
|
|||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <process.h>
|
#include <process.h>
|
||||||
|
#define STRICT
|
||||||
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -208,6 +210,52 @@ recv_message (GIOChannel *channel,
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
recv_windows_message (GIOChannel *channel,
|
||||||
|
GIOCondition cond,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
GIOError error;
|
||||||
|
MSG msg;
|
||||||
|
guint nb;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
error = g_io_channel_read (channel, &msg, sizeof (MSG), &nb);
|
||||||
|
|
||||||
|
if (error != G_IO_ERROR_NONE)
|
||||||
|
{
|
||||||
|
g_print ("gio-test: ...reading Windows message: G_IO_ERROR_%s\n",
|
||||||
|
(error == G_IO_ERROR_AGAIN ? "AGAIN" :
|
||||||
|
(error == G_IO_ERROR_INVAL ? "INVAL" :
|
||||||
|
(error == G_IO_ERROR_UNKNOWN ? "UNKNOWN" : "???"))));
|
||||||
|
if (error == G_IO_ERROR_AGAIN)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_print ("gio-test: ...Windows message for %#x: %d,%d,%d\n",
|
||||||
|
msg.hwnd, msg.message, msg.wParam, msg.lParam);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK
|
||||||
|
window_procedure (HWND hwnd,
|
||||||
|
UINT message,
|
||||||
|
WPARAM wparam,
|
||||||
|
LPARAM lparam)
|
||||||
|
{
|
||||||
|
g_print ("gio-test: window_procedure for %#x: %d,%d,%d\n",
|
||||||
|
hwnd, message, wparam, lparam);
|
||||||
|
return DefWindowProc (hwnd, message, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc,
|
main (int argc,
|
||||||
char **argv)
|
char **argv)
|
||||||
@ -224,11 +272,47 @@ main (int argc,
|
|||||||
GTimeVal start, end;
|
GTimeVal start, end;
|
||||||
GPollFD pollfd;
|
GPollFD pollfd;
|
||||||
int pollresult;
|
int pollresult;
|
||||||
|
ATOM klass;
|
||||||
|
static WNDCLASS wcl;
|
||||||
|
HWND hwnd;
|
||||||
|
GIOChannel *windows_messages_channel;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nkiddies = (argc == 1 ? 1 : atoi(argv[1]));
|
nkiddies = (argc == 1 ? 1 : atoi(argv[1]));
|
||||||
seqtab = g_malloc (nkiddies * 2 * sizeof (int));
|
seqtab = g_malloc (nkiddies * 2 * sizeof (int));
|
||||||
|
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
wcl.style = 0;
|
||||||
|
wcl.lpfnWndProc = window_procedure;
|
||||||
|
wcl.cbClsExtra = 0;
|
||||||
|
wcl.cbWndExtra = 0;
|
||||||
|
wcl.hInstance = GetModuleHandle (NULL);
|
||||||
|
wcl.hIcon = NULL;
|
||||||
|
wcl.hCursor = NULL;
|
||||||
|
wcl.hbrBackground = NULL;
|
||||||
|
wcl.lpszMenuName = NULL;
|
||||||
|
wcl.lpszClassName = "gio-test";
|
||||||
|
|
||||||
|
klass = RegisterClass (&wcl);
|
||||||
|
|
||||||
|
if (!klass)
|
||||||
|
{
|
||||||
|
g_print ("gio-test: RegisterClass failed\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
hwnd = CreateWindow (klass, "gio-test", 0, 0, 0, 10, 10,
|
||||||
|
NULL, NULL, wcl.hInstance, NULL);
|
||||||
|
if (!hwnd)
|
||||||
|
{
|
||||||
|
g_print ("gio-test: CreateWindow failed\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
windows_messages_channel = g_io_channel_win32_new_messages (hwnd);
|
||||||
|
g_io_add_watch (windows_messages_channel, G_IO_IN, recv_windows_message, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < nkiddies; i++)
|
for (i = 0; i < nkiddies; i++)
|
||||||
{
|
{
|
||||||
int pipe_to_sub[2], pipe_from_sub[2];
|
int pipe_to_sub[2], pipe_from_sub[2];
|
||||||
@ -237,7 +321,6 @@ main (int argc,
|
|||||||
pipe (pipe_from_sub) == -1)
|
pipe (pipe_from_sub) == -1)
|
||||||
perror ("pipe"), exit (1);
|
perror ("pipe"), exit (1);
|
||||||
|
|
||||||
|
|
||||||
seqtab[i].fd = pipe_from_sub[0];
|
seqtab[i].fd = pipe_from_sub[0];
|
||||||
seqtab[i].seq = 0;
|
seqtab[i].seq = 0;
|
||||||
|
|
||||||
@ -250,18 +333,18 @@ main (int argc,
|
|||||||
recv_message,
|
recv_message,
|
||||||
id);
|
id);
|
||||||
|
|
||||||
cmdline = g_strdup_printf ("%s %d %d &", argv[0],
|
|
||||||
pipe_to_sub[0], pipe_from_sub[1]);
|
|
||||||
|
|
||||||
nrunning++;
|
nrunning++;
|
||||||
|
|
||||||
#ifdef G_OS_WIN32
|
#ifdef G_OS_WIN32
|
||||||
{
|
cmdline = g_strdup_printf ("%d:%d:%d",
|
||||||
gchar *readfd = g_strdup_printf ("%d", pipe_to_sub[0]);
|
pipe_to_sub[0],
|
||||||
gchar *writefd = g_strdup_printf ("%d", pipe_from_sub[1]);
|
pipe_from_sub[1],
|
||||||
_spawnl (_P_NOWAIT, argv[0], argv[0], readfd, writefd, NULL);
|
hwnd);
|
||||||
}
|
_spawnl (_P_NOWAIT, argv[0], argv[0], "--child", cmdline, NULL);
|
||||||
#else
|
#else
|
||||||
|
cmdline = g_strdup_printf ("%s --child %d:%d &", argv[0],
|
||||||
|
pipe_to_sub[0], pipe_from_sub[1]);
|
||||||
|
|
||||||
system (cmdline);
|
system (cmdline);
|
||||||
#endif
|
#endif
|
||||||
close (pipe_to_sub[0]);
|
close (pipe_to_sub[0]);
|
||||||
@ -290,15 +373,22 @@ main (int argc,
|
|||||||
/* Child */
|
/* Child */
|
||||||
|
|
||||||
int readfd, writefd;
|
int readfd, writefd;
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
HWND hwnd;
|
||||||
|
#endif
|
||||||
int i, j;
|
int i, j;
|
||||||
char buf[BUFSIZE];
|
char buf[BUFSIZE];
|
||||||
int buflen;
|
int buflen;
|
||||||
GTimeVal tv;
|
GTimeVal tv;
|
||||||
|
int n;
|
||||||
|
|
||||||
g_get_current_time (&tv);
|
g_get_current_time (&tv);
|
||||||
|
|
||||||
readfd = atoi (argv[1]);
|
sscanf (argv[2], "%d:%d%n", &readfd, &writefd, &n);
|
||||||
writefd = atoi (argv[2]);
|
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
sscanf (argv[2] + n, ":%d", &hwnd);
|
||||||
|
#endif
|
||||||
|
|
||||||
srand (tv.tv_sec ^ (tv.tv_usec / 1000) ^ readfd ^ (writefd << 4));
|
srand (tv.tv_sec ^ (tv.tv_usec / 1000) ^ readfd ^ (writefd << 4));
|
||||||
|
|
||||||
@ -308,10 +398,23 @@ main (int argc,
|
|||||||
buflen = rand() % BUFSIZE;
|
buflen = rand() % BUFSIZE;
|
||||||
for (j = 0; j < buflen; j++)
|
for (j = 0; j < buflen; j++)
|
||||||
buf[j] = ' ' + ((buflen + j) % 95);
|
buf[j] = ' ' + ((buflen + j) % 95);
|
||||||
g_print ("gio-test: child writing %d bytes to %d\n", buflen, writefd);
|
g_print ("gio-test: child writing %d+%d bytes to %d\n",
|
||||||
|
sizeof(i) + sizeof(buflen), buflen, writefd);
|
||||||
write (writefd, &i, sizeof (i));
|
write (writefd, &i, sizeof (i));
|
||||||
write (writefd, &buflen, sizeof (buflen));
|
write (writefd, &buflen, sizeof (buflen));
|
||||||
write (writefd, buf, buflen);
|
write (writefd, buf, buflen);
|
||||||
|
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
if (rand() % 100 < 5)
|
||||||
|
{
|
||||||
|
int msg = WM_USER + (rand() % 100);
|
||||||
|
WPARAM wparam = rand ();
|
||||||
|
LPARAM lparam = rand ();
|
||||||
|
g_print ("gio-test: child posting message %d,%d,%d to %#x\n",
|
||||||
|
msg, wparam, lparam, hwnd);
|
||||||
|
PostMessage (hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
g_print ("gio-test: child exiting, closing %d\n", writefd);
|
g_print ("gio-test: child exiting, closing %d\n", writefd);
|
||||||
close (writefd);
|
close (writefd);
|
||||||
|
@ -48,7 +48,6 @@ makefile.mingw: makefile.mingw.in
|
|||||||
.SUFFIXES: .c .exe
|
.SUFFIXES: .c .exe
|
||||||
|
|
||||||
.c.exe:
|
.c.exe:
|
||||||
$(CC) $(CFLAGS) -c $<
|
|
||||||
$(CC) $(CFLAGS) -o $@ $< -L .. -lglib-$(GLIB_VER) -L ../gthread -lgthread-$(GLIB_VER)
|
$(CC) $(CFLAGS) -o $@ $< -L .. -lglib-$(GLIB_VER) -L ../gthread -lgthread-$(GLIB_VER)
|
||||||
|
|
||||||
check: all
|
check: all
|
||||||
|
Loading…
x
Reference in New Issue
Block a user