10 Starts executing the thread. Needs to clean up memory a tad better.
14 THREAD_RET_TYPE thread_run(LPVOID arg) {
15 ithread* thread = (ithread*) arg;
17 void thread_run(ithread* thread) {
21 dTHXa(thread->interp);
24 PERL_SET_CONTEXT(thread->interp);
27 thread->thr = GetCurrentThreadId();
29 thread->thr = pthread_self();
32 SHAREDSvEDIT(threads);
33 thread_tid_ptr = Perl_newSViv(sharedsv_space, (IV) thread->thr);
34 thread_ptr = Perl_newSViv(sharedsv_space, (IV) thread);
35 hv_store_ent((HV*)SHAREDSvGET(threads), thread_tid_ptr, thread_ptr,0);
36 SvREFCNT_dec(thread_tid_ptr);
37 SHAREDSvRELEASE(threads);
40 PL_perl_destruct_level = 2;
47 params = (AV*) SvRV(thread->params);
53 for(i = 0; i < len + 1; i++) {
54 XPUSHs(av_shift(params));
58 call_sv(thread->init_function, G_DISCARD);
67 MUTEX_LOCK(&thread->mutex);
68 perl_destruct(thread->interp);
69 perl_free(thread->interp);
70 if(thread->detached == 1) {
71 MUTEX_UNLOCK(&thread->mutex);
72 thread_destruct(thread);
74 MUTEX_UNLOCK(&thread->mutex);
88 SV* thread_create(char* class, SV* init_function, SV* params) {
89 ithread* thread = malloc(sizeof(ithread));
94 PerlInterpreter *current_perl;
96 MUTEX_LOCK(&create_mutex);
98 obj = newSVrv(obj_ref, class);
99 sv_setiv(obj, (IV)thread);
103 current_perl = PERL_GET_CONTEXT;
106 here we put the values of params and function to call onto namespace, this is so perl will properly clone them when we call perl_clone.
109 /*if(SvTYPE(SvRV(init_function)) == SVt_PVCV) {
110 CvCLONED_on(SvRV(init_function));
114 temp_store = Perl_get_sv(current_perl, "threads::paramtempstore", TRUE | GV_ADDMULTI);
115 Perl_sv_setsv(current_perl, temp_store,params);
119 temp_store = Perl_get_sv(current_perl, "threads::calltempstore", TRUE | GV_ADDMULTI);
120 Perl_sv_setsv(current_perl,temp_store, init_function);
125 thread->interp = perl_clone(current_perl,4);
127 thread->interp = perl_clone(current_perl,0);
130 PL_perl_destruct_level = 2;
133 sv_dump(SvRV(Perl_get_sv(current_perl, "threads::calltempstore",FALSE)));
134 sv_dump(SvRV(Perl_get_sv(thread->interp, "threads::calltempstore",FALSE)));
137 thread->init_function = newSVsv(Perl_get_sv(thread->interp, "threads::calltempstore",FALSE));
138 thread->params = newSVsv(Perl_get_sv(thread->interp, "threads::paramtempstore",FALSE));
140 init_function = NULL;
145 And here we make sure we clean up the data we put in the namespace of iThread, both in the new and the calling inteprreter
150 temp_store = Perl_get_sv(thread->interp,"threads::paramtempstore",FALSE);
151 Perl_sv_setsv(thread->interp,temp_store, &PL_sv_undef);
153 temp_store = Perl_get_sv(thread->interp,"threads::calltempstore",FALSE);
154 Perl_sv_setsv(thread->interp,temp_store, &PL_sv_undef);
156 PERL_SET_CONTEXT(current_perl);
158 temp_store = Perl_get_sv(current_perl,"threads::paramtempstore",FALSE);
159 Perl_sv_setsv(current_perl, temp_store, &PL_sv_undef);
161 temp_store = Perl_get_sv(current_perl,"threads::calltempstore",FALSE);
162 Perl_sv_setsv(current_perl, temp_store, &PL_sv_undef);
164 /* lets init the thread */
170 MUTEX_INIT(&thread->mutex);
171 thread->tid = tid_counter++;
172 thread->detached = 0;
177 thread->handle = CreateThread(NULL, 0, thread_run,
178 (LPVOID)thread, 0, &thread->thr);
181 pthread_create( &thread->thr, NULL, (void *) thread_run, thread);
183 MUTEX_UNLOCK(&create_mutex);
186 if(!SvRV(obj_ref)) printf("FUCK\n");
191 returns the id of the thread
193 I32 thread_tid (SV* obj) {
196 obj = thread_self(SvPV_nolen(obj));
197 thread = (ithread*)SvIV(SvRV(obj));
200 thread = (ithread*)SvIV(SvRV(obj));
205 SV* thread_self (char* class) {
213 PerlInterpreter *old_context = PERL_GET_CONTEXT;
217 SHAREDSvEDIT(threads);
219 thread_tid_ptr = Perl_newSViv(sharedsv_space, (IV) GetCurrentThreadId());
221 thread_tid_ptr = Perl_newSViv(sharedsv_space, (IV) pthread_self());
223 thread_entry = Perl_hv_fetch_ent(sharedsv_space,(HV*) SHAREDSvGET(threads), thread_tid_ptr, 0,0);
224 thread_ptr = HeVAL(thread_entry);
225 SvREFCNT_dec(thread_tid_ptr);
226 pointer = SvIV(thread_ptr);
227 SHAREDSvRELEASE(threads);
232 obj_ref = newSViv(0);
233 obj = newSVrv(obj_ref, class);
234 sv_setiv(obj, pointer);
241 this code needs to take the returnvalue from the call_sv and send it back
244 void thread_join(SV* obj) {
245 ithread* thread = (ithread*)SvIV(SvRV(obj));
248 waitcode = WaitForSingleObject(thread->handle, INFINITE);
251 pthread_join(thread->thr,&retval);
258 needs to better clean up memory
261 void thread_detach(SV* obj) {
262 ithread* thread = (ithread*)SvIV(SvRV(obj));
263 MUTEX_LOCK(&thread->mutex);
264 thread->detached = 1;
266 pthread_detach(thread->thr);
268 MUTEX_UNLOCK(&thread->mutex);
273 void thread_DESTROY (SV* obj) {
274 ithread* thread = (ithread*)SvIV(SvRV(obj));
276 MUTEX_LOCK(&thread->mutex);
278 MUTEX_UNLOCK(&thread->mutex);
279 thread_destruct(thread);
283 void thread_destruct (ithread* thread) {
285 MUTEX_LOCK(&thread->mutex);
286 if(thread->count != 0) {
287 MUTEX_UNLOCK(&thread->mutex);
290 MUTEX_UNLOCK(&thread->mutex);
291 /* it is safe noone is holding a ref to this */
292 /*printf("proper destruction!\n");*/
296 MODULE = threads PACKAGE = threads
298 Perl_sharedsv_init(aTHX);
299 PL_perl_destruct_level = 2;
300 threads = Perl_sharedsv_new(aTHX);
301 SHAREDSvEDIT(threads);
302 SHAREDSvGET(threads) = (SV *)newHV();
303 SHAREDSvRELEASE(threads);
307 SV* temp = get_sv("threads::sharedsv_space", TRUE | GV_ADDMULTI);
308 SV* temp2 = newSViv((IV)sharedsv_space );
309 sv_setsv( temp , temp2 );
312 ithread* thread = malloc(sizeof(ithread));
315 MUTEX_INIT(&thread->mutex);
318 thread->thr = GetCurrentThreadId();
320 thread->thr = pthread_self();
322 SHAREDSvEDIT(threads);
323 thread_tid_ptr = Perl_newSViv(sharedsv_space, (IV) thread->thr);
324 thread_ptr = Perl_newSViv(sharedsv_space, (IV) thread);
325 hv_store_ent((HV*) SHAREDSvGET(threads), thread_tid_ptr, thread_ptr,0);
326 SvREFCNT_dec(thread_tid_ptr);
327 SHAREDSvRELEASE(threads);
330 MUTEX_INIT(&create_mutex);
337 create (class, function_to_call, ...)
339 SV * function_to_call
341 AV* params = newAV();
344 for(i = 2; i < items ; i++) {
345 av_push(params, ST(i));
348 RETVAL = thread_create(class, function_to_call, newRV_noinc((SV*) params));
356 RETVAL = thread_self(class);
364 RETVAL = thread_tid(obj);
374 temp = PL_markstack_ptr++;
376 if (PL_markstack_ptr != temp) {
377 /* truly void, because dXSARGS not invoked */
378 PL_markstack_ptr = temp;
379 XSRETURN_EMPTY; /* return empty stack */
381 /* must have used dXSARGS; list context implied */
382 return; /* assume stack size is correct */
390 temp = PL_markstack_ptr++;
392 if (PL_markstack_ptr != temp) {
393 /* truly void, because dXSARGS not invoked */
394 PL_markstack_ptr = temp;
395 XSRETURN_EMPTY; /* return empty stack */
397 /* must have used dXSARGS; list context implied */
398 return; /* assume stack size is correct */
410 temp = PL_markstack_ptr++;
412 if (PL_markstack_ptr != temp) {
413 /* truly void, because dXSARGS not invoked */
414 PL_markstack_ptr = temp;
415 XSRETURN_EMPTY; /* return empty stack */
417 /* must have used dXSARGS; list context implied */
418 return; /* assume stack size is correct */