kgio.git  about / heads / tags
kinder, gentler I/O for Ruby
blob fa2fb4a31e5fae5c3a059f752c3fd54b59f52c0d 3675 bytes (raw)
$ git show HEAD:ext/kgio/wait.c	# shows this blob on the CLI

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
 
#include "kgio.h"
#include "my_fileno.h"
static ID id_wait_rd, id_wait_wr;

#if defined(HAVE_RB_TIME_INTERVAL) && defined(HAVE_RB_WAIT_FOR_SINGLE_FD)
static int kgio_timedwait(VALUE self, VALUE timeout, int write_p)
{
	struct timeval tv = rb_time_interval(timeout);
	int events = write_p ? RB_WAITFD_OUT : RB_WAITFD_IN;

	return rb_wait_for_single_fd(my_fileno(self), events, &tv);
}
#else  /* ! (HAVE_RB_TIME_INTERVAL && HAVE_RB_WAIT_FOR_SINGLE_FD) */
static int kgio_timedwait(VALUE self, VALUE timeout, int write_p)
{
	VALUE argv[4];
	VALUE set = rb_ary_new3(1, self);

	argv[0] = write_p ? Qnil : set;
	argv[1] = write_p ? set : Qnil;
	argv[2] = Qnil;
	argv[3] = timeout;

	set = rb_funcall2(rb_cIO, rb_intern("select"), 4, argv);
	return NIL_P(set) ? 0 : 1;
}
#endif /* ! (HAVE_RB_TIME_INTERVAL && HAVE_RB_WAIT_FOR_SINGLE_FD) */

static int kgio_wait(int argc, VALUE *argv, VALUE self, int write_p)
{
	int fd;
	VALUE timeout;

	if (rb_scan_args(argc, argv, "01", &timeout) == 1 && !NIL_P(timeout))
		return kgio_timedwait(self, timeout, write_p);

	fd = my_fileno(self);
	errno = EAGAIN;
	write_p ? rb_io_wait_writable(fd) : rb_io_wait_readable(fd);
	return 1;
}

/*
 * call-seq:
 *
 *	io.kgio_wait_readable           -> IO
 *	io.kgio_wait_readable(timeout)  -> IO or nil
 *
 * Blocks the running Thread indefinitely until the IO object is readable
 * or if +timeout+ expires.  If +timeout+ is specified and expires, +nil+
 * is returned.
 *
 * This method is automatically called (without timeout argument) by default
 * whenever kgio_read needs to block on input.
 *
 * Users of alternative threading/fiber libraries are
 * encouraged to override this method in their subclasses or modules to
 * work with their threading/blocking methods.
 */
static VALUE kgio_wait_readable(int argc, VALUE *argv, VALUE self)
{
	int r = kgio_wait(argc, argv, self, 0);

	if (r < 0) rb_sys_fail("kgio_wait_readable");
	return r == 0 ? Qnil : self;
}

/*
 * call-seq:
 *
 *	io.kgio_wait_writable           -> IO
 *	io.kgio_wait_writable(timeout)  -> IO or nil
 *
 * Blocks the running Thread indefinitely until the IO object is writable
 * or if +timeout+ expires.  If +timeout+ is specified and expires, +nil+
 * is returned.
 *
 * This method is automatically called (without timeout argument) by default
 * whenever kgio_write needs to block on output.
 *
 * Users of alternative threading/fiber libraries are
 * encouraged to override this method in their subclasses or modules to
 * work with their threading/blocking methods.
 */
static VALUE kgio_wait_writable(int argc, VALUE *argv, VALUE self)
{
	int r = kgio_wait(argc, argv, self, 1);

	if (r < 0) rb_sys_fail("kgio_wait_writable");
	return r == 0 ? Qnil : self;
}

VALUE kgio_call_wait_writable(VALUE io)
{
	return rb_funcall(io, id_wait_wr, 0);
}

VALUE kgio_call_wait_readable(VALUE io)
{
	return rb_funcall(io, id_wait_rd, 0);
}

void init_kgio_wait(void)
{
	VALUE mKgio = rb_define_module("Kgio");

	/*
	 * Document-module: Kgio::DefaultWaiters
	 *
	 * This module contains default kgio_wait_readable and
	 * kgio_wait_writable methods that block indefinitely (in a
	 * thread-safe manner) until an IO object is read or writable.
	 * This module is included in the Kgio::PipeMethods and
	 * Kgio::SocketMethods modules used by all bundled IO-derived
	 * objects.
	 */
	VALUE mWaiters = rb_define_module_under(mKgio, "DefaultWaiters");

	id_wait_rd = rb_intern("kgio_wait_readable");
	id_wait_wr = rb_intern("kgio_wait_writable");

	rb_define_method(mWaiters, "kgio_wait_readable",
	                 kgio_wait_readable, -1);
	rb_define_method(mWaiters, "kgio_wait_writable",
	                 kgio_wait_writable, -1);
}

git clone git://yhbt.net/kgio.git
git clone https://yhbt.net/kgio.git