2009-11-24 12 views
5

EDYCJA: Stworzyłem ticket dla tego, który ma dane na temat alternatywy dla tego sposobu robienia rzeczy.Tworzenie wątków zwrotnych w XS

Mam updated the code próbuję użyć wywołania zwrotnego MY_CXT, ponieważ gcxt nie przechowywał wątków. Jednak to powoduje awarię na 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; 

Ten błąd występuje, gdy tylko wejdę w ENTER w celu oddzwonienia.

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"; 

Wyjście jest

$ 

powinno być

$ Never Prints 
+0

nie powinien istnieć „uśpienia” pomiędzy ustawieniem timera i drukowanie $ czas? – tsee

+1

Jeśli twój program nie blokuje, ale po prostu wskakuje z powrotem do powłoki, to wydaje się, że to twarda awaria lub inaczej perl nie wymknie się spod kontroli. Wypróbuj perl debugowania i uruchom programy w gdb. – tsee

+0

OK Próbuję tego, ale nic nie dało mi zupełnie innego pomysłu. Załączam bilet na to pytanie. – kthakore

Odpowiedz

-1

Znaleźliśmy rozwiązanie tego problemu za pomocą interpreterów i wątków interpretera Perla :: shared. Proszę zobaczyć te

Time.xs

Również tutaj jest przykład skryptu przy użyciu tego kodu.

TestTimer.pl

0

$ czas musi być wspólna zmienna - w przeciwnym razie Perl współpracuje z oddzielnych kopii zmiennej.

+0

um ... Nie mam zielonego pojęcia, o co ci chodzi. Chcesz umieścić trochę kodu? – kthakore

+0

Dodaj snu 200 na końcu i zobacz, czy widzisz jakieś wyjście. – weismat

+0

no no go go. Nawet nie zasypia. :( – kthakore

4

Szybkie komentarze:

  • Nie używać Perl konstrukcjom (SV, AV, HV, ...) poza kontekście interpretera obiektu Perl. To znaczy. nie używaj go jako statycznych danych na poziomie C. Będzie wybuchać w kontekście wątków. Zaufaj mi, byłem tam.
  • Zobacz sekcję "Bezpieczne przechowywanie danych statycznych w XS" na stronie podręcznika perlxs.
  • Niektóre z tych rzeczy, które robisz, wyglądają raczej niepublicznie z punktu widzenia perlapi. Nie jestem jednak całkiem pewien.
+0

zobacz aktualizację – kthakore

0

Moim preferowanym sposobem postępowania jest przechowywanie danych w haszu PL_modglobal. Jest automatycznie powiązany z aktualnym tłumaczem.

Powiązane problemy