2009-11-24 13 views
5

EDIT: per questo ho creato uno ticket che ha dati su un'alternativa a questo modo di fare le cose.Creazione di callback con thread in XS

Ho updated the code in un tentativo di utilizzare il callback MY_CXT poiché gcxt non si memorizzava tra i thread. Comunque questo segfaults su ENTER.

#include "EXTERN.h" 
#include "perl.h" 
#include "XSUB.h" 

#ifndef aTHX_ 
#define aTHX_ 
#endif 

#ifdef USE_THREADS 
#define HAVE_TLS_CONTEXT 
#endif 

/* For windows */ 
#ifndef SDL_PERL_DEFINES_H 
#define SDL_PERL_DEFINES_H 

#ifdef HAVE_TLS_CONTEXT 
PerlInterpreter *parent_perl = NULL; 
extern PerlInterpreter *parent_perl; 
#define GET_TLS_CONTEXT parent_perl = PERL_GET_CONTEXT; 
#define ENTER_TLS_CONTEXT \ 
     PerlInterpreter *current_perl = PERL_GET_CONTEXT; \ 
      PERL_SET_CONTEXT(parent_perl); { \ 
           PerlInterpreter *my_perl = parent_perl; 
#define LEAVE_TLS_CONTEXT \ 
             } PERL_SET_CONTEXT(current_perl); 
#else 
#define GET_TLS_CONTEXT   /* TLS context not enabled */ 
#define ENTER_TLS_CONTEXT  /* TLS context not enabled */ 
#define LEAVE_TLS_CONTEXT  /* TLS context not enabled */ 
#endif 

#endif 


#include <SDL.h> 

#define MY_CXT_KEY "SDL::Time::_guts" XS_VERSION 


typedef struct { 
void* data; 
SV* callback; 
Uint32 retval; 
} my_cxt_t; 

static my_cxt_t gcxt; 

START_MY_CXT 


static Uint32 add_timer_cb (Uint32 interval, void* param) 
{ 

     ENTER_TLS_CONTEXT 
     dMY_CXT; 
     dSP; 
     int back; 
     ENTER; //SEGFAULTS RIGHT HERE! 
     SAVETMPS; 
     PUSHMARK(SP); 
     XPUSHs(sv_2mortal(newSViv(interval))); 
     PUTBACK; 

     if (0 != (back = call_sv(MY_CXT.callback,G_SCALAR))) { 
     SPAGAIN; 
     if (back != 1) Perl_croak (aTHX_ "Timer Callback failed!"); 
     MY_CXT.retval = POPi;  
     } else { 
     Perl_croak(aTHX_ "Timer Callback failed!"); 
     } 

     FREETMPS; 
     LEAVE; 

     LEAVE_TLS_CONTEXT 
     dMY_CXT; 
     return MY_CXT.retval; 

} 

MODULE = SDL::Time PACKAGE = SDL::Time PREFIX = time_ 

BOOT: 
{ 
    MY_CXT_INIT; 
} 


SDL_TimerID 
time_add_timer (interval, cmd) 
    Uint32 interval 
    void *cmd 
    PREINIT: 
     dMY_CXT; 
    CODE: 
     MY_CXT.callback=cmd;  
     gcxt = MY_CXT; 
     RETVAL = SDL_AddTimer(interval,add_timer_cb,(void *)cmd);  
    OUTPUT: 
     RETVAL 

void 
CLONE(...) 
    CODE: 
    MY_CXT_CLONE; 

Questo segfaults non appena entro in INVIO per la richiamata.

use SDL; 
use SDL::Time; 

SDL::init(SDL_INIT_TIMER); 
my $time = 0; 
SDL::Timer::add_timer(100, sub { $time++; return $_[0]}); 
sleep(10); 
print "Never Prints"; 

uscita è

$ 

Va

$ Never Prints 
+0

non dovrebbe esserci un "sonno" tra l'impostazione del timer e la stampa $ tempo? – tsee

+1

Se il tuo programma non blocca ma torna semplicemente alla shell, questo sembra un arresto anomalo o altrimenti perl non sarebbe totalmente fuori controllo. Prova un debl perl e esegui le cose all'interno di gdb. – tsee

+0

Ok, ci sto provando, ma nulla mi ha dato un'idea completamente diversa. Ho allegato il ticket a questa domanda. – kthakore

risposta

-1

Abbiamo trovato una soluzione a questo utilizzando thread e thread dell'interprete Perl :: shared. Da queste

Time.xs

Anche qui è un esempio di uno script utilizzando questo codice.

TestTimer.pl

0

$ tempo deve essere una variabile condivisa - altrimenti opere perl con copie separate della variabile.

+0

um ... Non ho idea di cosa ti riferisci. Ti va di mettere un po 'di codice? – kthakore

+0

Aggiungi sleep 200 alla fine e controlla se vedi qualsiasi output. – weismat

+0

no, non andare. Non riesce nemmeno a dormire. :( – kthakore

4

commenti rapidi:

  • Non utilizzare Perl struct (SV, AV, HV, ...) al di fuori del contesto di un oggetto interprete Perl. Cioè non usarlo come dati statici di livello C. Scoppierà in un contesto di threading. Fidati di me, ci sono stato.
  • Controllare la sezione "Archiviazione sicura dei dati statici in XS" nella manpage perlxs.
  • Alcune di quelle cose che stai facendo sembrano piuttosto non pubbliche dal punto di vista della perlapi. Non sono abbastanza sicuro, però.
+0

si prega di consultare l'aggiornamento – kthakore

0

Il mio modo preferito di gestirlo è archiviare i dati nell'hash PL_modglobal. È automaticamente collegato all'interprete corrente.

Problemi correlati