cvsuser     04/02/09 06:47:08

  Modified:    include/parrot events.h interpreter.h
               ops      core.ops ops.num
               src      events.c interpreter.c nci_test.c
               t/pmc    nci.t
  Log:
  pdd16-3
  * implement Parrot_callback_D
  * new_callback opcode to create the CB
  * fix type handling of external_data
  
  Revision  Changes    Path
  1.12      +3 -2      parrot/include/parrot/events.h
  
  Index: events.h
  ===================================================================
  RCS file: /cvs/public/parrot/include/parrot/events.h,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -w -r1.11 -r1.12
  --- events.h  7 Feb 2004 12:58:46 -0000       1.11
  +++ events.h  9 Feb 2004 14:46:56 -0000       1.12
  @@ -1,7 +1,7 @@
   /* events.h
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: events.h,v 1.11 2004/02/07 12:58:46 leo Exp $
  + *     $Id: events.h,v 1.12 2004/02/09 14:46:56 leo Exp $
    *  Overview:
    *     This api will handle parrot events
    *  Data Structure and Algorithms:
  @@ -79,7 +79,8 @@
   void disable_event_checking(Parrot_Interp);
   void enable_event_checking(Parrot_Interp);
   
  -void Parrot_new_cb_event(Parrot_Interp, PMC*sub, PMC*user, void*ext);
  +void Parrot_new_cb_event(Parrot_Interp, PMC*sub, void*ext);
  +void Parrot_run_callback(Parrot_Interp, PMC*sub, void*ext);
   
   void Parrot_kill_event_loop(void);
   void* Parrot_sleep_on_event(Parrot_Interp, FLOATVAL t, void* next);
  
  
  
  1.121     +3 -2      parrot/include/parrot/interpreter.h
  
  Index: interpreter.h
  ===================================================================
  RCS file: /cvs/public/parrot/include/parrot/interpreter.h,v
  retrieving revision 1.120
  retrieving revision 1.121
  diff -u -w -r1.120 -r1.121
  --- interpreter.h     8 Feb 2004 19:42:04 -0000       1.120
  +++ interpreter.h     9 Feb 2004 14:46:56 -0000       1.121
  @@ -1,7 +1,7 @@
   /* interpreter.h
    *  Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
    *  CVS Info
  - *     $Id: interpreter.h,v 1.120 2004/02/08 19:42:04 leo Exp $
  + *     $Id: interpreter.h,v 1.121 2004/02/09 14:46:56 leo Exp $
    *  Overview:
    *     The interpreter api handles running the operations
    *  Data Structure and Algorithms:
  @@ -339,7 +339,8 @@
   
   void Parrot_callback_C(void *external_data, PMC *callback_info);
   void Parrot_callback_D(PMC *callback_info, void *external_data);
  -PMC* Parrot_make_cb(Parrot_Interp interpreter, PMC* sub, PMC* user_data);
  +PMC* Parrot_make_cb(Parrot_Interp interpreter, PMC* sub, PMC* user_data,
  +        STRING* cb_signature);
   
   typedef opcode_t *(*native_func_t)(struct Parrot_Interp * interpreter,
                                     opcode_t * cur_opcode,
  
  
  
  1.350     +10 -0     parrot/ops/core.ops
  
  Index: core.ops
  ===================================================================
  RCS file: /cvs/public/parrot/ops/core.ops,v
  retrieving revision 1.349
  retrieving revision 1.350
  diff -u -w -r1.349 -r1.350
  --- core.ops  4 Feb 2004 21:16:02 -0000       1.349
  +++ core.ops  9 Feb 2004 14:47:01 -0000       1.350
  @@ -1089,6 +1089,11 @@
   Register the PASM sub at address $2 as a compiler for source type $1.
   XXX: leo N/Y
   
  +=item B<new_callback>(out PMC, in PMC, in PMC, in STR)
  +
  +Create a callback stub $1 for PASM subroutine $2 with userdata $3 and
  +function signature $4.
  +
   =cut
   
   inline op loadlib(out PMC, in STR) {
  @@ -1153,6 +1158,11 @@
   }
   
   inline op bogus() {
  +  goto NEXT();
  +}
  +
  +op new_callback(out PMC, in PMC, in PMC, in STR) {
  +  $1 = Parrot_make_cb(interpreter, $2, $3, $4);
     goto NEXT();
   }
   
  
  
  
  1.22      +2 -0      parrot/ops/ops.num
  
  Index: ops.num
  ===================================================================
  RCS file: /cvs/public/parrot/ops/ops.num,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -w -r1.21 -r1.22
  --- ops.num   4 Feb 2004 21:16:02 -0000       1.21
  +++ ops.num   9 Feb 2004 14:47:01 -0000       1.22
  @@ -1363,3 +1363,5 @@
   errorson_ic  1336
   errorsoff_i  1337
   errorsoff_ic 1338
  +new_callback_p_p_p_s    1339
  +new_callback_p_p_p_sc   1340
  
  
  
  1.34      +4 -7      parrot/src/events.c
  
  Index: events.c
  ===================================================================
  RCS file: /cvs/public/parrot/src/events.c,v
  retrieving revision 1.33
  retrieving revision 1.34
  diff -u -w -r1.33 -r1.34
  --- events.c  9 Feb 2004 10:47:46 -0000       1.33
  +++ events.c  9 Feb 2004 14:47:04 -0000       1.34
  @@ -1,6 +1,6 @@
   /*
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: events.c,v 1.33 2004/02/09 10:47:46 leo Exp $
  +$Id: events.c,v 1.34 2004/02/09 14:47:04 leo Exp $
   
   =head1 NAME
   
  @@ -400,7 +400,7 @@
   /*
   
   =item C<void
  -Parrot_new_cb_event(Parrot_Interp, PMC*sub, PMC*user, void*ext)>
  +Parrot_new_cb_event(Parrot_Interp, PMC*sub, void*ext)>
   
   Prepare and schedul a callback event
   
  @@ -409,12 +409,11 @@
   */
   
   void
  -Parrot_new_cb_event(Parrot_Interp interpreter, PMC* sub, PMC* user, void* ext)
  +Parrot_new_cb_event(Parrot_Interp interpreter, PMC* sub, void* ext)
   {
       parrot_event* ev = mem_sys_allocate(sizeof(parrot_event));
       ev->type = EVENT_TYPE_CALL_BACK;
       ev->u.call_back.sub = sub;
  -    ev->u.call_back.user_data = user;
       ev->u.call_back.external_data = ext;
       Parrot_schedule_event(interpreter, ev);
   }
  @@ -1094,9 +1093,7 @@
               break;
           case EVENT_TYPE_CALL_BACK:
               edebug((stderr, "starting user cb\n"));
  -            Parrot_runops_fromc_args_save(interpreter, event->u.call_back.sub,
  -                    "PP",
  -                    event->u.call_back.user_data,
  +            Parrot_run_callback(interpreter, event->u.call_back.sub,
                       event->u.call_back.external_data);
               break;
           case EVENT_TYPE_SLEEP:
  
  
  
  1.264     +105 -16   parrot/src/interpreter.c
  
  Index: interpreter.c
  ===================================================================
  RCS file: /cvs/public/parrot/src/interpreter.c,v
  retrieving revision 1.263
  retrieving revision 1.264
  diff -u -w -r1.263 -r1.264
  --- interpreter.c     7 Feb 2004 16:44:31 -0000       1.263
  +++ interpreter.c     9 Feb 2004 14:47:04 -0000       1.264
  @@ -1,7 +1,7 @@
   /*
   ################################################################################
   Copyright: 2001-2003 The Perl Foundation.  All Rights Reserved.
  -$Id: interpreter.c,v 1.263 2004/02/07 16:44:31 leo Exp $
  +$Id: interpreter.c,v 1.264 2004/02/09 14:47:04 leo Exp $
   ################################################################################
   
   =head1 NAME
  @@ -1133,18 +1133,22 @@
   
   /*
   
  -=item C<PMC* Parrot_make_cb(Parrot_Interp interpreter, PMC* sub, PMC* user)>
  +=item C<PMC* Parrot_make_cb(Parrot_Interp interpreter, PMC* sub, PMC* user
  +        STRING* cb_signature)>
   
  -Register a callback function according to pdd16
  +Create a callback function according to pdd16.
   
   =cut
   
   */
   
   PMC*
  -Parrot_make_cb(Parrot_Interp interpreter, PMC* sub, PMC* user_data)
  +Parrot_make_cb(Parrot_Interp interpreter, PMC* sub, PMC* user_data,
  +        STRING *cb_signature)
   {
  -    PMC* interp_pmc, *cb;
  +    PMC* interp_pmc, *cb, *cb_sig;
  +    int type;
  +    char * sig_str;
       /*
        * we stuff all the information into the Sub PMC and pass that
        * on to the external sub
  @@ -1152,11 +1156,32 @@
       interp_pmc = VTABLE_get_pmc_keyed_int(interpreter, interpreter->iglobals,
               (INTVAL) IGLOBALS_INTERPRETER);
       VTABLE_setprop(interpreter, sub,
  -            string_make(interpreter, "_interpreter", 12, NULL,
  -                PObj_external_FLAG, NULL), interp_pmc);
  +            const_string(interpreter, "_interpreter"),
  +            interp_pmc);
       VTABLE_setprop(interpreter, sub,
  -            string_make(interpreter, "_user_data", 10, NULL,
  -                PObj_external_FLAG, NULL), user_data);
  +            const_string(interpreter, "_user_data"),
  +            user_data);
  +    /* only ASCII sigs supported */
  +    sig_str = cb_signature->strstart;
  +    if (*sig_str == 'U') {
  +        type = 'D';
  +    }
  +    else {
  +        ++sig_str;
  +        if (*sig_str == 'U') {
  +            type = 'C';
  +        }
  +        else {
  +            internal_exception(1, "unhandled signature '%Ss' in make_cb",
  +                    cb_signature);
  +        }
  +    }
  +
  +    cb_sig = pmc_new(interpreter, enum_class_PerlString);
  +    VTABLE_set_string_native(interpreter, cb_sig, cb_signature);
  +    VTABLE_setprop(interpreter, sub,
  +            const_string(interpreter, "_signature"),
  +            cb_sig);
       /*
        * we are gonna passing this PMC to external code, the PMCs
        * might get out of scope until the callback is called -
  @@ -1172,7 +1197,15 @@
        * it can be passed on with signature 'p'
        */
       cb = pmc_new(interpreter, enum_class_UnManagedStruct);
  +    /*
  +     * we handle currently 2 types only:
  +     * _C ... user_data is 2nd param
  +     * _D ... user_data is 1st param
  +     */
  +    if (type == 'C')
       PMC_data(cb) = F2DPTR(Parrot_callback_C);
  +    else
  +        PMC_data(cb) = F2DPTR(Parrot_callback_D);
       dod_register_pmc(interpreter, cb);
   
       return cb;
  @@ -1263,17 +1296,14 @@
   {
   
       PMC *passed_interp;         /* the interp that originated the CB */
  -    PMC *user_data;             /* user really intended to get that back */
       int async = 1;              /* cb is hitting this sub somewhen inmidst */
       /*
        * 3) extract user_data, func signature, check interpreter ...
        */
       passed_interp = VTABLE_getprop(interpreter, callback_info,
  -            string_from_cstring(interpreter, "_interpreter", 0));
  +            const_string(interpreter, "_interpreter"));
       if (PMC_data(passed_interp) != interpreter)
           PANIC("callback gone to wrong interpreter");
  -    user_data = VTABLE_getprop(interpreter, callback_info,
  -            string_from_cstring(interpreter, "_user_data", 0));
       /*
        * 4) check if the call_back is synchronous:
        *    - if yes we are inside the NCI call
  @@ -1290,8 +1320,7 @@
            * then wait for the CB_EVENT_xx to finish and return the
            * result
            */
  -        Parrot_new_cb_event(interpreter, callback_info,
  -                user_data, external_data);
  +        Parrot_new_cb_event(interpreter, callback_info, external_data);
       }
       else {
           /*
  @@ -1300,6 +1329,66 @@
       }
   }
   
  +void
  +Parrot_run_callback(Parrot_Interp interpreter, PMC* sub, void* ext)
  +{
  +    PMC* user_data, *sig;
  +    STRING* sig_str;
  +    char *p;
  +    char pasm_sig[4];
  +    FLOATVAL d_param;
  +    INTVAL   i_param;
  +    void*    param;
  +
  +    user_data = VTABLE_getprop(interpreter, sub,
  +            const_string(interpreter, "_user_data"));
  +    sig = VTABLE_getprop(interpreter, sub,
  +            const_string(interpreter, "_signature"));
  +    sig_str = VTABLE_get_string(interpreter, sig);
  +    p = sig_str->strstart;
  +
  +    pasm_sig[0] = 'v';  /* no return value supported yet */
  +    pasm_sig[1] = 'P';
  +    if (*p == 'U') /* user_data Z in pdd16 */
  +        ++p;    /* p is now type of external data */
  +    switch (*p) {
  +        case 'v':
  +            pasm_sig[2] = 'v';
  +            break;
  +        case '2':
  +        case '3':
  +        case '4':
  +        case 'l':
  +        case 'i':
  +        case 's':
  +        case 'c':
  +            pasm_sig[2] = 'I';
  +            i_param = *(INTVAL*) ext;
  +            param = &i_param;
  +            break;
  +        case 'f':
  +        case 'd':
  +            pasm_sig[2] = 'N';
  +            d_param = *(FLOATVAL*) ext;
  +            param = &d_param;
  +            break;
  +#if 0
  +        case 'p':
  +        case 'P':
  +            pasm_sig[2] = 'P';
  +            break;
  +#endif
  +        case 't':
  +            pasm_sig[2] = 'S';
  +            param = string_from_cstring(interpreter, ext, 0);
  +            break;
  +        default:
  +            internal_exception(1, "unhandled sig char '%c' in run_cb");
  +    }
  +    pasm_sig[3] = '\0';
  +    Parrot_runops_fromc_args_save(interpreter, sub, pasm_sig,
  +            user_data, param);
  +}
   /*
   
   =item C<void Parrot_callback_C(void *external_data, PMC *callback_info)>
  
  
  
  1.21      +12 -1     parrot/src/nci_test.c
  
  Index: nci_test.c
  ===================================================================
  RCS file: /cvs/public/parrot/src/nci_test.c,v
  retrieving revision 1.20
  retrieving revision 1.21
  diff -u -w -r1.20 -r1.21
  --- nci_test.c        7 Feb 2004 12:58:53 -0000       1.20
  +++ nci_test.c        9 Feb 2004 14:47:05 -0000       1.21
  @@ -23,6 +23,9 @@
   typedef void (*cb_C1_func)(const char*, void*);
   void nci_cb_C1(cb_C1_func, void*);
   
  +typedef void (*cb_D1_func)(void*, const char*);
  +void nci_cb_D1(cb_D1_func, void*);
  +
   double nci_dd(double d) {
       return d * 2.0;
   }
  @@ -231,9 +234,17 @@
   void
   nci_cb_C1(cb_C1_func cb, void* user_data)
   {
  -    const char *result = "succeded";
  +    const char *result = "succeeded";
       /* call the cb synchronously */
       (cb)(result, user_data);
  +}
  +
  +void
  +nci_cb_D1(cb_D1_func cb, void* user_data)
  +{
  +    const char *result = "succeeded";
  +    /* call the cb synchronously */
  +    (cb)(user_data, result);
   }
   
   #ifdef TEST
  
  
  
  1.31      +70 -16    parrot/t/pmc/nci.t
  
  Index: nci.t
  ===================================================================
  RCS file: /cvs/public/parrot/t/pmc/nci.t,v
  retrieving revision 1.30
  retrieving revision 1.31
  diff -u -w -r1.30 -r1.31
  --- nci.t     8 Feb 2004 19:42:09 -0000       1.30
  +++ nci.t     9 Feb 2004 14:47:07 -0000       1.31
  @@ -1,4 +1,4 @@
  -use Parrot::Test tests => 27;
  +use Parrot::Test tests => 28;
   use Parrot::Config;
   
   print STDERR $PConfig{jitcpuarch}, " JIT CPU\n";
  @@ -824,39 +824,33 @@
   OUTPUT
   
   output_is(<<'CODE', <<'OUTPUT', "nci_cb_C1");
  -  bounds 1   # no JIT yet
  +
     # we need a flag if the call_back is already done
     new P10, .PerlInt
     store_global "cb_done", P10
     # first attempt - create cb manually (this step will be hidden later)
  -  newsub P5, .Sub, _call_back
  -  null P1
  -  dlfunc P0, P1, "Parrot_make_cb", "PIPP"
  -  print "ok 1\n"
  +  newsub P6, .Sub, _call_back
     # prepare user data
  -  new P6, .PerlInt
  -  set P6, 42
  -  # preserve the Sub
  -  set P7, P5
  -  # create callback (=> P5)
  -  invoke
  +  new P7, .PerlInt
  +  set P7, 42
  +  new_callback P5, P6, P7, "tU"      # Z in pdd16
  +  print "ok 1\n"
     # now call the external sub, that takes a call_back and user_data
     loadlib P1, "libnci"
     dlfunc P0, P1, "nci_cb_C1", "vpP"
     print "ok 2\n"
     # P5 is the cb
  -  # get user_data i.e. the Sub
  -  set P6, P7
  +  # P6 is user_data - the Sub
     invoke
     # call_back will be called at any time
     # so spin a bit
     set I20, 0
   loop:
     inc I20
  -  #or  sleep 0.01 and loop only a few times
  +  sleep 0.01
     find_global P11, "cb_done"
     if P11, fin
  -  gt I20, 100000, err
  +  gt I20, 10, err
     branch loop
   fin:
     print "done.\n"
  @@ -870,6 +864,9 @@
     print "user data: "
     print P5
     print "\n"
  +  print "external data: "
  +  print S5
  +  print "\n"
     find_global P12, "cb_done"
     inc P12
     invoke P1
  @@ -879,9 +876,66 @@
   ok 2
   in callback
   user data: 42
  +external data: succeeded
   done.
   OUTPUT
   
  +output_is(<<'CODE', <<'OUTPUT', "nci_cb_D1");
  +
  +  # we need a flag if the call_back is already done
  +  new P10, .PerlInt
  +  store_global "cb_done", P10
  +  # first attempt - create cb manually (this step will be hidden later)
  +  newsub P6, .Sub, _call_back
  +  # prepare user data
  +  new P7, .PerlInt
  +  set P7, 42
  +  new_callback P5, P6, P7, "Ut"      # Z in pdd16
  +  print "ok 1\n"
  +  # now call the external sub, that takes a call_back and user_data
  +  loadlib P1, "libnci"
  +  dlfunc P0, P1, "nci_cb_D1", "vpP"
  +  print "ok 2\n"
  +  # P5 is the cb
  +  # P6 is user_data - the Sub
  +  invoke
  +  # call_back will be called at any time
  +  # so spin a bit
  +  set I20, 0
  +loop:
  +  inc I20
  +  sleep 0.01
  +  find_global P11, "cb_done"
  +  if P11, fin
  +  gt I20, 10, err
  +  branch loop
  +fin:
  +  print "done.\n"
  +  end
  +err:
  +  print "cb didnt run\n"
  +  end
  +
  +_call_back:
  +  print "in callback\n"
  +  print "user data: "
  +  print P5
  +  print "\n"
  +  print "external data: "
  +  print S5
  +  print "\n"
  +  find_global P12, "cb_done"
  +  inc P12
  +  invoke P1
  +
  +CODE
  +ok 1
  +ok 2
  +in callback
  +user data: 42
  +external data: succeeded
  +done.
  +OUTPUT
   } # SKIP
   
   1;
  
  
  

Reply via email to