mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-13 12:39:22 +08:00
So far fhandler_pipe_fifo::raw_write always returns -1/EINTR if a signal arrived. Linux does not do that if there's still space left in the pipe buffer. The Linux buffer handling can't be emulated by Cygwin, but we can do something similar which makes it much more likely to still write successfully even if the buffer is almost full. Utilize pipe_data_available to return valid pipe buffer usage to raw_write, allowing a more sophisticated way to fill the buffer while maintaining comaptibility with non-Cygwin pipes. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
148 lines
3.9 KiB
C++
148 lines
3.9 KiB
C++
/* select.h
|
|
|
|
This file is part of Cygwin.
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
details. */
|
|
|
|
#ifndef _SELECT_H_
|
|
#define _SELECT_H_
|
|
|
|
struct fh_select_data_serial
|
|
{
|
|
DWORD event;
|
|
OVERLAPPED ov;
|
|
|
|
fh_select_data_serial () : event (0) { memset (&ov, 0, sizeof ov); }
|
|
};
|
|
|
|
struct select_record
|
|
{
|
|
int fd;
|
|
HANDLE h;
|
|
fhandler_base *fh;
|
|
_cygtls *tls;
|
|
int thread_errno;
|
|
bool windows_handle;
|
|
bool read_ready, write_ready, except_ready;
|
|
bool read_selected, write_selected, except_selected;
|
|
bool except_on_write;
|
|
int (*startup) (select_record *, class select_stuff *);
|
|
int (*peek) (select_record *, bool);
|
|
int (*verify) (select_record *, fd_set *, fd_set *, fd_set *);
|
|
void (*cleanup) (select_record *, class select_stuff *);
|
|
struct select_record *next;
|
|
/* If an fhandler type needs per-fhandler, per-select data, this union
|
|
is the place to add it. First candidate: fhandler_serial. */
|
|
union
|
|
{
|
|
fh_select_data_serial *fh_data_serial;
|
|
void *fh_data_union; /* type-agnostic placeholder for constructor */
|
|
};
|
|
void set_select_errno () {__seterrno (); thread_errno = errno;}
|
|
int saw_error () {return thread_errno;}
|
|
select_record (int): next (NULL) {}
|
|
select_record () :
|
|
fd (0), h (NULL), fh (NULL), tls (&_my_tls), thread_errno (0),
|
|
windows_handle (false), read_ready (false), write_ready (false),
|
|
except_ready (false), read_selected (false), write_selected (false),
|
|
except_selected (false), except_on_write (false),
|
|
startup (NULL), peek (NULL), verify (NULL), cleanup (NULL),
|
|
next (NULL), fh_data_union (NULL) {}
|
|
#ifdef DEBUGGING
|
|
void dump_select_record ();
|
|
#endif
|
|
};
|
|
|
|
struct select_info
|
|
{
|
|
cygthread *thread;
|
|
bool stop_thread;
|
|
HANDLE bye;
|
|
select_record *start;
|
|
select_info (): thread (NULL), stop_thread (0), start (NULL) {}
|
|
};
|
|
|
|
struct select_console_info: public select_info
|
|
{
|
|
select_console_info (): select_info () {}
|
|
};
|
|
|
|
struct select_pipe_info: public select_info
|
|
{
|
|
select_pipe_info (): select_info () {}
|
|
};
|
|
|
|
struct select_fifo_info: public select_info
|
|
{
|
|
select_fifo_info (): select_info () {}
|
|
};
|
|
|
|
struct select_socket_info: public select_info
|
|
{
|
|
int num_w4;
|
|
LONG *ser_num;
|
|
HANDLE *w4;
|
|
select_socket_info (): select_info (), num_w4 (0), ser_num (0), w4 (NULL) {}
|
|
};
|
|
|
|
struct select_dsp_info: public select_info
|
|
{
|
|
select_dsp_info (): select_info () {}
|
|
};
|
|
|
|
class select_stuff
|
|
{
|
|
public:
|
|
enum wait_states
|
|
{
|
|
select_signalled = -3,
|
|
select_error = -1,
|
|
select_ok = 0,
|
|
select_set_zero = 1
|
|
};
|
|
|
|
~select_stuff ();
|
|
bool return_on_signal;
|
|
bool always_ready, windows_used;
|
|
select_record start;
|
|
|
|
/* If an fhandler type needs a singleton per-select datastructure for all
|
|
its objects in the descriptor lists, here's the place to be. This is
|
|
mainly used to maintain a single thread for all fhandlers of a single
|
|
type in the descriptor lists. */
|
|
select_console_info *device_specific_console;
|
|
select_pipe_info *device_specific_pipe;
|
|
select_pipe_info *device_specific_ptys;
|
|
select_fifo_info *device_specific_fifo;
|
|
select_socket_info *device_specific_socket;
|
|
select_dsp_info *device_specific_dsp;
|
|
|
|
bool test_and_set (int, fd_set *, fd_set *, fd_set *);
|
|
int poll (fd_set *, fd_set *, fd_set *);
|
|
wait_states wait (fd_set *, fd_set *, fd_set *, LONGLONG);
|
|
void cleanup ();
|
|
void destroy ();
|
|
|
|
select_stuff (): return_on_signal (false), always_ready (false),
|
|
windows_used (false), start (),
|
|
device_specific_console (NULL),
|
|
device_specific_pipe (NULL),
|
|
device_specific_ptys (NULL),
|
|
device_specific_fifo (NULL),
|
|
device_specific_socket (NULL),
|
|
device_specific_dsp (NULL)
|
|
{}
|
|
};
|
|
|
|
extern "C" int cygwin_select (int , fd_set *, fd_set *, fd_set *,
|
|
struct timeval *to);
|
|
|
|
ssize_t pipe_data_available (int, fhandler_base *, HANDLE, int);
|
|
|
|
#define PDA_WRITE 0x01
|
|
#define PDA_SELECT 0x02
|
|
|
|
#endif /* _SELECT_H_ */
|