+/* The callback functions for call_subprocess_async */
+static int
+s_Molecule_CallSubProcessAsync_EndCallback(Molecule *mol, int status)
+{
+ int ruby_status;
+ VALUE procval, retval, args[2];
+ args[0] = ValueFromMolecule(mol);
+ args[1] = INT2NUM(status);
+ procval = rb_ivar_get(args[0], rb_intern("end_proc"));
+ if (procval != Qnil) {
+ retval = Ruby_funcall2_protect(procval, rb_intern("call"), 2, args, &ruby_status);
+ if (ruby_status != 0 || retval == Qnil || retval == Qfalse)
+ return 1;
+ }
+ return 0;
+}
+
+static int
+s_Molecule_CallSubProcessAsync_TimerCallback(Molecule *mol, int tcount)
+{
+ int ruby_status;
+ VALUE procval, retval, args[2];
+ args[0] = ValueFromMolecule(mol);
+ args[1] = INT2NUM(tcount);
+ procval = rb_ivar_get(args[0], rb_intern("timer_proc"));
+ if (procval != Qnil) {
+ retval = Ruby_funcall2_protect(procval, rb_intern("call"), 2, args, &ruby_status);
+ if (ruby_status != 0 || retval == Qnil || retval == Qfalse)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * call-seq:
+ * call_subprocess_async(cmd [, end_callback [, timer_callback]])
+ *
+ * Call subprocess asynchronically.
+ * If end_callback is given, it will be called (with two arguments self and termination status)
+ * when the subprocess terminated.
+ * If timer_callback is given, it will be called (also with two arguments, self and timer count).
+ * If timer_callback returns nil or false, then the subprocess will be interrupted.
+ * Returns the process ID as an integer.
+ */
+static VALUE
+s_Molecule_CallSubProcessAsync(int argc, VALUE *argv, VALUE self)
+{
+ VALUE cmd, end_proc, timer_proc;
+ Molecule *mol;
+ int n;
+ rb_scan_args(argc, argv, "12", &cmd, &end_proc, &timer_proc);
+ Data_Get_Struct(self, Molecule, mol);
+
+ /* Register procs as instance variables */
+ rb_ivar_set(self, rb_intern("end_proc"), end_proc);
+ rb_ivar_set(self, rb_intern("timer_proc"), timer_proc);
+ n = MoleculeCallback_callSubProcessAsync(mol, StringValuePtr(cmd), s_Molecule_CallSubProcessAsync_EndCallback, (timer_proc == Qnil ? NULL : s_Molecule_CallSubProcessAsync_TimerCallback), (FILE *)1, (FILE *)1);
+ return INT2NUM(n);
+}
+