diff options
Diffstat (limited to 'include/ruby/io.h')
| -rw-r--r-- | include/ruby/io.h | 242 |
1 files changed, 72 insertions, 170 deletions
diff --git a/include/ruby/io.h b/include/ruby/io.h index e9dfeda5b1..3e035c114d 100644 --- a/include/ruby/io.h +++ b/include/ruby/io.h @@ -35,11 +35,7 @@ # undef revents # endif # define RB_WAITFD_IN POLLIN -# if defined(POLLPRI) -# define RB_WAITFD_PRI POLLPRI -# else -# define RB_WAITFD_PRI 0 -# endif +# define RB_WAITFD_PRI POLLPRI # define RB_WAITFD_OUT POLLOUT #else # define RB_WAITFD_IN 0x001 @@ -49,17 +45,11 @@ /** @endcond */ #include "ruby/internal/attr/const.h" -#include "ruby/internal/attr/packed_struct.h" #include "ruby/internal/attr/pure.h" #include "ruby/internal/attr/noreturn.h" #include "ruby/internal/dllexport.h" #include "ruby/internal/value.h" - -// IO#wait, IO#wait_readable, IO#wait_writable, IO#wait_priority are defined by this implementation. -#define RUBY_IO_WAIT_METHODS - -// Used as the default timeout argument to `rb_io_wait` to use the `IO#timeout` value. -#define RUBY_IO_TIMEOUT_DEFAULT Qnil +#include "ruby/backward/2/attributes.h" /* PACKED_STRUCT_UNALIGNED */ RBIMPL_SYMBOL_EXPORT_BEGIN() @@ -67,31 +57,23 @@ struct stat; struct timeval; /** - * Indicates that a timeout has occurred while performing an IO operation. - */ -RUBY_EXTERN VALUE rb_eIOTimeoutError; - -/** * Type of events that an IO can wait. * * @internal * * This is visible from extension libraries because `io/wait` wants it. */ -enum rb_io_event { +typedef enum { RUBY_IO_READABLE = RB_WAITFD_IN, /**< `IO::READABLE` */ RUBY_IO_WRITABLE = RB_WAITFD_OUT, /**< `IO::WRITABLE` */ RUBY_IO_PRIORITY = RB_WAITFD_PRI, /**< `IO::PRIORITY` */ -}; - -typedef enum rb_io_event rb_io_event_t; +} rb_io_event_t; /** * IO buffers. This is an implementation detail of ::rb_io_t::wbuf and * ::rb_io_t::rbuf. People don't manipulate it directly. */ -RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_BEGIN() -struct rb_io_internal_buffer { +PACKED_STRUCT_UNALIGNED(struct rb_io_buffer_t { /** Pointer to the underlying memory region, of at least `capa` bytes. */ char *ptr; /* off + len <= capa */ @@ -104,84 +86,45 @@ struct rb_io_internal_buffer { /** Designed capacity of the buffer. */ int capa; -} RBIMPL_ATTR_PACKED_STRUCT_UNALIGNED_END(); +}); /** @alias{rb_io_buffer_t} */ -typedef struct rb_io_internal_buffer rb_io_buffer_t; - -/** Decomposed encoding flags (e.g. `"enc:enc2""`). */ -/* - * enc enc2 read action write action - * NULL NULL force_encoding(default_external) write the byte sequence of str - * e1 NULL force_encoding(e1) convert str.encoding to e1 - * e1 e2 convert from e2 to e1 convert str.encoding to e2 - */ -struct rb_io_encoding { - /** Internal encoding. */ - rb_encoding *enc; - /** External encoding. */ - rb_encoding *enc2; - /** - * Flags. - * - * @see enum ::ruby_econv_flag_type - */ - int ecflags; - /** - * Flags as Ruby hash. - * - * @internal - * - * This is set. But used from nowhere maybe? - */ - VALUE ecopts; -}; +typedef struct rb_io_buffer_t rb_io_buffer_t; -#ifndef HAVE_RB_IO_T -#define HAVE_RB_IO_T 1 /** Ruby's IO, metadata and buffers. */ -struct rb_io { +typedef struct rb_io_t { + /** The IO's Ruby level counterpart. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE self; /** stdio ptr for read/write, if available. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) FILE *stdio_file; /** file descriptor. */ - RBIMPL_ATTR_DEPRECATED(("rb_io_descriptor")) int fd; /** mode flags: FMODE_XXXs */ - RBIMPL_ATTR_DEPRECATED(("rb_io_mode")) int mode; /** child's pid (for pipes) */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_pid_t pid; /** number of lines read */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) int lineno; /** pathname for file */ - RBIMPL_ATTR_DEPRECATED(("rb_io_path")) VALUE pathv; /** finalize proc */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) - void (*finalize)(struct rb_io*,int); + void (*finalize)(struct rb_io_t*,int); /** Write buffer. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_io_buffer_t wbuf; /** * (Byte) read buffer. Note also that there is a field called * ::rb_io_t::cbuf, which also concerns read IO. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_io_buffer_t rbuf; /** @@ -189,25 +132,49 @@ struct rb_io { * * @see rb_io_set_write_io() */ - RBIMPL_ATTR_DEPRECATED(("rb_io_get_write_io")) VALUE tied_io_for_writing; - RBIMPL_ATTR_DEPRECATED(("with no replacement")) - struct rb_io_encoding encs; /**< Decomposed encoding flags. */ + /** Decomposed encoding flags (e.g. `"enc:enc2""`). */ + /* + * enc enc2 read action write action + * NULL NULL force_encoding(default_external) write the byte sequence of str + * e1 NULL force_encoding(e1) convert str.encoding to e1 + * e1 e2 convert from e2 to e1 convert str.encoding to e2 + */ + struct rb_io_enc_t { + /** Internal encoding. */ + rb_encoding *enc; + + /** External encoding. */ + rb_encoding *enc2; + + /** + * Flags. + * + * @see enum ::ruby_econv_flag_type + */ + int ecflags; + + /** + * Flags as Ruby hash. + * + * @internal + * + * This is set. But used from nowhere maybe? + */ + VALUE ecopts; + } encs; /**< Decomposed encoding flags. */ /** Encoding converter used when reading from this IO. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_econv_t *readconv; /** * rb_io_ungetc() destination. This buffer is read before checking * ::rb_io_t::rbuf */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_io_buffer_t cbuf; /** Encoding converter used when writing to this IO. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) rb_econv_t *writeconv; /** @@ -216,25 +183,21 @@ struct rb_io { * conversion from encoding X to encoding Y does not exist, Ruby finds an * encoding Z that bridges the two, so that X to Z to Y conversion happens. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE writeconv_asciicompat; /** Whether ::rb_io_t::writeconv is already set up. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) int writeconv_initialized; /** * Value of ::rb_io_t::rb_io_enc_t::ecflags stored right before * initialising ::rb_io_t::writeconv. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) int writeconv_pre_ecflags; /** * Value of ::rb_io_t::rb_io_enc_t::ecopts stored right before initialising * ::rb_io_t::writeconv. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE writeconv_pre_ecopts; /** @@ -244,21 +207,20 @@ struct rb_io { * * This of course doesn't help inter-process IO interleaves, though. */ - RBIMPL_ATTR_DEPRECATED(("with no replacement")) VALUE write_lock; - - /** - * The timeout associated with this IO when performing blocking operations. - */ - RBIMPL_ATTR_DEPRECATED(("rb_io_timeout/rb_io_set_timeout")) - VALUE timeout; -}; -#endif - -typedef struct rb_io rb_io_t; +} rb_io_t; /** @alias{rb_io_enc_t} */ -typedef struct rb_io_encoding rb_io_enc_t; +typedef struct rb_io_enc_t rb_io_enc_t; + +/** + * @private + * + * @deprecated This macro once was a thing in the old days, but makes no sense + * any longer today. Exists here for backwards compatibility + * only. You can safely forget about it. + */ +#define HAVE_RB_IO_T 1 /** * @name Possible flags for ::rb_io_t::mode @@ -349,16 +311,7 @@ typedef struct rb_io_encoding rb_io_enc_t; * Setting this one and #FMODE_BINMODE at the same time is a contradiction. */ #define FMODE_TEXTMODE 0x00001000 -/** - * This flag means that an IO object is wrapping an "external" file descriptor, - * which is owned by something outside the Ruby interpreter (usually a C extension). - * Ruby will not close this file when the IO object is garbage collected. - * If this flag is set, then IO#autoclose? is false, and vice-versa. - * - * This flag was previously called FMODE_PREP internally. - */ -#define FMODE_EXTERNAL 0x00010000 - +/* #define FMODE_PREP 0x00010000 */ /* #define FMODE_SIGNAL_ON_EPIPE 0x00020000 */ /** @@ -373,18 +326,6 @@ typedef struct rb_io_encoding rb_io_enc_t; /** @} */ /** - * Allocate a new IO object, with the given file descriptor. - */ -VALUE rb_io_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, struct rb_io_encoding *encoding); - -/** - * Returns whether or not the underlying IO is closed. - * - * @return Whether the underlying IO is closed. - */ -VALUE rb_io_closed_p(VALUE io); - -/** * Queries the underlying IO pointer. * * @param[in] obj An IO object. @@ -454,14 +395,14 @@ rb_io_t *rb_io_make_open_file(VALUE obj); * like this: * * ```CXX - * typedef struct rb_io { + * typedef struct rb_io_t { * FILE *f; // stdio ptr for read/write * FILE *f2; // additional ptr for rw pipes * int mode; // mode flags * int pid; // child's pid (for pipes) * int lineno; // number of lines read * char *path; // pathname for file - * void (*finalize) _((struct rb_io*,int)); // finalize proc + * void (*finalize) _((struct rb_io_t*,int)); // finalize proc * } rb_io_t; *``` * @@ -707,23 +648,10 @@ VALUE rb_io_get_write_io(VALUE io); VALUE rb_io_set_write_io(VALUE io, VALUE w); /** - * Instructs the OS to put its internal file structure into "nonblocking mode". - * This is an in-Kernel concept. Reading from/writing to that file using C - * function calls would return -1 with errno set. However when it comes to a - * ruby program, we hide that error behind our `IO#read` method. Ruby level - * `IO#read` blocks regardless of this flag. If you want to avoid blocking, - * you should consider using methods like `IO#readpartial`. - * - * ```ruby - * require 'io/nonblock' - * STDIN.nonblock = true - * STDIN.gets # blocks. - * ``` - * - * As of writing there is a room of this API in Fiber schedulers. A Fiber - * scheduler could be written in a way its behaviour depends on this property. - * You need an in-depth understanding of how schedulers work to properly - * leverage this, though. + * Sets an IO to a "nonblock mode". This amends the way an IO operates so that + * instead of waiting for rooms for read/write, it returns errors. In case of + * multiplexed IO situations it can be vital for IO operations not to block. + * This is the key API to achieve that property. * * @note Note however that nonblocking-ness propagates across process * boundaries. You must really carefully watch your step when turning @@ -743,12 +671,6 @@ VALUE rb_io_set_write_io(VALUE io, VALUE w); void rb_io_set_nonblock(rb_io_t *fptr); /** - * Returns the path for the given IO. - * - */ -VALUE rb_io_path(VALUE io); - -/** * Returns an integer representing the numeric file descriptor for * <em>io</em>. * @@ -758,12 +680,6 @@ VALUE rb_io_path(VALUE io); int rb_io_descriptor(VALUE io); /** - * Get the mode of the IO. - * - */ -int rb_io_mode(VALUE io); - -/** * This function breaks down the option hash that `IO#initialize` takes into * components. This is an implementation detail of rb_io_extract_modeenc() * today. People prefer that API instead. @@ -910,37 +826,13 @@ int rb_io_wait_writable(int fd); int rb_wait_for_single_fd(int fd, int events, struct timeval *tv); /** - * Get the timeout associated with the specified io object. - * - * @param[in] io An IO object. - * @retval RUBY_Qnil There is no associated timeout. - * @retval Otherwise The timeout value. - */ -VALUE rb_io_timeout(VALUE io); - -/** - * Set the timeout associated with the specified io object. This timeout is - * used as a best effort timeout to prevent operations from blocking forever. - * - * @param[in] io An IO object. - * @param[in] timeout A timeout value. Must respond to #to_f. - * @ - */ -VALUE rb_io_set_timeout(VALUE io, VALUE timeout); - -/** * Blocks until the passed IO is ready for the passed events. The "events" * here is a Ruby level integer, which is an OR-ed value of `IO::READABLE`, * `IO::WRITable`, and `IO::PRIORITY`. * - * If timeout is `Qnil`, it will use the default timeout as given by - * `rb_io_timeout(io)`. - * * @param[in] io An IO object to wait. * @param[in] events See above. * @param[in] timeout Time, or numeric seconds since UNIX epoch. - * If Qnil, use the default timeout. If Qfalse - * or Qundef, wait forever. * @exception rb_eIOError `io` is not open. * @exception rb_eRangeError `timeout` is out of range. * @exception rb_eSystemCallError `select(2)` failed for some reason. @@ -992,8 +884,13 @@ VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout); * @exception rb_eIOError `io` is not open. * @exception rb_eRangeError `timeout` is out of range. * @exception rb_eSystemCallError `select(2)` failed for some reason. - * @retval 0 Operation timed out. - * @retval Otherwise Always returns ::RUBY_IO_READABLE. + * @exception rb_eTypeError Operation timed out. + * @return Always returns ::RUBY_IO_READABLE. + * + * @internal + * + * Because rb_io_maybe_wait() returns ::RUBY_Qfalse on timeout, this function + * fails to convert that value to `int`, and raises ::rb_eTypeError. */ int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout); @@ -1008,8 +905,13 @@ int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout); * @exception rb_eIOError `io` is not open. * @exception rb_eRangeError `timeout` is out of range. * @exception rb_eSystemCallError `select(2)` failed for some reason. - * @retval 0 Operation timed out. - * @retval Otherwise Always returns ::RUBY_IO_WRITABLE. + * @exception rb_eTypeError Operation timed out. + * @return Always returns ::RUBY_IO_WRITABLE. + * + * @internal + * + * Because rb_io_maybe_wait() returns ::RUBY_Qfalse on timeout, this function + * fails to convert that value to `int`, and raises ::rb_eTypeError. */ int rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout); |
