2009-11-24 29 views
5

EDIT: Tôi đã tạo một ticket cho điều này có dữ liệu thay thế cho cách làm việc này.Tạo cuộc gọi lại Threaded trong XS

Tôi có updated the code trong nỗ lực sử dụng gọi lại của MY_CXT vì gcxt không được lưu trữ trên các chuỗi. Tuy nhiên điều này segfaults tại 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; 

Điều này sẽ phân biệt ngay khi tôi vào ENTER để gọi lại.

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

Output là

$ 

nó phải được

$ Never Prints 
+0

Nên không có được một "giấc ngủ" giữa cài đặt hẹn giờ và in $ thời gian? – tsee

+1

Nếu chương trình của bạn không chặn nhưng chỉ đơn giản là nhảy trở lại vỏ, điều này có vẻ như một vụ tai nạn cứng hoặc nếu không perl sẽ không hoàn toàn có được ra khỏi tầm kiểm soát. Hãy thử một perl gỡ lỗi và chạy mọi thứ trong gdb. – tsee

+0

Ok Tôi đang cố gắng nhưng không có gì đã cho tôi một ý tưởng hoàn toàn khác. Tôi đã đính kèm vé cho câu hỏi này. – kthakore

Trả lời

-1

Chúng tôi đã tìm thấy giải pháp cho điều này bằng cách sử dụng chủ đề và chủ đề thông dịch Perl :: được chia sẻ. Xin vui lòng xem những

Time.xs

Ngoài ra đây là một ví dụ về một kịch bản sử dụng mã này.

TestTimer.pl

0

$ thời gian cần phải được một biến chia sẻ - nếu không công trình perl với bản riêng biệt của biến.

+0

um ... Tôi không biết bạn đang đề cập đến điều gì. Chăm sóc để đặt một số mã lên? – kthakore

+0

Thêm ngủ 200 vào cuối và xem bạn có thấy bất kỳ đầu ra nào không. – weismat

+0

không có. Nó thậm chí không ngủ được. :( – kthakore

4

bình luận nhanh:

  • Không sử dụng cấu trúc Perl (SV, AV, HV, ...) bên ngoài bối cảnh của một đối tượng thông dịch Perl. I E. không sử dụng nó làm dữ liệu tĩnh cấp C. Nó sẽ nổ tung trong một bối cảnh luồng. Tin tôi đi, tôi đã ở đó.
  • Kiểm tra phần "Lưu trữ dữ liệu tĩnh an toàn trong XS" trong trang nhân viên perlxs.
  • Một số nội dung bạn đang thực hiện có vẻ ngoài công khai từ quan điểm của perlapi. Tôi không chắc lắm.
+0

vui lòng xem nội dung cập nhật – kthakore

0

Cách xử lý ưu tiên của tôi là lưu trữ dữ liệu trong mã băm PL_modglobal. Nó tự động gắn với thông dịch viên hiện tại.

Các vấn đề liên quan