[perl #37946] preserve the referent associated with a shared RV.
[p5sagit/p5-mst-13.2.git] / ext / threads / shared / shared.xs
CommitLineData
afe38520 1/* shared.xs
68795e93 2 *
60c5c75c 3 * Copyright (c) 2001-2002, 2006 Larry Wall
68795e93 4 *
5 * You may distribute under the terms of either the GNU General Public
6 * License or the Artistic License, as specified in the README file.
7 *
21312124 8 * "Hand any two wizards a piece of rope and they would instinctively pull in
9 * opposite directions."
10 * --Sourcery
11 *
12 * Contributed by Arthur Bergman arthur@contiller.se
13 * pulled in the (an)other direction by Nick Ing-Simmons nick@ing-simmons.net
14 */
68795e93 15
29ecdb6f 16/*
17 * Shared variables are implemented by a scheme similar to tieing.
18 * Each thread has a proxy SV with attached magic -- "private SVs" --
19 * which all point to a single SV in a separate shared interpreter
20 * (PL_sharedsv_space) -- "shared SVs".
21 *
22 * The shared SV holds the variable's true values, and its state is
23 * copied between the shared and private SVs with the usual
24 * mg_get()/mg_set() arrangement.
25 *
26 * Aggregates (AVs and HVs) are implemented using tie magic, except that
27 * the vtable used is one defined in this file rather than the standard one.
28 * This means that where a tie function like is FETCH is normally invoked by
29 * the tie magic's mg_get() function, we completely bypass the calling of a
30 * perl-level function, and directly call C-level code to handle it. On
31 * the other hand. calls to functions like PUSH are done directly by code
32 * in av.c etc, which we can't bypass. So the best we can do is to provide
33 * XS versions of these functions. We also have to attach a tie object,
34 * blessed into the class threads::shared::tie, to keep the method-calling
35 * code happy.
36 *
37 * Access to aggregate elements is done the usual tied way by returning a
38 * proxy PVLV element with attached element magic.
39 *
40 * Pointers to the shared SV are squirrelled away in the mg->mg_ptr field
41 * of magic (with mg_len == 0), and in the IV2PTR(SvIV(sv)) field of tied
42 * object SVs. These pointers have to be hidden like this because they
43 * cross interpreter boundaries, and we don't want sv_clear() and friends
44 * following them.
45 *
46 * The three basic shared types look like the following:
47 *
48 * -----------------
49 *
50 * Shared scalar (my $s : shared):
51 *
52 * SV = PVMG(0x7ba238) at 0x7387a8
53 * FLAGS = (PADMY,GMG,SMG)
54 * MAGIC = 0x824d88
55 * MG_TYPE = PERL_MAGIC_shared_scalar(n)
56 * MG_PTR = 0x810358 <<<< pointer to the shared SV
57 *
58 * -----------------
59 *
60 * Shared aggregate (my @a : shared; my %h : shared):
61 *
62 * SV = PVAV(0x7175d0) at 0x738708
63 * FLAGS = (PADMY,RMG)
64 * MAGIC = 0x824e48
65 * MG_TYPE = PERL_MAGIC_tied(P)
66 * MG_OBJ = 0x7136e0 <<<< ref to the tied object
67 * SV = RV(0x7136f0) at 0x7136e0
68 * RV = 0x738640
69 * SV = PVMG(0x7ba238) at 0x738640 <<<< the tied object
70 * FLAGS = (OBJECT,IOK,pIOK)
71 * IV = 8455000 <<<< pointer to the shared AV
72 * STASH = 0x80abf0 "threads::shared::tie"
73 * MG_PTR = 0x810358 "" <<<< another pointer to the shared AV
74 * ARRAY = 0x0
75 *
76 * -----------------
77 *
78 * Aggregate element (my @a : shared; $a[0])
79 *
80 * SV = PVLV(0x77f628) at 0x713550
81 * FLAGS = (GMG,SMG,RMG,pIOK)
82 * MAGIC = 0x72bd58
83 * MG_TYPE = PERL_MAGIC_shared_scalar(n)
84 * MG_PTR = 0x8103c0 "" <<<< pointer to the shared element
85 * MAGIC = 0x72bd18
86 * MG_TYPE = PERL_MAGIC_tiedelem(p)
87 * MG_OBJ = 0x7136e0 <<<< ref to the tied object
88 * SV = RV(0x7136f0) at 0x7136e0
89 * RV = 0x738660
90 * SV = PVMG(0x7ba278) at 0x738660 <<<< the tied object
91 * FLAGS = (OBJECT,IOK,pIOK)
92 * IV = 8455064 <<<< pointer to the shared AV
93 * STASH = 0x80ac30 "threads::shared::tie"
94 * TYPE = t
95 *
96 * Note that PERL_MAGIC_tiedelem(p) magic doesn't have a pointer to a
97 * shared SV in mg_ptr; instead this is used to store the hash key,
98 * if any, like normal tied elements. Note also that element SVs may have
99 * pointers to both the shared aggregate and the shared element
100 *
101 *
102 * Userland locks:
103 *
104 * if a shared variable is used as a perl-level lock or condition
105 * variable, then PERL_MAGIC_ext magic is attached to the associated
106 * *shared* SV, whose mg_ptr field points to a malloced structure
107 * containing the necessary mutexes and condition variables.
108 *
109 * Nomenclature:
110 *
111 * In this file, any variable name prefixed with 's', eg ssv, stmp or sobj,
112 * usually represents a shared SV which correspondis to a private SV named
113 * without the prefix, eg sv, tmp or obj.
114 */
115
68795e93 116#define PERL_NO_GET_CONTEXT
b050c948 117#include "EXTERN.h"
118#include "perl.h"
119#include "XSUB.h"
120
73e09c8f 121#ifdef USE_ITHREADS
122
21312124 123/*
124 * The shared things need an intepreter to live in ...
125 */
126PerlInterpreter *PL_sharedsv_space; /* The shared sv space */
127/* To access shared space we fake aTHX in this scope and thread's context */
057e91b3 128
129/* bug #24255: we include ENTER+SAVETMPS/FREETMPS+LEAVE with
130 * SHARED_CONTEXT/CALLER_CONTEXT macros, so that any mortals etc created
1011f542 131 * while in the shared interpreter context don't languish */
057e91b3 132
133#define SHARED_CONTEXT \
134 STMT_START { \
135 PERL_SET_CONTEXT((aTHX = PL_sharedsv_space)); \
136 ENTER; \
137 SAVETMPS; \
138 } STMT_END
21312124 139
140/* So we need a way to switch back to the caller's context... */
141/* So we declare _another_ copy of the aTHX variable ... */
142#define dTHXc PerlInterpreter *caller_perl = aTHX
057e91b3 143
21312124 144/* and use it to switch back */
057e91b3 145#define CALLER_CONTEXT \
146 STMT_START { \
147 FREETMPS; \
148 LEAVE; \
149 PERL_SET_CONTEXT((aTHX = caller_perl)); \
150 } STMT_END
21312124 151
152/*
153 * Only one thread at a time is allowed to mess with shared space.
154 */
a446a88f 155
6d56dc1c 156typedef struct
157{
158 perl_mutex mutex;
6d56dc1c 159 PerlInterpreter *owner;
160 I32 locks;
6b85e4fe 161 perl_cond cond;
162#ifdef DEBUG_LOCKS
163 char * file;
164 int line;
165#endif
6d56dc1c 166} recursive_lock_t;
167
168recursive_lock_t PL_sharedsv_lock; /* Mutex protecting the shared sv space */
169
170void
171recursive_lock_init(pTHX_ recursive_lock_t *lock)
172{
173 Zero(lock,1,recursive_lock_t);
174 MUTEX_INIT(&lock->mutex);
175 COND_INIT(&lock->cond);
176}
177
a39edb3a 178void
579f9913 179recursive_lock_destroy(pTHX_ recursive_lock_t *lock)
180{
181 MUTEX_DESTROY(&lock->mutex);
182 COND_DESTROY(&lock->cond);
183}
184
6d56dc1c 185void
186recursive_lock_release(pTHX_ recursive_lock_t *lock)
187{
188 MUTEX_LOCK(&lock->mutex);
189 if (lock->owner != aTHX) {
190 MUTEX_UNLOCK(&lock->mutex);
191 }
192 else {
193 if (--lock->locks == 0) {
194 lock->owner = NULL;
195 COND_SIGNAL(&lock->cond);
196 }
197 }
198 MUTEX_UNLOCK(&lock->mutex);
199}
a446a88f 200
6d56dc1c 201void
6b85e4fe 202recursive_lock_acquire(pTHX_ recursive_lock_t *lock,char *file,int line)
6d56dc1c 203{
204 assert(aTHX);
205 MUTEX_LOCK(&lock->mutex);
206 if (lock->owner == aTHX) {
207 lock->locks++;
208 }
209 else {
6b85e4fe 210 while (lock->owner) {
211#ifdef DEBUG_LOCKS
212 Perl_warn(aTHX_ " %p waiting - owned by %p %s:%d\n",
213 aTHX, lock->owner, lock->file, lock->line);
214#endif
6d56dc1c 215 COND_WAIT(&lock->cond,&lock->mutex);
6b85e4fe 216 }
6d56dc1c 217 lock->locks = 1;
218 lock->owner = aTHX;
6b85e4fe 219#ifdef DEBUG_LOCKS
220 lock->file = file;
221 lock->line = line;
222#endif
6d56dc1c 223 }
224 MUTEX_UNLOCK(&lock->mutex);
6b85e4fe 225 SAVEDESTRUCTOR_X(recursive_lock_release,lock);
6d56dc1c 226}
227
228#define ENTER_LOCK STMT_START { \
229 ENTER; \
6b85e4fe 230 recursive_lock_acquire(aTHX_ &PL_sharedsv_lock, __FILE__, __LINE__); \
a446a88f 231 } STMT_END
21312124 232
29ecdb6f 233/* the unlocking is done automatically at scope exit */
6d56dc1c 234#define LEAVE_LOCK LEAVE
235
21312124 236
237/* A common idiom is to acquire access and switch in ... */
238#define SHARED_EDIT STMT_START { \
6d56dc1c 239 ENTER_LOCK; \
21312124 240 SHARED_CONTEXT; \
241 } STMT_END
242
243/* then switch out and release access. */
244#define SHARED_RELEASE STMT_START { \
245 CALLER_CONTEXT; \
6d56dc1c 246 LEAVE_LOCK; \
21312124 247 } STMT_END
85e0a142 248
21312124 249
29ecdb6f 250/* user-level locks:
251 This structure is attached (using ext magic) to any shared SV that
252 is used by user-level locking or condition code
21312124 253*/
68795e93 254
255typedef struct {
29ecdb6f 256 recursive_lock_t lock; /* for user-levl locks */
68795e93 257 perl_cond user_cond; /* For user-level conditions */
29ecdb6f 258} user_lock;
68795e93 259
29ecdb6f 260/* magic used for attaching user_lock structs to shared SVs
68795e93 261
21312124 262 The vtable used has just one entry - when the SV goes away
263 we free the memory for the above.
21312124 264 */
68795e93 265
21312124 266int
29ecdb6f 267sharedsv_userlock_free(pTHX_ SV *sv, MAGIC *mg)
21312124 268{
29ecdb6f 269 user_lock *ul = (user_lock *) mg->mg_ptr;
270 assert(aTHX == PL_sharedsv_space);
271 if (ul) {
272 recursive_lock_destroy(aTHX_ &ul->lock);
273 COND_DESTROY(&ul->user_cond);
274 PerlMemShared_free(ul);
21312124 275 mg->mg_ptr = NULL;
276 }
277 return 0;
278}
279
29ecdb6f 280MGVTBL sharedsv_uesrlock_vtbl = {
21312124 281 0, /* get */
282 0, /* set */
283 0, /* len */
284 0, /* clear */
29ecdb6f 285 sharedsv_userlock_free, /* free */
21312124 286 0, /* copy */
287 0, /* dup */
a5063e7c 288 0 /* local */
21312124 289};
290
291/* Access to shared things is heavily based on MAGIC - in mg.h/mg.c/sv.c sense */
292
293/* In any thread that has access to a shared thing there is a "proxy"
294 for it in its own space which has 'MAGIC' associated which accesses
295 the shared thing.
296 */
297
298MGVTBL sharedsv_scalar_vtbl; /* scalars have this vtable */
299MGVTBL sharedsv_array_vtbl; /* hashes and arrays have this - like 'tie' */
300MGVTBL sharedsv_elem_vtbl; /* elements of hashes and arrays have this
29ecdb6f 301 _AS WELL AS_ the scalar magic:
302 The sharedsv_elem_vtbl associates the element with the array/hash and
21312124 303 the sharedsv_scalar_vtbl associates it with the value
304 */
305
6b85e4fe 306
29ecdb6f 307/* get shared aggregate SV pointed to by threads::shared::tie magic object */
308
309STATIC SV *
310S_sharedsv_from_obj(pTHX_ SV *sv)
6b85e4fe 311{
29ecdb6f 312 return SvROK(sv) ? INT2PTR(SV *, SvIV(SvRV(sv))) : NULL;
313}
314
315
316/* Return the user_lock structure (if any) associated with a shared SV.
317 * If create is true, create one if it doesn't exist */
318
319STATIC user_lock *
320S_get_userlock(pTHX_ SV* ssv, bool create)
321{
322 MAGIC *mg;
323 user_lock *ul = NULL;
324
325 assert(ssv);
326 /* XXX redsign the storage of user locks so we dont need a global
327 * lock to access them ???? DAPM */
328 ENTER_LOCK;
329 mg = mg_find(ssv, PERL_MAGIC_ext);
330 if (mg)
331 ul = (user_lock*)(mg->mg_ptr);
332 else if (create) {
333 dTHXc;
334 SHARED_CONTEXT;
335 ul = (user_lock *) PerlMemShared_malloc(sizeof(user_lock));
336 Zero(ul, 1, user_lock);
337 /* attach to shared SV using ext magic */
338 sv_magicext(ssv, NULL, PERL_MAGIC_ext, &sharedsv_uesrlock_vtbl,
339 (char *)ul, 0);
340 recursive_lock_init(aTHX_ &ul->lock);
341 COND_INIT(&ul->user_cond);
342 CALLER_CONTEXT;
343 }
344 LEAVE_LOCK;
345 return ul;
6b85e4fe 346}
347
29ecdb6f 348
21312124 349=for apidoc sharedsv_find
350
6b85e4fe 351Given a private side SV tries to find if the SV has a shared backend,
21312124 352by looking for the magic.
353
354=cut
355
29ecdb6f 356SV *
21312124 357Perl_sharedsv_find(pTHX_ SV *sv)
358{
359 MAGIC *mg;
a446a88f 360 if (SvTYPE(sv) >= SVt_PVMG) {
361 switch(SvTYPE(sv)) {
362 case SVt_PVAV:
363 case SVt_PVHV:
364 if ((mg = mg_find(sv, PERL_MAGIC_tied))
365 && mg->mg_virtual == &sharedsv_array_vtbl) {
29ecdb6f 366 return (SV *) mg->mg_ptr;
21312124 367 }
368 break;
a446a88f 369 default:
6b85e4fe 370 /* This should work for elements as well as they
371 * have scalar magic as well as their element magic
372 */
a446a88f 373 if ((mg = mg_find(sv, PERL_MAGIC_shared_scalar))
374 && mg->mg_virtual == &sharedsv_scalar_vtbl) {
29ecdb6f 375 return (SV *) mg->mg_ptr;
6b85e4fe 376 }
a446a88f 377 break;
21312124 378 }
379 }
6b85e4fe 380 /* Just for tidyness of API also handle tie objects */
381 if (SvROK(sv) && sv_derived_from(sv, "threads::shared::tie")) {
29ecdb6f 382 return S_sharedsv_from_obj(aTHX_ sv);
6b85e4fe 383 }
21312124 384 return NULL;
385}
68795e93 386
68795e93 387
29ecdb6f 388/* associate a private SV with a shared SV by pointing the appropriate
389 * magics at it. Assumes lock is held */
390
391void
392Perl_sharedsv_associate(pTHX_ SV *sv, SV *ssv)
21312124 393{
21312124 394 dTHXc;
a446a88f 395 MAGIC *mg = 0;
a446a88f 396
29ecdb6f 397 /* If we are asked for any private ops we need a thread */
a446a88f 398 assert ( aTHX != PL_sharedsv_space );
399
400 /* To avoid need for recursive locks require caller to hold lock */
6d56dc1c 401 assert ( PL_sharedsv_lock.owner == aTHX );
6b85e4fe 402
29ecdb6f 403 switch(SvTYPE(sv)) {
404 case SVt_PVAV:
405 case SVt_PVHV:
406 if (!(mg = mg_find(sv, PERL_MAGIC_tied))
407 || mg->mg_virtual != &sharedsv_array_vtbl
408 || (SV*) mg->mg_ptr != ssv)
409 {
410 SV *obj = newSV(0);
411 sv_setref_iv(obj, "threads::shared::tie",PTR2IV(ssv));
412 if (mg) {
413 sv_unmagic(sv, PERL_MAGIC_tied);
414 }
415 mg = sv_magicext(sv, obj, PERL_MAGIC_tied, &sharedsv_array_vtbl,
416 (char *) ssv, 0);
417 mg->mg_flags |= (MGf_COPY|MGf_DUP);
418 SvREFCNT_inc(ssv);
419 SvREFCNT_dec(obj);
29ecdb6f 420 }
421 break;
68795e93 422
29ecdb6f 423 default:
424 if ((SvTYPE(sv) < SVt_PVMG)
425 || !(mg = mg_find(sv, PERL_MAGIC_shared_scalar))
426 || mg->mg_virtual != &sharedsv_scalar_vtbl
427 || (SV*) mg->mg_ptr != ssv)
428 {
429 if (mg) {
430 sv_unmagic(sv, PERL_MAGIC_shared_scalar);
431 }
432 mg = sv_magicext(sv, Nullsv, PERL_MAGIC_shared_scalar,
433 &sharedsv_scalar_vtbl, (char *)ssv, 0);
60c5c75c 434 mg->mg_flags |= (MGf_DUP|MGf_LOCAL);
29ecdb6f 435 SvREFCNT_inc(ssv);
21312124 436 }
29ecdb6f 437 break;
21312124 438 }
29ecdb6f 439 assert ( Perl_sharedsv_find(aTHX_ sv) == ssv );
440}
6b85e4fe 441
6b85e4fe 442
29ecdb6f 443/* Given a private SV, create and return an associated shared SV.
444 * Assumes lock is held */
68795e93 445
29ecdb6f 446STATIC SV *
447S_sharedsv_new_shared(pTHX_ SV *sv)
448{
449 dTHXc;
450 SV *ssv;
6b85e4fe 451
29ecdb6f 452 assert(PL_sharedsv_lock.owner == aTHX);
453 assert(aTHX != PL_sharedsv_space);
68795e93 454
29ecdb6f 455 SHARED_CONTEXT;
456 ssv = newSV(0);
457 SvREFCNT(ssv) = 0; /* will be upped to 1 by Perl_sharedsv_associate */
458 sv_upgrade(ssv, SvTYPE(sv));
459 CALLER_CONTEXT;
460 Perl_sharedsv_associate(aTHX_ sv, ssv);
461 return ssv;
462}
21312124 463
21312124 464
29ecdb6f 465/* Given a shared SV, create and return an associated private SV.
466 * Assumes lock is held */
467
468STATIC SV *
469S_sharedsv_new_private(pTHX_ SV *ssv)
470{
471 SV *sv;
472
473 assert(PL_sharedsv_lock.owner == aTHX);
474 assert(aTHX != PL_sharedsv_space);
475
476 sv = newSV(0);
477 sv_upgrade(sv, SvTYPE(ssv));
478 Perl_sharedsv_associate(aTHX_ sv, ssv);
479 return sv;
21312124 480}
68795e93 481
29ecdb6f 482
483/* a threadsafe version of SvREFCNT_dec(ssv) */
484
485STATIC void
486S_sharedsv_dec(pTHX_ SV* ssv)
68795e93 487{
29ecdb6f 488 if (!ssv)
489 return;
490 ENTER_LOCK;
491 if (SvREFCNT(ssv) > 1) {
492 /* no side effects, so can do it lightweight */
493 SvREFCNT_dec(ssv);
494 }
495 else {
21312124 496 dTHXc;
29ecdb6f 497 SHARED_CONTEXT;
498 SvREFCNT_dec(ssv);
499 CALLER_CONTEXT;
21312124 500 }
29ecdb6f 501 LEAVE_LOCK;
68795e93 502}
503
29ecdb6f 504/* implements Perl-level share() and :shared */
505
21312124 506void
507Perl_sharedsv_share(pTHX_ SV *sv)
508{
509 switch(SvTYPE(sv)) {
510 case SVt_PVGV:
511 Perl_croak(aTHX_ "Cannot share globs yet");
512 break;
513
514 case SVt_PVCV:
515 Perl_croak(aTHX_ "Cannot share subs yet");
516 break;
85e0a142 517
21312124 518 default:
6d56dc1c 519 ENTER_LOCK;
29ecdb6f 520 (void) S_sharedsv_new_shared(aTHX_ sv);
6d56dc1c 521 LEAVE_LOCK;
a446a88f 522 SvSETMAGIC(sv);
523 break;
21312124 524 }
525}
68795e93 526
a0e036c1 527#if defined(WIN32) || defined(OS2)
528# define ABS2RELMILLI(abs) \
529 do { \
2666606c 530 abs -= (double)time(NULL); \
a0e036c1 531 if (abs > 0) { abs *= 1000; } \
532 else { abs = 0; } \
533 } while (0)
534#endif /* WIN32 || OS2 */
535
29ecdb6f 536/* do OS-specific condition timed wait */
537
a0e036c1 538bool
539Perl_sharedsv_cond_timedwait(perl_cond *cond, perl_mutex *mut, double abs)
540{
541#if defined(NETWARE) || defined(FAKE_THREADS) || defined(I_MACH_CTHREADS)
542 Perl_croak_nocontext("cond_timedwait not supported on this platform");
543#else
544# ifdef WIN32
545 int got_it = 0;
546
547 ABS2RELMILLI(abs);
548
549 cond->waiters++;
550 MUTEX_UNLOCK(mut);
551 /* See comments in win32/win32thread.h COND_WAIT vis-a-vis race */
028f8eaa 552 switch (WaitForSingleObject(cond->sem, (DWORD)abs)) {
a0e036c1 553 case WAIT_OBJECT_0: got_it = 1; break;
554 case WAIT_TIMEOUT: break;
555 default:
556 /* WAIT_FAILED? WAIT_ABANDONED? others? */
557 Perl_croak_nocontext("panic: cond_timedwait (%ld)",GetLastError());
558 break;
559 }
560 MUTEX_LOCK(mut);
2666606c 561 cond->waiters--;
a0e036c1 562 return got_it;
563# else
564# ifdef OS2
565 int rc, got_it = 0;
566 STRLEN n_a;
567
568 ABS2RELMILLI(abs);
569
570 if ((rc = DosResetEventSem(*cond,&n_a)) && (rc != ERROR_ALREADY_RESET))
571 Perl_rc = rc, croak_with_os2error("panic: cond_timedwait-reset");
572 MUTEX_UNLOCK(mut);
573 if (CheckOSError(DosWaitEventSem(*cond,abs))
574 && (rc != ERROR_INTERRUPT))
575 croak_with_os2error("panic: cond_timedwait");
576 if (rc == ERROR_INTERRUPT) errno = EINTR;
577 MUTEX_LOCK(mut);
578 return got_it;
579# else /* hope you're I_PTHREAD! */
580 struct timespec ts;
581 int got_it = 0;
582
583 ts.tv_sec = (long)abs;
584 abs -= (NV)ts.tv_sec;
585 ts.tv_nsec = (long)(abs * 1000000000.0);
586
587 switch (pthread_cond_timedwait(cond, mut, &ts)) {
588 case 0: got_it = 1; break;
589 case ETIMEDOUT: break;
590 default:
591 Perl_croak_nocontext("panic: cond_timedwait");
592 break;
593 }
594 return got_it;
595# endif /* OS2 */
596# endif /* WIN32 */
597#endif /* NETWARE || FAKE_THREADS || I_MACH_CTHREADS */
598}
599
dad67c22 600
601/* given a shared RV, copy it's value to a private RV, also coping the
602 * object status of the referent.
603 * If the private side is already an appropriate RV->SV combination, keep
604 * it if possible.
605 */
606
607STATIC void
608S_get_RV(pTHX_ SV *sv, SV *ssv) {
609 SV *sobj = SvRV(ssv);
610 SV *obj;
611 if ( ! ( SvROK(sv)
612 && ((obj = SvRV(sv)))
613 && (Perl_sharedsv_find(aTHX_ obj) == sobj)
614 && (SvTYPE(obj) == SvTYPE(sobj))
615 )
616 )
617 {
618 /* can't reuse obj */
619 if (SvROK(sv)) {
620 SvREFCNT_dec(SvRV(sv));
621 }
622 else {
623 assert(SvTYPE(sv) >= SVt_RV);
624 sv_setsv_nomg(sv, &PL_sv_undef);
625 SvROK_on(sv);
626 }
627 obj = S_sharedsv_new_private(aTHX_ SvRV(ssv));
628 SvRV_set(sv, obj);
629 }
630
631 if (SvOBJECT(obj)) {
632 /* remove any old blessing */
633 SvREFCNT_dec(SvSTASH(obj));
634 SvOBJECT_off(obj);
635 }
636 if (SvOBJECT(sobj)) {
637 /* add any new old blessing */
638 STRLEN len;
639 char* stash_ptr = SvPV((SV*) SvSTASH(sobj), len);
640 HV* stash = gv_stashpvn(stash_ptr, len, TRUE);
641 SvOBJECT_on(obj);
642 SvSTASH_set(obj, (HV*)SvREFCNT_inc(stash));
643 }
644}
645
646
29ecdb6f 647/* ------------ PERL_MAGIC_shared_scalar(n) functions -------------- */
648
649/* get magic for PERL_MAGIC_shared_scalar(n) */
68795e93 650
21312124 651int
652sharedsv_scalar_mg_get(pTHX_ SV *sv, MAGIC *mg)
68795e93 653{
29ecdb6f 654 SV *ssv = (SV *) mg->mg_ptr;
655 assert(ssv);
21312124 656
6d56dc1c 657 ENTER_LOCK;
29ecdb6f 658 if (SvROK(ssv)) {
dad67c22 659 S_get_RV(aTHX_ sv, ssv);
29ecdb6f 660 }
661 else {
662 sv_setsv_nomg(sv, ssv);
21312124 663 }
6d56dc1c 664 LEAVE_LOCK;
21312124 665 return 0;
666}
667
29ecdb6f 668/* copy the contents of a private SV to a shared SV:
669 * used by various mg_set()-type functions.
670 * Assumes lock is held */
671
6b85e4fe 672void
29ecdb6f 673sharedsv_scalar_store(pTHX_ SV *sv, SV *ssv)
21312124 674{
675 dTHXc;
21312124 676 bool allowed = TRUE;
29ecdb6f 677
678 assert(PL_sharedsv_lock.owner == aTHX);
21312124 679 if (SvROK(sv)) {
29ecdb6f 680 SV *obj = SvRV(sv);
681 SV *sobj = Perl_sharedsv_find(aTHX_ obj);
682 if (sobj) {
a446a88f 683 SHARED_CONTEXT;
29ecdb6f 684 SvUPGRADE(ssv, SVt_RV);
685 sv_setsv_nomg(ssv, &PL_sv_undef);
686
687 SvRV_set(ssv, SvREFCNT_inc(sobj));
688 SvROK_on(ssv);
689 if(SvOBJECT(obj)) {
690 SV* fake_stash = newSVpv(HvNAME_get(SvSTASH(obj)),0);
691 SvOBJECT_on(sobj);
692 SvSTASH_set(sobj, (HV*)fake_stash);
5c360ac5 693 }
a446a88f 694 CALLER_CONTEXT;
21312124 695 }
696 else {
697 allowed = FALSE;
698 }
699 }
700 else {
5c360ac5 701 SvTEMP_off(sv);
a446a88f 702 SHARED_CONTEXT;
29ecdb6f 703 sv_setsv_nomg(ssv, sv);
5c360ac5 704 if(SvOBJECT(sv)) {
bfcb3514 705 SV* fake_stash = newSVpv(HvNAME_get(SvSTASH(sv)),0);
29ecdb6f 706 SvOBJECT_on(ssv);
707 SvSTASH_set(ssv, (HV*)fake_stash);
5c360ac5 708 }
a446a88f 709 CALLER_CONTEXT;
21312124 710 }
21312124 711 if (!allowed) {
712 Perl_croak(aTHX_ "Invalid value for shared scalar");
713 }
6b85e4fe 714}
715
29ecdb6f 716/* set magic for PERL_MAGIC_shared_scalar(n) */
717
6b85e4fe 718int
719sharedsv_scalar_mg_set(pTHX_ SV *sv, MAGIC *mg)
720{
29ecdb6f 721 SV *ssv = (SV*)(mg->mg_ptr);
722 assert(ssv);
6b85e4fe 723 ENTER_LOCK;
29ecdb6f 724 if (SvTYPE(ssv) < SvTYPE(sv)) {
725 dTHXc;
726 SHARED_CONTEXT;
727 sv_upgrade(ssv, SvTYPE(sv));
728 CALLER_CONTEXT;
729 }
730 sharedsv_scalar_store(aTHX_ sv, ssv);
6b85e4fe 731 LEAVE_LOCK;
21312124 732 return 0;
68795e93 733}
734
29ecdb6f 735/* free magic for PERL_MAGIC_shared_scalar(n) */
a446a88f 736
737int
29ecdb6f 738sharedsv_scalar_mg_free(pTHX_ SV *sv, MAGIC *mg)
a446a88f 739{
29ecdb6f 740 S_sharedsv_dec(aTHX_ (SV*)mg->mg_ptr);
21312124 741 return 0;
742}
68795e93 743
744/*
29ecdb6f 745 * Called during cloning of PERL_MAGIC_shared_scalar(n) magic in new thread
21312124 746 */
747int
748sharedsv_scalar_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
749{
29ecdb6f 750 SvREFCNT_inc(mg->mg_ptr);
21312124 751 return 0;
752}
68795e93 753
a5063e7c 754/*
755 * Called during local $shared
756 */
757int
758sharedsv_scalar_mg_local(pTHX_ SV* nsv, MAGIC *mg)
759{
760 MAGIC *nmg;
29ecdb6f 761 SV *ssv = (SV *) mg->mg_ptr;
762 if (ssv) {
a5063e7c 763 ENTER_LOCK;
29ecdb6f 764 SvREFCNT_inc(ssv);
a5063e7c 765 LEAVE_LOCK;
766 }
767 nmg = sv_magicext(nsv, mg->mg_obj, mg->mg_type, mg->mg_virtual,
768 mg->mg_ptr, mg->mg_len);
769 nmg->mg_flags = mg->mg_flags;
770 nmg->mg_private = mg->mg_private;
771
772 return 0;
773}
774
21312124 775MGVTBL sharedsv_scalar_vtbl = {
776 sharedsv_scalar_mg_get, /* get */
777 sharedsv_scalar_mg_set, /* set */
778 0, /* len */
29ecdb6f 779 0, /* clear */
21312124 780 sharedsv_scalar_mg_free, /* free */
781 0, /* copy */
a5063e7c 782 sharedsv_scalar_mg_dup, /* dup */
783 sharedsv_scalar_mg_local /* local */
21312124 784};
68795e93 785
29ecdb6f 786/* ------------ PERL_MAGIC_tiedelem(p) functions -------------- */
787
788/* get magic for PERL_MAGIC_tiedelem(p) */
789
21312124 790int
791sharedsv_elem_mg_FETCH(pTHX_ SV *sv, MAGIC *mg)
68795e93 792{
21312124 793 dTHXc;
29ecdb6f 794 SV *saggregate = S_sharedsv_from_obj(aTHX_ mg->mg_obj);
21312124 795 SV** svp;
796
6b85e4fe 797 ENTER_LOCK;
29ecdb6f 798 if (SvTYPE(saggregate) == SVt_PVAV) {
a446a88f 799 assert ( mg->mg_ptr == 0 );
6b85e4fe 800 SHARED_CONTEXT;
29ecdb6f 801 svp = av_fetch((AV*) saggregate, mg->mg_len, 0);
21312124 802 }
803 else {
6b85e4fe 804 char *key = mg->mg_ptr;
805 STRLEN len = mg->mg_len;
a446a88f 806 assert ( mg->mg_ptr != 0 );
6b85e4fe 807 if (mg->mg_len == HEf_SVKEY) {
808 key = SvPV((SV *) mg->mg_ptr, len);
809 }
810 SHARED_CONTEXT;
29ecdb6f 811 svp = hv_fetch((HV*) saggregate, key, len, 0);
21312124 812 }
6b85e4fe 813 CALLER_CONTEXT;
21312124 814 if (svp) {
6b85e4fe 815 /* Exists in the array */
abdac9fa 816 if (SvROK(*svp)) {
dad67c22 817 S_get_RV(aTHX_ sv, *svp);
abdac9fa 818 }
819 else {
29ecdb6f 820 /* XXX can this branch ever happen? DAPM */
821 /* XXX assert("no such branch"); */
822 Perl_sharedsv_associate(aTHX_ sv, *svp);
abdac9fa 823 sv_setsv(sv, *svp);
824 }
21312124 825 }
6b85e4fe 826 else {
827 /* Not in the array */
828 sv_setsv(sv, &PL_sv_undef);
68795e93 829 }
6b85e4fe 830 LEAVE_LOCK;
21312124 831 return 0;
68795e93 832}
833
29ecdb6f 834/* set magic for PERL_MAGIC_tiedelem(p) */
835
21312124 836int
837sharedsv_elem_mg_STORE(pTHX_ SV *sv, MAGIC *mg)
838{
839 dTHXc;
29ecdb6f 840 SV *saggregate = S_sharedsv_from_obj(aTHX_ mg->mg_obj);
6b85e4fe 841 SV **svp;
21312124 842 /* Theory - SV itself is magically shared - and we have ordered the
843 magic such that by the time we get here it has been stored
844 to its shared counterpart
845 */
6d56dc1c 846 ENTER_LOCK;
29ecdb6f 847 assert(saggregate);
848 if (SvTYPE(saggregate) == SVt_PVAV) {
6b85e4fe 849 assert ( mg->mg_ptr == 0 );
850 SHARED_CONTEXT;
29ecdb6f 851 svp = av_fetch((AV*) saggregate, mg->mg_len, 1);
21312124 852 }
853 else {
6b85e4fe 854 char *key = mg->mg_ptr;
855 STRLEN len = mg->mg_len;
856 assert ( mg->mg_ptr != 0 );
857 if (mg->mg_len == HEf_SVKEY)
858 key = SvPV((SV *) mg->mg_ptr, len);
859 SHARED_CONTEXT;
29ecdb6f 860 svp = hv_fetch((HV*) saggregate, key, len, 1);
21312124 861 }
6b85e4fe 862 CALLER_CONTEXT;
29ecdb6f 863 Perl_sharedsv_associate(aTHX_ sv, *svp);
864 sharedsv_scalar_store(aTHX_ sv, *svp);
6b85e4fe 865 LEAVE_LOCK;
21312124 866 return 0;
867}
68795e93 868
29ecdb6f 869/* clear magic for PERL_MAGIC_tiedelem(p) */
870
21312124 871int
872sharedsv_elem_mg_DELETE(pTHX_ SV *sv, MAGIC *mg)
68795e93 873{
21312124 874 dTHXc;
057e91b3 875 MAGIC *shmg;
29ecdb6f 876 SV *saggregate = S_sharedsv_from_obj(aTHX_ mg->mg_obj);
6b85e4fe 877 ENTER_LOCK;
878 sharedsv_elem_mg_FETCH(aTHX_ sv, mg);
057e91b3 879 if ((shmg = mg_find(sv, PERL_MAGIC_shared_scalar)))
880 sharedsv_scalar_mg_get(aTHX_ sv, shmg);
29ecdb6f 881 if (SvTYPE(saggregate) == SVt_PVAV) {
6b85e4fe 882 SHARED_CONTEXT;
29ecdb6f 883 av_delete((AV*) saggregate, mg->mg_len, G_DISCARD);
68795e93 884 }
21312124 885 else {
6b85e4fe 886 char *key = mg->mg_ptr;
887 STRLEN len = mg->mg_len;
888 assert ( mg->mg_ptr != 0 );
889 if (mg->mg_len == HEf_SVKEY)
890 key = SvPV((SV *) mg->mg_ptr, len);
891 SHARED_CONTEXT;
29ecdb6f 892 hv_delete((HV*) saggregate, key, len, G_DISCARD);
21312124 893 }
6b85e4fe 894 CALLER_CONTEXT;
895 LEAVE_LOCK;
21312124 896 return 0;
897}
898
29ecdb6f 899/* Called during cloning of PERL_MAGIC_tiedelem(p) magic in new
900 * thread */
901
21312124 902int
903sharedsv_elem_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
904{
29ecdb6f 905 SvREFCNT_inc(S_sharedsv_from_obj(aTHX_ mg->mg_obj));
906 assert(mg->mg_flags & MGf_DUP);
21312124 907 return 0;
908}
909
910MGVTBL sharedsv_elem_vtbl = {
911 sharedsv_elem_mg_FETCH, /* get */
912 sharedsv_elem_mg_STORE, /* set */
913 0, /* len */
914 sharedsv_elem_mg_DELETE, /* clear */
60c5c75c 915 0, /* free */
21312124 916 0, /* copy */
a5063e7c 917 sharedsv_elem_mg_dup, /* dup */
918 0 /* local */
21312124 919};
920
29ecdb6f 921/* ------------ PERL_MAGIC_tied(P) functions -------------- */
922
923/* len magic for PERL_MAGIC_tied(P) */
924
21312124 925U32
926sharedsv_array_mg_FETCHSIZE(pTHX_ SV *sv, MAGIC *mg)
927{
928 dTHXc;
29ecdb6f 929 SV *ssv = (SV *) mg->mg_ptr;
21312124 930 U32 val;
931 SHARED_EDIT;
29ecdb6f 932 if (SvTYPE(ssv) == SVt_PVAV) {
933 val = av_len((AV*) ssv);
21312124 934 }
935 else {
936 /* not actually defined by tie API but ... */
29ecdb6f 937 val = HvKEYS((HV*) ssv);
21312124 938 }
939 SHARED_RELEASE;
940 return val;
941}
942
29ecdb6f 943/* clear magic for PERL_MAGIC_tied(P) */
944
21312124 945int
946sharedsv_array_mg_CLEAR(pTHX_ SV *sv, MAGIC *mg)
947{
948 dTHXc;
29ecdb6f 949 SV *ssv = (SV *) mg->mg_ptr;
21312124 950 SHARED_EDIT;
29ecdb6f 951 if (SvTYPE(ssv) == SVt_PVAV) {
952 av_clear((AV*) ssv);
21312124 953 }
954 else {
29ecdb6f 955 hv_clear((HV*) ssv);
21312124 956 }
957 SHARED_RELEASE;
958 return 0;
959}
960
29ecdb6f 961/* free magic for PERL_MAGIC_tied(P) */
962
21312124 963int
964sharedsv_array_mg_free(pTHX_ SV *sv, MAGIC *mg)
965{
29ecdb6f 966 S_sharedsv_dec(aTHX_ (SV*)mg->mg_ptr);
21312124 967 return 0;
68795e93 968}
969
970/*
29ecdb6f 971 * copy magic for PERL_MAGIC_tied(P)
21312124 972 * This is called when perl is about to access an element of
973 * the array -
974 */
975int
976sharedsv_array_mg_copy(pTHX_ SV *sv, MAGIC* mg,
977 SV *nsv, const char *name, int namlen)
978{
21312124 979 MAGIC *nmg = sv_magicext(nsv,mg->mg_obj,
980 toLOWER(mg->mg_type),&sharedsv_elem_vtbl,
981 name, namlen);
982 nmg->mg_flags |= MGf_DUP;
21312124 983 return 1;
984}
985
29ecdb6f 986/* Called during cloning of PERL_MAGIC_tied(P) magic in new thread */
987
21312124 988int
989sharedsv_array_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
990{
29ecdb6f 991 SvREFCNT_inc((SV*)mg->mg_ptr);
992 assert(mg->mg_flags & MGf_DUP);
21312124 993 return 0;
994}
995
996MGVTBL sharedsv_array_vtbl = {
997 0, /* get */
998 0, /* set */
999 sharedsv_array_mg_FETCHSIZE, /* len */
1000 sharedsv_array_mg_CLEAR, /* clear */
1001 sharedsv_array_mg_free, /* free */
1002 sharedsv_array_mg_copy, /* copy */
a5063e7c 1003 sharedsv_array_mg_dup, /* dup */
1004 0 /* local */
21312124 1005};
1006
1007=for apidoc sharedsv_unlock
68795e93 1008
1009Recursively unlocks a shared sv.
1010
21312124 1011=cut
68795e93 1012
1013void
29ecdb6f 1014Perl_sharedsv_unlock(pTHX_ SV *ssv)
68795e93 1015{
29ecdb6f 1016 user_lock *ul = S_get_userlock(aTHX_ ssv, 0);
1017 assert(ul);
1018 recursive_lock_release(aTHX_ &ul->lock);
68795e93 1019}
1020
21312124 1021=for apidoc sharedsv_lock
68795e93 1022
21312124 1023Recursive locks on a sharedsv.
1024Locks are dynamically scoped at the level of the first lock.
68795e93 1025
21312124 1026=cut
68795e93 1027
1028void
29ecdb6f 1029Perl_sharedsv_lock(pTHX_ SV *ssv)
68795e93 1030{
29ecdb6f 1031 user_lock *ul;
21312124 1032 if (!ssv)
1033 return;
29ecdb6f 1034 ul = S_get_userlock(aTHX_ ssv, 1);
1035 recursive_lock_acquire(aTHX_ &ul->lock, __FILE__, __LINE__);
68795e93 1036}
1037
afe38520 1038/* handles calls from lock() builtin via PL_lockhook */
1039
21312124 1040void
1041Perl_sharedsv_locksv(pTHX_ SV *sv)
1042{
29ecdb6f 1043 SV *ssv;
afe38520 1044
1045 if(SvROK(sv))
1046 sv = SvRV(sv);
29ecdb6f 1047 ssv = Perl_sharedsv_find(aTHX_ sv);
1048 if(!ssv)
afe38520 1049 croak("lock can only be used on shared values");
29ecdb6f 1050 Perl_sharedsv_lock(aTHX_ ssv);
b050c948 1051}
1052
21312124 1053=head1 Shared SV Functions
b050c948 1054
21312124 1055=for apidoc sharedsv_init
b050c948 1056
21312124 1057Saves a space for keeping SVs wider than an interpreter,
b050c948 1058
21312124 1059=cut
1060
1061void
1062Perl_sharedsv_init(pTHX)
1063{
1064 dTHXc;
1065 /* This pair leaves us in shared context ... */
1066 PL_sharedsv_space = perl_alloc();
1067 perl_construct(PL_sharedsv_space);
1068 CALLER_CONTEXT;
6d56dc1c 1069 recursive_lock_init(aTHX_ &PL_sharedsv_lock);
21312124 1070 PL_lockhook = &Perl_sharedsv_locksv;
1071 PL_sharehook = &Perl_sharedsv_share;
b050c948 1072}
1073
73e09c8f 1074#endif /* USE_ITHREADS */
1075
21312124 1076MODULE = threads::shared PACKAGE = threads::shared::tie
b050c948 1077
21312124 1078PROTOTYPES: DISABLE
b050c948 1079
73e09c8f 1080#ifdef USE_ITHREADS
6b85e4fe 1081
21312124 1082void
29ecdb6f 1083PUSH(SV *obj, ...)
21312124 1084CODE:
1085 dTHXc;
29ecdb6f 1086 SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
21312124 1087 int i;
21312124 1088 for(i = 1; i < items; i++) {
1089 SV* tmp = newSVsv(ST(i));
29ecdb6f 1090 SV *stmp;
6d56dc1c 1091 ENTER_LOCK;
29ecdb6f 1092 stmp = S_sharedsv_new_shared(aTHX_ tmp);
1093 sharedsv_scalar_store(aTHX_ tmp, stmp);
21312124 1094 SHARED_CONTEXT;
29ecdb6f 1095 av_push((AV*) sobj, stmp);
1096 SvREFCNT_inc(stmp);
a446a88f 1097 SHARED_RELEASE;
21312124 1098 SvREFCNT_dec(tmp);
1099 }
b050c948 1100
21312124 1101void
29ecdb6f 1102UNSHIFT(SV *obj, ...)
21312124 1103CODE:
1104 dTHXc;
29ecdb6f 1105 SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
21312124 1106 int i;
6d56dc1c 1107 ENTER_LOCK;
21312124 1108 SHARED_CONTEXT;
29ecdb6f 1109 av_unshift((AV*)sobj, items - 1);
21312124 1110 CALLER_CONTEXT;
1111 for(i = 1; i < items; i++) {
29ecdb6f 1112 SV *tmp = newSVsv(ST(i));
1113 SV *stmp = S_sharedsv_new_shared(aTHX_ tmp);
1114 sharedsv_scalar_store(aTHX_ tmp, stmp);
21312124 1115 SHARED_CONTEXT;
29ecdb6f 1116 av_store((AV*) sobj, i - 1, stmp);
1117 SvREFCNT_inc(stmp);
21312124 1118 CALLER_CONTEXT;
1119 SvREFCNT_dec(tmp);
1120 }
6d56dc1c 1121 LEAVE_LOCK;
b050c948 1122
21312124 1123void
29ecdb6f 1124POP(SV *obj)
21312124 1125CODE:
1126 dTHXc;
29ecdb6f 1127 SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1128 SV* ssv;
6d56dc1c 1129 ENTER_LOCK;
21312124 1130 SHARED_CONTEXT;
29ecdb6f 1131 ssv = av_pop((AV*)sobj);
21312124 1132 CALLER_CONTEXT;
9b018978 1133 ST(0) = sv_newmortal();
29ecdb6f 1134 Perl_sharedsv_associate(aTHX_ ST(0), ssv);
1135 SvREFCNT_dec(ssv);
6d56dc1c 1136 LEAVE_LOCK;
21312124 1137 XSRETURN(1);
b050c948 1138
21312124 1139void
29ecdb6f 1140SHIFT(SV *obj)
21312124 1141CODE:
1142 dTHXc;
29ecdb6f 1143 SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
1144 SV* ssv;
6d56dc1c 1145 ENTER_LOCK;
21312124 1146 SHARED_CONTEXT;
29ecdb6f 1147 ssv = av_shift((AV*)sobj);
21312124 1148 CALLER_CONTEXT;
9b018978 1149 ST(0) = sv_newmortal();
29ecdb6f 1150 Perl_sharedsv_associate(aTHX_ ST(0), ssv);
1151 SvREFCNT_dec(ssv);
6d56dc1c 1152 LEAVE_LOCK;
21312124 1153 XSRETURN(1);
b050c948 1154
21312124 1155void
29ecdb6f 1156EXTEND(SV *obj, IV count)
21312124 1157CODE:
1158 dTHXc;
29ecdb6f 1159 SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
21312124 1160 SHARED_EDIT;
29ecdb6f 1161 av_extend((AV*)sobj, count);
21312124 1162 SHARED_RELEASE;
b050c948 1163
21312124 1164void
29ecdb6f 1165STORESIZE(SV *obj,IV count)
6b85e4fe 1166CODE:
1167 dTHXc;
29ecdb6f 1168 SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
6b85e4fe 1169 SHARED_EDIT;
29ecdb6f 1170 av_fill((AV*) sobj, count);
6b85e4fe 1171 SHARED_RELEASE;
1172
1173
1174
1175
1176void
29ecdb6f 1177EXISTS(SV *obj, SV *index)
21312124 1178CODE:
1179 dTHXc;
29ecdb6f 1180 SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
21312124 1181 bool exists;
29ecdb6f 1182 if (SvTYPE(sobj) == SVt_PVAV) {
680c9d89 1183 SHARED_EDIT;
29ecdb6f 1184 exists = av_exists((AV*) sobj, SvIV(index));
21312124 1185 }
1186 else {
6b85e4fe 1187 STRLEN len;
1188 char *key = SvPV(index,len);
680c9d89 1189 SHARED_EDIT;
29ecdb6f 1190 exists = hv_exists((HV*) sobj, key, len);
21312124 1191 }
1192 SHARED_RELEASE;
1193 ST(0) = (exists) ? &PL_sv_yes : &PL_sv_no;
1194 XSRETURN(1);
b050c948 1195
1196
1197void
29ecdb6f 1198FIRSTKEY(SV *obj)
21312124 1199CODE:
1200 dTHXc;
29ecdb6f 1201 SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
21312124 1202 char* key = NULL;
1203 I32 len = 0;
1204 HE* entry;
6d56dc1c 1205 ENTER_LOCK;
21312124 1206 SHARED_CONTEXT;
29ecdb6f 1207 hv_iterinit((HV*) sobj);
1208 entry = hv_iternext((HV*) sobj);
21312124 1209 if (entry) {
1210 key = hv_iterkey(entry,&len);
1211 CALLER_CONTEXT;
1212 ST(0) = sv_2mortal(newSVpv(key, len));
1213 } else {
1214 CALLER_CONTEXT;
1215 ST(0) = &PL_sv_undef;
1216 }
6d56dc1c 1217 LEAVE_LOCK;
21312124 1218 XSRETURN(1);
b050c948 1219
866fba46 1220void
29ecdb6f 1221NEXTKEY(SV *obj, SV *oldkey)
21312124 1222CODE:
1223 dTHXc;
29ecdb6f 1224 SV *sobj = S_sharedsv_from_obj(aTHX_ obj);
21312124 1225 char* key = NULL;
1226 I32 len = 0;
1227 HE* entry;
6d56dc1c 1228 ENTER_LOCK;
21312124 1229 SHARED_CONTEXT;
29ecdb6f 1230 entry = hv_iternext((HV*) sobj);
6b85e4fe 1231 if (entry) {
21312124 1232 key = hv_iterkey(entry,&len);
1233 CALLER_CONTEXT;
1234 ST(0) = sv_2mortal(newSVpv(key, len));
1235 } else {
1236 CALLER_CONTEXT;
1237 ST(0) = &PL_sv_undef;
1238 }
6d56dc1c 1239 LEAVE_LOCK;
21312124 1240 XSRETURN(1);
1241
1242MODULE = threads::shared PACKAGE = threads::shared
1243
1244PROTOTYPES: ENABLE
866fba46 1245
68795e93 1246void
9c4972d9 1247_id(SV *ref)
1248 PROTOTYPE: \[$@%]
1249CODE:
29ecdb6f 1250 SV *ssv;
afe38520 1251 ref = SvRV(ref);
9c4972d9 1252 if(SvROK(ref))
1253 ref = SvRV(ref);
29ecdb6f 1254 if( (ssv = Perl_sharedsv_find(aTHX_ ref)) ){
1255 ST(0) = sv_2mortal(newSViv(PTR2IV(ssv)));
9c4972d9 1256 XSRETURN(1);
1257 }
1258 XSRETURN_UNDEF;
1259
1260
1261void
6b85e4fe 1262_refcnt(SV *ref)
a446a88f 1263 PROTOTYPE: \[$@%]
1264CODE:
29ecdb6f 1265 SV *ssv;
afe38520 1266 ref = SvRV(ref);
a446a88f 1267 if(SvROK(ref))
1268 ref = SvRV(ref);
29ecdb6f 1269 if( (ssv = Perl_sharedsv_find(aTHX_ ref)) ) {
1270 ST(0) = sv_2mortal(newSViv(SvREFCNT(ssv)));
a446a88f 1271 XSRETURN(1);
a446a88f 1272 }
1273 else {
436c6dd3 1274 Perl_warn(aTHX_ "%" SVf " is not shared",ST(0));
a446a88f 1275 }
1276 XSRETURN_UNDEF;
1277
caf25f3b 1278SV*
a446a88f 1279share(SV *ref)
1280 PROTOTYPE: \[$@%]
1281 CODE:
56fcff86 1282 if(!SvROK(ref))
1283 Perl_croak(aTHX_ "Argument to share needs to be passed as ref");
afe38520 1284 ref = SvRV(ref);
a446a88f 1285 if(SvROK(ref))
1286 ref = SvRV(ref);
38875929 1287 Perl_sharedsv_share(aTHX_ ref);
caf25f3b 1288 RETVAL = newRV(ref);
1289 OUTPUT:
1290 RETVAL
a446a88f 1291
1292void
21312124 1293lock_enabled(SV *ref)
ce127893 1294 PROTOTYPE: \[$@%]
6f942b98 1295 CODE:
29ecdb6f 1296 SV *ssv;
56fcff86 1297 if(!SvROK(ref))
1298 Perl_croak(aTHX_ "Argument to lock needs to be passed as ref");
afe38520 1299 ref = SvRV(ref);
6f942b98 1300 if(SvROK(ref))
1301 ref = SvRV(ref);
29ecdb6f 1302 ssv = Perl_sharedsv_find(aTHX_ ref);
1303 if(!ssv)
21312124 1304 croak("lock can only be used on shared values");
29ecdb6f 1305 Perl_sharedsv_lock(aTHX_ ssv);
6f942b98 1306
1307void
a0e036c1 1308cond_wait_enabled(SV *ref_cond, SV *ref_lock = 0)
1309 PROTOTYPE: \[$@%];\[$@%]
1310 PREINIT:
29ecdb6f 1311 SV *ssv;
a0e036c1 1312 perl_cond* user_condition;
6f942b98 1313 int locks;
a0e036c1 1314 int same = 0;
29ecdb6f 1315 user_lock *ul;
a0e036c1 1316
1317 CODE:
1318 if (!ref_lock || ref_lock == ref_cond) same = 1;
1319
1320 if(!SvROK(ref_cond))
56fcff86 1321 Perl_croak(aTHX_ "Argument to cond_wait needs to be passed as ref");
a0e036c1 1322 ref_cond = SvRV(ref_cond);
1323 if(SvROK(ref_cond))
1324 ref_cond = SvRV(ref_cond);
29ecdb6f 1325 ssv = Perl_sharedsv_find(aTHX_ ref_cond);
1326 if(!ssv)
6f942b98 1327 croak("cond_wait can only be used on shared values");
29ecdb6f 1328 ul = S_get_userlock(aTHX_ ssv, 1);
a0e036c1 1329
29ecdb6f 1330 user_condition = &ul->user_cond;
a0e036c1 1331 if (! same) {
1332 if (!SvROK(ref_lock))
1333 Perl_croak(aTHX_ "cond_wait lock needs to be passed as ref");
1334 ref_lock = SvRV(ref_lock);
1335 if (SvROK(ref_lock)) ref_lock = SvRV(ref_lock);
29ecdb6f 1336 ssv = Perl_sharedsv_find(aTHX_ ref_lock);
1337 if (!ssv)
a0e036c1 1338 croak("cond_wait lock must be a shared value");
29ecdb6f 1339 ul = S_get_userlock(aTHX_ ssv, 1);
a0e036c1 1340 }
29ecdb6f 1341 if(ul->lock.owner != aTHX)
6f942b98 1342 croak("You need a lock before you can cond_wait");
6d56dc1c 1343 /* Stealing the members of the lock object worries me - NI-S */
29ecdb6f 1344 MUTEX_LOCK(&ul->lock.mutex);
1345 ul->lock.owner = NULL;
1346 locks = ul->lock.locks;
1347 ul->lock.locks = 0;
89661126 1348
1349 /* since we are releasing the lock here we need to tell other
1350 people that is ok to go ahead and use it */
29ecdb6f 1351 COND_SIGNAL(&ul->lock.cond);
1352 COND_WAIT(user_condition, &ul->lock.mutex);
1353 while(ul->lock.owner != NULL) {
a0e036c1 1354 /* OK -- must reacquire the lock */
29ecdb6f 1355 COND_WAIT(&ul->lock.cond, &ul->lock.mutex);
a0e036c1 1356 }
29ecdb6f 1357 ul->lock.owner = aTHX;
1358 ul->lock.locks = locks;
1359 MUTEX_UNLOCK(&ul->lock.mutex);
a0e036c1 1360
1361int
1362cond_timedwait_enabled(SV *ref_cond, double abs, SV *ref_lock = 0)
1363 PROTOTYPE: \[$@%]$;\[$@%]
1364 PREINIT:
29ecdb6f 1365 SV *ssv;
a0e036c1 1366 perl_cond* user_condition;
1367 int locks;
1368 int same = 0;
29ecdb6f 1369 user_lock *ul;
a0e036c1 1370
1371 CODE:
1372 if (!ref_lock || ref_cond == ref_lock) same = 1;
1373
1374 if(!SvROK(ref_cond))
1375 Perl_croak(aTHX_ "Argument to cond_timedwait needs to be passed as ref");
1376 ref_cond = SvRV(ref_cond);
1377 if(SvROK(ref_cond))
1378 ref_cond = SvRV(ref_cond);
29ecdb6f 1379 ssv = Perl_sharedsv_find(aTHX_ ref_cond);
1380 if(!ssv)
a0e036c1 1381 croak("cond_timedwait can only be used on shared values");
29ecdb6f 1382 ul = S_get_userlock(aTHX_ ssv, 1);
a0e036c1 1383
29ecdb6f 1384 user_condition = &ul->user_cond;
a0e036c1 1385 if (! same) {
1386 if (!SvROK(ref_lock))
1387 Perl_croak(aTHX_ "cond_timedwait lock needs to be passed as ref");
1388 ref_lock = SvRV(ref_lock);
1389 if (SvROK(ref_lock)) ref_lock = SvRV(ref_lock);
29ecdb6f 1390 ssv = Perl_sharedsv_find(aTHX_ ref_lock);
1391 if (!ssv)
a0e036c1 1392 croak("cond_timedwait lock must be a shared value");
29ecdb6f 1393 ul = S_get_userlock(aTHX_ ssv, 1);
a0e036c1 1394 }
29ecdb6f 1395 if(ul->lock.owner != aTHX)
a0e036c1 1396 croak("You need a lock before you can cond_wait");
1397
29ecdb6f 1398 MUTEX_LOCK(&ul->lock.mutex);
1399 ul->lock.owner = NULL;
1400 locks = ul->lock.locks;
1401 ul->lock.locks = 0;
a0e036c1 1402 /* since we are releasing the lock here we need to tell other
1403 people that is ok to go ahead and use it */
29ecdb6f 1404 COND_SIGNAL(&ul->lock.cond);
1405 RETVAL = Perl_sharedsv_cond_timedwait(user_condition, &ul->lock.mutex, abs);
1406 while (ul->lock.owner != NULL) {
a0e036c1 1407 /* OK -- must reacquire the lock... */
29ecdb6f 1408 COND_WAIT(&ul->lock.cond, &ul->lock.mutex);
a0e036c1 1409 }
29ecdb6f 1410 ul->lock.owner = aTHX;
1411 ul->lock.locks = locks;
1412 MUTEX_UNLOCK(&ul->lock.mutex);
6f942b98 1413
a0e036c1 1414 if (RETVAL == 0)
1415 XSRETURN_UNDEF;
1416 OUTPUT:
1417 RETVAL
1418
21312124 1419void
1420cond_signal_enabled(SV *ref)
ce127893 1421 PROTOTYPE: \[$@%]
6f942b98 1422 CODE:
29ecdb6f 1423 SV *ssv;
1424 user_lock *ul;
1425
56fcff86 1426 if(!SvROK(ref))
1427 Perl_croak(aTHX_ "Argument to cond_signal needs to be passed as ref");
afe38520 1428 ref = SvRV(ref);
6f942b98 1429 if(SvROK(ref))
1430 ref = SvRV(ref);
29ecdb6f 1431 ssv = Perl_sharedsv_find(aTHX_ ref);
1432 if(!ssv)
10532ef0 1433 croak("cond_signal can only be used on shared values");
29ecdb6f 1434 ul = S_get_userlock(aTHX_ ssv, 1);
1435 if (ckWARN(WARN_THREADS) && ul->lock.owner != aTHX)
38875929 1436 Perl_warner(aTHX_ packWARN(WARN_THREADS),
1437 "cond_signal() called on unlocked variable");
29ecdb6f 1438 COND_SIGNAL(&ul->user_cond);
6f942b98 1439
21312124 1440void
1441cond_broadcast_enabled(SV *ref)
ce127893 1442 PROTOTYPE: \[$@%]
6f942b98 1443 CODE:
29ecdb6f 1444 SV *ssv;
1445 user_lock *ul;
1446
56fcff86 1447 if(!SvROK(ref))
1448 Perl_croak(aTHX_ "Argument to cond_broadcast needs to be passed as ref");
afe38520 1449 ref = SvRV(ref);
6f942b98 1450 if(SvROK(ref))
1451 ref = SvRV(ref);
29ecdb6f 1452 ssv = Perl_sharedsv_find(aTHX_ ref);
1453 if(!ssv)
6f942b98 1454 croak("cond_broadcast can only be used on shared values");
29ecdb6f 1455 ul = S_get_userlock(aTHX_ ssv, 1);
1456 if (ckWARN(WARN_THREADS) && ul->lock.owner != aTHX)
38875929 1457 Perl_warner(aTHX_ packWARN(WARN_THREADS),
1458 "cond_broadcast() called on unlocked variable");
29ecdb6f 1459 COND_BROADCAST(&ul->user_cond);
b050c948 1460
5c360ac5 1461
1462SV*
1463bless(SV* ref, ...);
1464 PROTOTYPE: $;$
1465 CODE:
1466 {
1467 HV* stash;
29ecdb6f 1468 SV *ssv;
5c360ac5 1469 if (items == 1)
1470 stash = CopSTASH(PL_curcop);
1471 else {
29ecdb6f 1472 SV* classname = ST(1);
5c360ac5 1473 STRLEN len;
1474 char *ptr;
1475
29ecdb6f 1476 if (classname && !SvGMAGICAL(classname) &&
1477 !SvAMAGIC(classname) && SvROK(classname))
5c360ac5 1478 Perl_croak(aTHX_ "Attempt to bless into a reference");
29ecdb6f 1479 ptr = SvPV(classname,len);
5c360ac5 1480 if (ckWARN(WARN_MISC) && len == 0)
1481 Perl_warner(aTHX_ packWARN(WARN_MISC),
1482 "Explicit blessing to '' (assuming package main)");
1483 stash = gv_stashpvn(ptr, len, TRUE);
1484 }
1485 SvREFCNT_inc(ref);
1486 (void)sv_bless(ref, stash);
1487 RETVAL = ref;
29ecdb6f 1488 ssv = Perl_sharedsv_find(aTHX_ ref);
1489 if(ssv) {
5c360ac5 1490 dTHXc;
1491 ENTER_LOCK;
1492 SHARED_CONTEXT;
1493 {
bfcb3514 1494 SV* fake_stash = newSVpv(HvNAME_get(stash),0);
29ecdb6f 1495 (void)sv_bless(ssv,(HV*)fake_stash);
5c360ac5 1496 }
1497 CALLER_CONTEXT;
1498 LEAVE_LOCK;
1499 }
1500 }
1501 OUTPUT:
1502 RETVAL
1503
73e09c8f 1504#endif /* USE_ITHREADS */
1505
68795e93 1506BOOT:
1507{
73e09c8f 1508#ifdef USE_ITHREADS
68795e93 1509 Perl_sharedsv_init(aTHX);
73e09c8f 1510#endif /* USE_ITHREADS */
68795e93 1511}