[macruby-changes] [3198] MacRuby/trunk/gcd.c
source_changes at macosforge.org
source_changes at macosforge.org
Wed Jan 6 16:31:58 PST 2010
Revision: 3198
http://trac.macosforge.org/projects/ruby/changeset/3198
Author: ernest.prabhakar at gmail.com
Date: 2010-01-06 16:31:58 -0800 (Wed, 06 Jan 2010)
Log Message:
-----------
Completed Dispatch::Source API and Documentation, though neither work/are tested :-/
Modified Paths:
--------------
MacRuby/trunk/gcd.c
Modified: MacRuby/trunk/gcd.c
===================================================================
--- MacRuby/trunk/gcd.c 2010-01-06 23:35:23 UTC (rev 3197)
+++ MacRuby/trunk/gcd.c 2010-01-07 00:31:58 UTC (rev 3198)
@@ -768,17 +768,27 @@
/*
* call-seq:
- * Dispatch::Source.new(type, handle, mask, queue) => Dispatch::Source
+ * Dispatch::Source.new(type, handle, mask, queue) {|src| block}
+ * => Dispatch::Source
*
* Returns a Source used to monitor a variety of system objects and events
* including file descriptors, processes, virtual filesystem nodes, signal
* delivery and timers.
* When a state change occurs, the dispatch source will submit its event
- * handler block to its target queue.
+ * handler block to its target queue, with the source as a parameter.
*
* gcdq = Dispatch::Queue.new('doc')
- * src = Dispatch::Source.new(Dispatch::Source::DATA_ADD, 1, 2, gcdq)
+ * src = Dispatch::Source.new(Dispatch::Source::DATA_ADD, 0, 0, gcdq) do |s|
+ * puts "Fired!"
+ * end
*
+ * Unlike with the C API, Dispatch::Source objects start off resumed
+ * (since the event handler has already been set).
+ *
+ * src.suspended? #=? false
+ * src.merge(0)
+ * gcdq.sync { } #=> Fired!
+ *
*/
static VALUE
@@ -824,14 +834,132 @@
return Qnil;
}
+/*
+ * call-seq:
+ * src.handle => Number
+ *
+ * Returns the underlying handle to the dispatch source (i.e. file descriptor,
+ * process identifer, etc.). For Ruby, this must be representable as a Number.
+ *
+ * gcdq = Dispatch::Queue.new('doc')
+ * src = Dispatch::Source.new(Dispatch::Source::DATA_ADD, 0, 0, gcdq) { }
+ * puts src.handle #=> 0
+ */
+
static VALUE
+rb_source_get_handle(VALUE self, SEL sel)
+{
+ return LONG2NUM(dispatch_source_get_handle(RSource(self)->source));
+}
+
+/*
+ * call-seq:
+ * src.mask => Number
+ *
+ * Returns a Number representing the mask argument, corresponding to the flags
+ * set when the source was created.
+ *
+ * gcdq = Dispatch::Queue.new('doc')
+ * src = Dispatch::Source.new(Dispatch::Source::DATA_ADD, 0, 0, gcdq) { }
+ * puts src.mask #=> 0
+ */
+
+static VALUE
+rb_source_get_mask(VALUE self, SEL sel)
+{
+ return INT2NUM(dispatch_source_get_mask(RSource(self)->source));
+}
+
+/*
+ * call-seq:
+ * src.data => Number
+ *
+ * Returns a Number containing currently pending data for the dispatch source.
+ * This function should only be called from within the source's event handler.
+ * The result of calling this function from any other context is undefined.
+ *
+ * gcdq = Dispatch::Queue.new('doc')
+ * src = Dispatch::Source.new(Dispatch::Source::DATA_ADD, 0, 0, gcdq) do |s|
+ * puts s.data
+ * end
+ * src.merge(1)
+ * gcdq.sync { } #=> 1
+ */
+
+static VALUE
+rb_source_get_data(VALUE self, SEL sel)
+{
+ return LONG2NUM(dispatch_source_get_mask(RSource(self)->source));
+}
+
+/*
+ * call-seq:
+ * src.merge(number)
+ *
+ * Intended only for use with the Dispatch::Source::DATA_ADD and
+ * Dispatch::Source::DATA_OR source types, calling this function will
+ * atomically ADD or logical OR the count into the source's data, and
+ * trigger delivery of the source's event handler.
+ *
+ * gcdq = Dispatch::Queue.new('doc')
+ * @sum = 0
+ * src = Dispatch::Source.new(Dispatch::Source::DATA_ADD, 0, 0, gcdq) do |s|
+ * @sum += s.data # safe since always serialized
+ * end
+ * src.merge(1)
+ * src.merge(3)
+ * gcdq.sync { }
+ * puts @sum #=> 4
+ */
+
+static VALUE
rb_source_merge(VALUE self, SEL sel, VALUE data)
{
dispatch_source_merge_data(RSource(self)->source, NUM2INT(data));
return Qnil;
}
+static void
+rb_source_cancel_handler(void *source)
+{
+ assert(source != NULL);
+ rb_vm_block_t *the_block = RSource(source)->cancel_handler;
+ rb_vm_block_eval(the_block, 0, NULL);
+}
+
+/*
+ * call-seq:
+ * src.on_cancel { |src| block }
+ *
+ * This specifies an optional cancellation handler to be submitted exactly once
+ * to the target queue, and only when the source has been cancelled.
+ *
+ * This is most commonly used to close File descriptors associated with
+ * Dispatch::Source::WRITE, Dispatch::Source::READ and Dispatch::Source::VNODE
+ *
+ * gcdq = Dispatch::Queue.new('doc')
+ * file = File.open("/etc/passwd")
+ * src = Dispatch::Source.new(Dispatch::Source::READ, file, 0, gcdq) { }
+ * src.on_cancel { file.close }
+ * src.cancel!
+ *
+ */
+
static VALUE
+rb_source_on_cancellation(VALUE self, SEL sel)
+{
+ rb_source_t *src = RSource(self);
+ rb_vm_block_t *the_block = rb_vm_current_block();
+ if (the_block == NULL) {
+ rb_raise(rb_eArgError, "on_cancellation() requires a block argument");
+ }
+ GC_WB(&src->cancel_handler, the_block);
+ dispatch_set_context(src->source, (void*)self); // retain this?
+ dispatch_source_set_cancel_handler_f(src->source, rb_source_cancel_handler);
+ return Qnil;
+}
+
+static VALUE
rb_source_cancel(VALUE self, SEL sel)
{
dispatch_source_cancel(RSource(self)->source);
@@ -917,7 +1045,6 @@
return (VALUE)s;
}
-
/*
* call-seq:
* Dispatch::Semaphore.new(count) => Dispatch::Semaphore
@@ -1113,11 +1240,15 @@
rb_define_const(cSource, "WRITE", INT2NUM(SOURCE_TYPE_WRITE));
rb_objc_define_method(*(VALUE *)cSource, "alloc", rb_source_alloc, 0);
rb_objc_define_method(cSource, "initialize", rb_source_init, 4);
+ rb_objc_define_method(cSource, "on_cancel", rb_source_on_cancellation, 0);
rb_objc_define_method(cSource, "cancelled?", rb_source_cancelled_p, 0);
rb_objc_define_method(cSource, "cancel!", rb_source_cancel, 0);
rb_objc_define_method(cSource, "resume!", rb_dispatch_resume, 0);
rb_objc_define_method(cSource, "suspend!", rb_dispatch_suspend, 0);
rb_objc_define_method(cSource, "suspended?", rb_dispatch_suspended_p, 0);
+ rb_objc_define_method(cSource, "handle", rb_source_get_handle, 0);
+ rb_objc_define_method(cSource, "mask", rb_source_get_mask, 0);
+ rb_objc_define_method(cSource, "data", rb_source_get_data, 0);
rb_objc_define_method(cSource, "merge", rb_source_merge, 1);
cTimer = rb_define_class_under(mDispatch, "Timer", cSource);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100106/cc63e548/attachment-0001.html>
More information about the macruby-changes
mailing list