2009-11-24 4 views
5

편집 :이 작업을 수행하는 방법 대신 데이터를 가지고있는 ticket을 만들었습니다.XS에서 스레드 콜백 만들기

gcxt가 스레드간에 저장하지 않으므로 MY_CXT의 콜백을 사용하기 위해 updated the code이 있습니다. 그러나 이것은 ENTER에서 segfaults입니다.

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

Enter 키를 누르면 콜백이 시작됩니다. 변수의 별도의 사본과 달리 펄 작품 -

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

출력

$ 

그것이 $ 시간이 공유 변수가 될 필요가

$ Never Prints 
+0

가 타이머를 설정하고 $ 시간을 인쇄 할 사이에 "절전"있어야하지 않나요? – tsee

+1

프로그램이 차단되지 않고 단순히 셸로 돌아 가면 하드 충돌이나 그렇지 않으면 펄이 완전히 제어 할 수없는 것처럼 보입니다. 디버깅 펄과 gdb에서 실행 해보십시오. – tsee

+0

좋아, 나는 이것을 시도하고 있지만 나에게 완전히 다른 아이디어를주지는 않았다. 나는이 질문에 표를 붙였다. – kthakore

답변

-1

우리는 Perl 인터프리터 스레드와 스레드 :: 공유를 사용하여이 해결책을 발견했습니다. 이

Time.xs

는 또한 여기에이 코드를 사용하여 스크립트의 예입니다 참조하십시오.

TestTimer.pl

0

해야합니다.

+0

음 ... 나는 당신이 말하는 것을 전혀 모른다. 몇 가지 코드를 신경 써야하나요? – kthakore

+0

끝에 수면 200을 추가하고 출력이 있는지 확인하십시오. – weismat

+0

아무 것도 안됩니다. 그것은 심지어 자지 않습니다. : ( – kthakore

4

빠른 댓글 :

  • 는 펄 인터프리터 객체의 컨텍스트 외부 펄 구조체 (SV, AV, HV, ...)를 사용하지 마십시오. 나는. C 레벨 정적 데이터로 사용하지 마십시오. 스레딩 컨텍스트에서 폭발합니다. 날 믿어. 나는 거기 있었어.
  • perlxs (영문) 맨 페이지의 "XS에서 안전하게 정적 데이터 저장"섹션을 확인하십시오.
  • 당신이하고있는 것들 중 일부는 perlapi의 관점에서 비공개로 보입니다. 그래도 나는 확실하지 않다.
+0

업데이트를 참조하십시오 – kthakore

0

내 처리 방식은 데이터를 PL_modglobal 해시에 저장하는 것입니다. 현재 통역사와 자동으로 연결됩니다.

관련 문제