* [sleepy.penguin] [PATCH 1/4] doc: flesh out kqueue-related documentation
@ 2013-05-03 1:20 Eric Wong
2013-05-03 1:20 ` [sleepy.penguin] [PATCH 2/4] kqueue: remove timeout handling for nevents==0 Eric Wong
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Eric Wong @ 2013-05-03 1:20 UTC (permalink / raw)
To: sleepy.penguin
Hopefully this will lead to less confusion among new
users.
---
.document | 1 +
ext/sleepy_penguin/kqueue.c | 55 +++++++++++++++++++++++++++++++++-----------
lib/sleepy_penguin/kevent.rb | 4 ++++
lib/sleepy_penguin/kqueue.rb | 11 +++++++--
4 files changed, 56 insertions(+), 15 deletions(-)
diff --git a/.document b/.document
index 03969e3..001f785 100644
--- a/.document
+++ b/.document
@@ -10,3 +10,4 @@ ext/sleepy_penguin/init.c
ext/sleepy_penguin/inotify.c
ext/sleepy_penguin/signalfd.c
ext/sleepy_penguin/timerfd.c
+ext/sleepy_penguin/kqueue.c
diff --git a/ext/sleepy_penguin/kqueue.c b/ext/sleepy_penguin/kqueue.c
index 4d5785f..e7d1deb 100644
--- a/ext/sleepy_penguin/kqueue.c
+++ b/ext/sleepy_penguin/kqueue.c
@@ -117,7 +117,8 @@ out:
* kqueue descriptors are automatically invalidated across fork, so care
* must be taken when forking.
* Setting IO#autoclose=false is recommended for applications which fork
- * after kqueue creation.
+ * after kqueue creation. Ruby 1.8 does not have IO#autoclose=, so using
+ * this class is not recommended under Ruby 1.8
*/
static VALUE s_new(VALUE klass)
{
@@ -321,6 +322,26 @@ static void changelist_prepare(struct kevent *events, VALUE changelist)
/*
* call-seq:
* kq_io.kevent([changelist[, nevents[, timeout]]]) { |ident,filter,flags,fflags,data,udata| ... }
+ *
+ * This is a wrapper around the kevent(2) system call to change and/or
+ * retrieve events from the underlying kqueue descriptor.
+ *
+ * +changelist+ may be nil, a single Kevent struct or an array of Kevent
+ * structs. If +changelist+ is nil, no changes will be made to the
+ * underlying kqueue object.
+ *
+ * +nevents+ may be non-negative integer or nil. If +nevents+ is zero or
+ * nil, no events are retrieved. If +nevents+ is positive, a block must
+ * be passed to kevent for each event.
+ *
+ * +timeout+ is the numeric timeout in seconds to wait for +nevents+.
+ * If nil and +nevents+ is positive, kevent will sleep forever.
+ * +timeout+ may be in a floating point number if subsecond resolution
+ * is required. If +nevents+ is nil or zero and +timeout+ is not specified,
+ * +timeout+ is implied to be zero.
+ *
+ * If event retrieval is desired, a block taking 6-elements (one for each
+ * field of the kevent struct) must be passed.
*/
static VALUE sp_kevent(int argc, VALUE *argv, VALUE self)
{
@@ -365,6 +386,12 @@ static VALUE sp_kevent(int argc, VALUE *argv, VALUE self)
/* initialize constants in the SleepyPenguin::Ev namespace */
static void init_ev(VALUE mSleepyPenguin)
{
+ /*
+ * Document-module: SleepyPenguin::Ev
+ *
+ * Constants in the SleepyPenguin::Ev namespace are for the +flags+
+ * field in Kevent structs.
+ */
mEv = rb_define_module_under(mSleepyPenguin, "Ev");
/* See EV_ADD in the kevent(2) man page */
@@ -402,6 +429,8 @@ static void init_ev(VALUE mSleepyPenguin)
static void init_evfilt(VALUE mSleepyPenguin)
{
/*
+ * Document-module: SleepyPenguin::EvFilt
+ *
* Pre-defined system filters for Kqueue events. Not all filters
* are supported on all platforms. Consult the kevent(2) man page
* and source code for your operating system for more information.
@@ -464,7 +493,9 @@ static void init_evfilt(VALUE mSleepyPenguin)
static void init_note(VALUE mSleepyPenguin)
{
/*
- * data/hint flags/mask for EVFILT_USER and friends
+ * Document-module: SleepyPenguin::Note
+ *
+ * Data/hint flags/masks for EVFILT_USER and friends in Kqueue
* On input, the top two bits of fflags specifies how the lower
* twenty four bits should be applied to the stored value of fflags.
*
@@ -569,7 +600,11 @@ static void init_note(VALUE mSleepyPenguin)
static void init_vq(VALUE mSleepyPenguin)
{
#ifdef VQ_NOTRESP
- /* constants used by the EvFilt::FS filter */
+ /*
+ * Document-module: SleepyPenguin::VQ
+ *
+ * Constants used by the EvFilt::FS filter in the Kqueue interfaces
+ */
mVQ = rb_define_module_under(mSleepyPenguin, "VQ");
/* server down */
@@ -608,15 +643,6 @@ void sleepy_penguin_init_kqueue(void)
init_note(mSleepyPenguin);
init_vq(mSleepyPenguin);
- /*
- * Document-class: SleepyPenguin::Kqueue
- *
- * The Kqueue class provides high-level access to kqueue(2)
- * functionality in FreeBSD and similar systems.
- * It provides fork and GC-safety for Ruby objects stored
- * within the IO object and may be passed as an argument to
- * IO.select.
- */
cKqueue = rb_define_class_under(mSleepyPenguin, "Kqueue", rb_cObject);
/*
@@ -626,7 +652,10 @@ void sleepy_penguin_init_kqueue(void)
* GC-safety, so Ruby IO objects added via kevent must be retained
* by the application until IO#close is called.
*
- * Warning: this class is easy to misuse, do not rely on
+ * Warning: this class is easy to misuse, be careful as failure
+ * to preserve references objects passed as Kevent#udata may lead
+ * to crashes in Ruby. The high-level Kqueue class prevents these
+ * crashes (but may still return invalid objects).
*/
cKqueue_IO = rb_define_class_under(cKqueue, "IO", rb_cIO);
rb_define_singleton_method(cKqueue_IO, "new", s_new, 0);
diff --git a/lib/sleepy_penguin/kevent.rb b/lib/sleepy_penguin/kevent.rb
index 5b3dca9..1102737 100644
--- a/lib/sleepy_penguin/kevent.rb
+++ b/lib/sleepy_penguin/kevent.rb
@@ -1,3 +1,7 @@
+# This class represents a "struct kevent" structure for Ruby.
+# This may be passed to Kqueue::IO#kevent as either a single element
+# or as an element inside an array to inject changes into the kevent
+# list.
class SleepyPenguin::Kevent < Struct.new(:ident, :filter, :flags,
:fflags, :data, :udata)
end
diff --git a/lib/sleepy_penguin/kqueue.rb b/lib/sleepy_penguin/kqueue.rb
index 1eeb641..dd09c51 100644
--- a/lib/sleepy_penguin/kqueue.rb
+++ b/lib/sleepy_penguin/kqueue.rb
@@ -8,6 +8,10 @@
# Events registered to a Kqueue object cannot be shared across fork
# due to the underlying implementation of kqueue in *BSDs.
class SleepyPenguin::Kqueue
+
+ # Initialize a new Kqueue object, this allocates an underlying Kqueue::IO
+ # object and may fail if the system is out of file descriptors or
+ # kernel memory
def initialize
@io = SleepyPenguin::Kqueue::IO.new
@mtx = Mutex.new
@@ -46,8 +50,11 @@ def __kq_check # :nodoc:
@pid = $$
end
- # Users are responsible for ensuring udata objects remain visible to the
- # Ruby GC.
+ # A high-level wrapper around Kqueue::IO#kevent
+ # Users are responsible for ensuring +udata+ objects remain visible to the
+ # Ruby GC, otherwise ObjectSpace._id2ref may return invalid objects.
+ # Unlike the low-level Kqueue::IO#kevent, the block given yields only
+ # a single Kevent struct, not a 6-element array.
def kevent(changelist = nil, *args)
@mtx.synchronize { __kq_check }
if changelist
--
1.8.2.1.367.gc875ca7
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [sleepy.penguin] [PATCH 2/4] kqueue: remove timeout handling for nevents==0
2013-05-03 1:20 [sleepy.penguin] [PATCH 1/4] doc: flesh out kqueue-related documentation Eric Wong
@ 2013-05-03 1:20 ` Eric Wong
2013-05-03 1:20 ` [sleepy.penguin] [PATCH 3/4] test_kqueue_io: additional test for IO-likeness Eric Wong
2013-05-03 1:20 ` [sleepy.penguin] [PATCH 4/4] README: update with latest features Eric Wong
2 siblings, 0 replies; 4+ messages in thread
From: Eric Wong @ 2013-05-03 1:20 UTC (permalink / raw)
To: sleepy.penguin
The underlying kevent() itself already bypasses the timeout
if nevents==0 (so it is impossible to emulate a sleep function
with kevent()).
---
ext/sleepy_penguin/kqueue.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/ext/sleepy_penguin/kqueue.c b/ext/sleepy_penguin/kqueue.c
index e7d1deb..59c3dae 100644
--- a/ext/sleepy_penguin/kqueue.c
+++ b/ext/sleepy_penguin/kqueue.c
@@ -365,14 +365,13 @@ static VALUE sp_kevent(int argc, VALUE *argv, VALUE self)
rb_raise(rb_eArgError,
"block given but nevents not specified");
nevents = NUM2INT(events);
- if (nevents <= 0)
- rb_raise(rb_eArgError, "nevents must be positive");
+ if (nevents < 0)
+ rb_raise(rb_eArgError, "nevents must be non-negative");
} else {
if (!NIL_P(events))
rb_raise(rb_eArgError,
"nevents specified but block not given");
nevents = 0;
- timeout = INT2FIX(0);
}
kpt = kpt_get(self, nchanges, nevents);
--
1.8.2.1.367.gc875ca7
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [sleepy.penguin] [PATCH 3/4] test_kqueue_io: additional test for IO-likeness
2013-05-03 1:20 [sleepy.penguin] [PATCH 1/4] doc: flesh out kqueue-related documentation Eric Wong
2013-05-03 1:20 ` [sleepy.penguin] [PATCH 2/4] kqueue: remove timeout handling for nevents==0 Eric Wong
@ 2013-05-03 1:20 ` Eric Wong
2013-05-03 1:20 ` [sleepy.penguin] [PATCH 4/4] README: update with latest features Eric Wong
2 siblings, 0 replies; 4+ messages in thread
From: Eric Wong @ 2013-05-03 1:20 UTC (permalink / raw)
To: sleepy.penguin
We need to ensure Kqueue::IO remains IO-like
---
test/test_kqueue_io.rb | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/test/test_kqueue_io.rb b/test/test_kqueue_io.rb
index 076c9f0..04e3103 100644
--- a/test/test_kqueue_io.rb
+++ b/test/test_kqueue_io.rb
@@ -16,6 +16,13 @@ def teardown
end
end
+ def test_io_like
+ kq = Kqueue::IO.new
+ @to_close << kq
+ assert_equal kq, kq.to_io
+ assert_kind_of Integer, kq.fileno
+ end
+
def test_bad_type
kq = Kqueue::IO.new
@to_close << kq
--
1.8.2.1.367.gc875ca7
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [sleepy.penguin] [PATCH 4/4] README: update with latest features
2013-05-03 1:20 [sleepy.penguin] [PATCH 1/4] doc: flesh out kqueue-related documentation Eric Wong
2013-05-03 1:20 ` [sleepy.penguin] [PATCH 2/4] kqueue: remove timeout handling for nevents==0 Eric Wong
2013-05-03 1:20 ` [sleepy.penguin] [PATCH 3/4] test_kqueue_io: additional test for IO-likeness Eric Wong
@ 2013-05-03 1:20 ` Eric Wong
2 siblings, 0 replies; 4+ messages in thread
From: Eric Wong @ 2013-05-03 1:20 UTC (permalink / raw)
To: sleepy.penguin
We support kqueue and Rubinius. Nowadays, we also export
the potentially dangerous low-level APIs for epoll and kqueue.
---
README | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/README b/README
index 551ce8e..9574dce 100644
--- a/README
+++ b/README
@@ -2,19 +2,21 @@
sleepy_penguin provides access to newer, Linux-only system calls to wait
on events from traditionally non-I/O sources. Bindings to the eventfd,
-timerfd, inotify, and epoll interfaces are provided.
+timerfd, inotify, and epoll interfaces are provided. Experimental support
+for kqueue on FreeBSD (and likely OpenBSD/NetBSD) are also provided.
== Features
-* Thread-safe blocking operations for all versions of Ruby
+* Thread-safe blocking operations for all versions of Matz Ruby and Rubinius
* IO-like objects are backwards-compatible with IO.select.
-* Epoll interface is fork-safe and GC-safe
+* High-level Epoll interface is fork-safe and GC-safe
* Unlike portable event frameworks, the Linux-only epoll interfaces
allow using edge-triggered or one-shot notifications for possibly
- improved performance
+ improved performance. Likewise, the kqueue interface supports
+ one-shot notifiactions, too.
* Fully-documented and user-friendly API
--
1.8.2.1.367.gc875ca7
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2013-05-03 1:20 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-03 1:20 [sleepy.penguin] [PATCH 1/4] doc: flesh out kqueue-related documentation Eric Wong
2013-05-03 1:20 ` [sleepy.penguin] [PATCH 2/4] kqueue: remove timeout handling for nevents==0 Eric Wong
2013-05-03 1:20 ` [sleepy.penguin] [PATCH 3/4] test_kqueue_io: additional test for IO-likeness Eric Wong
2013-05-03 1:20 ` [sleepy.penguin] [PATCH 4/4] README: update with latest features Eric Wong
Code repositories for project(s) associated with this public inbox
https://yhbt.net/sleepy_penguin.git/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).