cvs -q diff -u
Index: libnci.def
===================================================================
RCS file: /cvs/public/parrot/libnci.def,v
retrieving revision 1.7
diff -u -u -r1.7 libnci.def
--- libnci.def	8 Oct 2004 11:57:38 -0000	1.7
+++ libnci.def	12 Oct 2004 22:16:18 -0000
@@ -19,8 +19,14 @@
     nci_vP
     nci_cb_C1
     nci_cb_C2
+    nci_cb_C3
     nci_cb_D1
+    nci_cb_D2
+    nci_cb_D3
+    nci_cb_D4
     nci_pip
     nci_i33
     nci_vpii
     nci_piiii
+    nci_dlvar_int
+    nci_dlvar_vv
Index: src/inter_cb.c
===================================================================
RCS file: /cvs/public/parrot/src/inter_cb.c,v
retrieving revision 1.2
diff -u -u -r1.2 inter_cb.c
--- src/inter_cb.c	16 Sep 2004 20:59:06 -0000	1.2
+++ src/inter_cb.c	12 Oct 2004 22:16:35 -0000
@@ -8,9 +8,13 @@
 
 =head1 DESCRIPTION
 
-NCI callback functions may run, whenever the C code executes the calback.
+NCI callback functions may run, whenever the C code executes the callback.
 To be prepared for async callbacks these are converted to callback events.
 
+Often callbacks should run synchronously. This can only happen when 
+the C-library calls the callback, because Parrot called a function in
+the C-library.
+
 =head2 Functions
 
 =over 4
@@ -105,31 +109,31 @@
 
 /*
 
-=item C<static void verify_CD(void *external_data, PMC *callback_info)>
+=item C<static void verify_CD(void *external_data, PMC *user_data)>
 
-Verify callback_info PMC then continue with callback_CD
+Verify user_data PMC then continue with callback_CD
 
 =cut
 
 */
 
-static void callback_CD(Parrot_Interp, void *, PMC *callback_info);
+static void callback_CD(Parrot_Interp, void *, PMC *user_data);
 
 static void
-verify_CD(void *external_data, PMC *callback_info)
+verify_CD(void *external_data, PMC *user_data)
 {
     Parrot_Interp interpreter = NULL;
     size_t i;
 
     /*
-     * 1.) callback_info is from external code so:
+     * 1.) user_data is from external code so:
      *     verify that we get a PMC that is one that we have passed in
      *     as user data, when we prepared the callback
      */
 
     /* a NULL pointer or a pointer not aligned is very likely wrong */
-    if (!callback_info || ((UINTVAL)callback_info & 3))
-        PANIC("callback_info doesn't look like a pointer");
+    if (!user_data || ((UINTVAL)user_data & 3))
+        PANIC("user_data doesn't look like a pointer");
 
     /*
      * we don't have an interpreter yet, where this PMC might be
@@ -142,7 +146,7 @@
         interpreter = interpreter_array[i];
         if (interpreter)
             if (contained_in_pool(interpreter,
-                        interpreter->arena_base->pmc_pool, callback_info))
+                        interpreter->arena_base->pmc_pool, user_data))
                 break;
     }
     UNLOCK(interpreter_array_mutex);
@@ -156,21 +160,21 @@
      */
 
     /* if that doesn't look like a PMC we are still lost */
-    if (!PObj_is_PMC_TEST(callback_info))
-        PANIC("callback_info isn't a PMC");
+    if (!PObj_is_PMC_TEST(user_data))
+        PANIC("user_data isn't a PMC");
 
-    if (!callback_info->vtable)
-        PANIC("callback_info hasn't a vtable");
+    if (!user_data->vtable)
+        PANIC("user_data hasn't a vtable");
     /*
      * ok fine till here
      */
-    callback_CD(interpreter, external_data, callback_info);
+    callback_CD(interpreter, external_data, user_data);
 }
 
 /*
 
 =item C<static void
-callback_CD(Parrot_Interp, void *external_data, PMC *callback_info)>
+callback_CD(Parrot_Interp, void *external_data, PMC *user_data)>
 
 Common callback function handler s. pdd16
 
@@ -179,19 +183,26 @@
 */
 
 static void
-callback_CD(Parrot_Interp interpreter, void *external_data, PMC *callback_info)
+callback_CD(Parrot_Interp interpreter, void *external_data, PMC *user_data)
 {
 
-    PMC *passed_interp;         /* the interp that originated the CB */
-    int async = 1;              /* cb is hitting this sub somewhen inmidst */
+    PMC *passed_interp;       /* the interp that originated the CB */
+    PMC *passed_synchronous;  /* flagging synchronous execution */ 
+    int synchronous = 0;      /* cb is hitting this sub somewhen inmidst, or not */
     STRING *sc;
     /*
      * 3) check interpreter ...
      */
     sc = CONST_STRING(interpreter, "_interpreter");
-    passed_interp = VTABLE_getprop(interpreter, callback_info, sc);
+    passed_interp = VTABLE_getprop(interpreter, user_data, sc);
     if (PMC_data(passed_interp) != interpreter)
         PANIC("callback gone to wrong interpreter");
+
+    sc = CONST_STRING(interpreter, "_synchronous");
+    passed_synchronous = VTABLE_getprop(interpreter, user_data, sc);
+    if (passed_synchronous && VTABLE_get_bool(interpreter, passed_synchronous))
+        synchronous = 1;
+
     /*
      * 4) check if the call_back is synchronous:
      *    - if yes we are inside the NCI call
@@ -199,7 +210,13 @@
      *    - if no, and that's always safe, post a CALLBACK_EVENT
      */
 
-    if (async) {
+    if ( synchronous ) {
+        /*
+         * just call the sub
+         */
+        Parrot_run_callback(interpreter, user_data, external_data);
+    }
+    else {
         /*
          * create a CB_EVENT, put user_data and data inside and finito
          *
@@ -208,12 +225,7 @@
          * then wait for the CB_EVENT_xx to finish and return the
          * result
          */
-        Parrot_new_cb_event(interpreter, callback_info, external_data);
-    }
-    else {
-        /*
-         * just call the sub
-         */
+        Parrot_new_cb_event(interpreter, user_data, external_data);
     }
 }
 
@@ -221,7 +233,7 @@
 
 =item C<void
 
-Parrot_run_callback(Parrot_Interp interpreter, PMC* user_data, void* ext)>
+Parrot_run_callback(Parrot_Interp interpreter, PMC* user_data, void* external_data)>
 
 Run a callback function. The PMC* user_data holds all
 necessary items in its properties.
@@ -231,7 +243,7 @@
 */
 
 void
-Parrot_run_callback(Parrot_Interp interpreter, PMC* user_data, void* ext)
+Parrot_run_callback(Parrot_Interp interpreter, PMC* user_data, void* external_data)
 {
     PMC *    signature;
     PMC *    sub;
@@ -265,16 +277,16 @@
         case '4':
 #endif
         case 'l':
-            i_param = (INTVAL)(long) ext;
+            i_param = (INTVAL)(long) external_data;
             goto case_I;
         case 'i':
-            i_param = (INTVAL)(int)(long) ext;
+            i_param = (INTVAL)(int)(long) external_data;
             goto case_I;
         case 's':
-            i_param = (INTVAL)(short)(long) ext;
+            i_param = (INTVAL)(short)(long) external_data;
             goto case_I;
         case 'c':
-            i_param = (INTVAL)(char)(long)ext;
+            i_param = (INTVAL)(char)(long)external_data;
 case_I:
             pasm_sig[2] = 'I';
             param = (void*) i_param;
@@ -290,7 +302,7 @@
         case 'p':
             /* created a UnManagedStruct */
             p_param = pmc_new(interpreter, enum_class_UnManagedStruct);
-            PMC_data(p_param) = ext;
+            PMC_data(p_param) = external_data;
             pasm_sig[2] = 'P';
             param = (void*) p_param;
             break;
@@ -301,7 +313,7 @@
 #endif
         case 't':
             pasm_sig[2] = 'S';
-            param = string_from_cstring(interpreter, ext, 0);
+            param = string_from_cstring(interpreter, external_data, 0);
             break;
         default:
             internal_exception(1, "unhandled signature char '%c' in run_cb", *p);
@@ -312,9 +324,9 @@
 }
 /*
 
-=item C<void Parrot_callback_C(void *external_data, PMC *callback_info)>
+=item C<void Parrot_callback_C(void *external_data, PMC *user_data)>
 
-=item C<void Parrot_callback_D(PMC *callback_info, void *external_data)>
+=item C<void Parrot_callback_D(PMC *user_data, void *external_data)>
 
 NCI callback functions s. ppd16
 
@@ -323,15 +335,15 @@
 */
 
 void
-Parrot_callback_C(void *external_data, PMC *callback_info)
+Parrot_callback_C(void *external_data, PMC *user_data)
 {
-    verify_CD(external_data, callback_info);
+    verify_CD(external_data, user_data);
 }
 
 void
-Parrot_callback_D(PMC *callback_info, void *external_data)
+Parrot_callback_D(PMC *user_data, void *external_data)
 {
-    verify_CD(external_data, callback_info);
+    verify_CD(external_data, user_data);
 }
 
 /*
Index: src/nci_test.c
===================================================================
RCS file: /cvs/public/parrot/src/nci_test.c,v
retrieving revision 1.34
diff -u -u -r1.34 nci_test.c
--- src/nci_test.c	8 Oct 2004 11:57:40 -0000	1.34
+++ src/nci_test.c	12 Oct 2004 22:16:35 -0000
@@ -81,6 +81,9 @@
 typedef void (*cb_D3_func)(void*, void*);
 void nci_cb_D3(cb_D3_func, void*);
 
+typedef void (*cb_D4_func)(void*, void*);
+void nci_cb_D4(cb_D4_func, void*);
+
 typedef struct {
     int y;
 } Nested;
@@ -376,12 +379,16 @@
     const char *result = "succeeded";
     /* call the cb synchronously */
     (cb)(result, user_data);
+
+    return;
 }
 
 void
 nci_cb_C2(cb_C2_func cb, void* user_data) {
     /* call the cb synchronously */
     (cb)(77, user_data);
+
+    return;
 }
 
 static int int_cb_C3 = 99;
@@ -389,6 +396,8 @@
 nci_cb_C3(cb_C3_func cb, void* user_data) {
     /* call the cb synchronously */
     (cb)(&int_cb_C3, user_data);
+
+    return;
 }
 
 void
@@ -396,12 +405,16 @@
     const char *result = "succeeded";
     /* call the cb synchronously */
     (cb)(user_data, result);
+
+    return;
 }
 
 void
 nci_cb_D2(cb_D2_func cb, void* user_data) {
     /* call the cb synchronously */
     (cb)(user_data, 88);
+
+    return;
 }
 
 static int int_cb_D3 = 111;
@@ -409,8 +422,22 @@
 nci_cb_D3(cb_D3_func cb, void* user_data) {
     /* call the cb synchronously */
     (cb)(user_data, &int_cb_D3);
+
+    return;
 }
 
+static int int_cb_D4 = 1;
+void
+nci_cb_D4(cb_D4_func times_ten, void* user_data) {
+    int cnt;
+    for ( cnt = 0; cnt < 10; cnt++ )
+    {
+        (times_ten)(user_data, &int_cb_D4);
+        int_cb_D4++;
+    }
+
+    return;
+}
 
 void
 nci_pip (int count, Rect_Like *rects) {
Index: t/pmc/nci.t
===================================================================
RCS file: /cvs/public/parrot/t/pmc/nci.t,v
retrieving revision 1.55
diff -u -u -r1.55 nci.t
--- t/pmc/nci.t	12 Oct 2004 09:00:26 -0000	1.55
+++ t/pmc/nci.t	12 Oct 2004 22:16:38 -0000
@@ -24,7 +24,7 @@
 
 =cut
 
-use Parrot::Test tests => 46;
+use Parrot::Test tests => 47;
 use Parrot::Config;
 
 SKIP: {
@@ -1576,6 +1576,76 @@
 OUTPUT
 
 
+output_is(<<'CODE', <<'OUTPUT', "nci_cb_D4 - synchronous callbacks");
+##PIR##
+
+.include "datatypes.pasm"
+
+.sub _test @MAIN
+
+    # prepare user data
+    .local pmc user_data
+    user_data = new Integer
+    user_data = 42
+
+    # A Sub that can be given to the library
+    # this callback function will eventually by called by the library
+    .local pmc cb
+    cb = newsub _call_back
+    .local pmc cb_wrapped
+    cb_wrapped = new_callback cb, user_data, "Up"	# Z in pdd16
+    print "created a callback sub\n"
+    .local pmc synchronous
+    synchronous = new Integer
+    synchronous = 1
+    setprop user_data, "_synchronous", synchronous
+    print "marked callback as synchronous\n"
+
+    # now call the external sub, that takes a callback and user data
+    .local pmc libnci
+    libnci = loadlib "libnci"
+    .local pmc nci_cb_D4
+    nci_cb_D4 = dlfunc libnci, "nci_cb_D4", "vpP"
+    print "loaded a function that takes a callback\n"
+    nci_cb_D4( cb_wrapped, user_data )
+
+    end
+.end
+
+.sub _call_back
+  # P6 is a UnManagedStruct PMC containing a pointer to an integer
+  new P2, .PerlArray
+  push P2, .DATATYPE_INT
+  push P2, 0
+  push P2, 0
+  assign P6, P2
+
+  print "external data: "
+  I17 = P6[0]
+  print I17
+  print "\n"
+  I17 = I17 * 10
+  P6[0] = I17
+
+  invoke P1
+.end
+
+CODE
+created a callback sub
+marked callback as synchronous
+loaded a function that takes a callback
+external data: 1
+external data: 11
+external data: 111
+external data: 1111
+external data: 11111
+external data: 111111
+external data: 1111111
+external data: 11111111
+external data: 111111111
+external data: 1111111111
+OUTPUT
+
 output_is(<<'CODE', <<'OUTPUT', 'nci_pip - array of structs');
 
 .include "datatypes.pasm"
