		/*
		 * This file was generated automatically by ExtUtils::ParseXS version 2.10 from the
		 * contents of shared.xs. Do not edit this file, edit shared.xs instead.
		 *
		 *	ANY CHANGES MADE HERE WILL BE LOST! 
		 *
		 */
		
		#line 1 "shared.xs"
		/*    shared.xs
		 *
		 *    Copyright (c) 2001-2002, Larry Wall
		 *
		 *    You may distribute under the terms of either the GNU General Public
		 *    License or the Artistic License, as specified in the README file.
		 *
		 * "Hand any two wizards a piece of rope and they would instinctively pull in
		 * opposite directions."
		 *                         --Sourcery
		 *
		 * Contributed by Arthur Bergman arthur@contiller.se
		 * pulled in the (an)other direction by Nick Ing-Simmons nick@ing-simmons.net
		 */
		
		#define PERL_NO_GET_CONTEXT
		#include "EXTERN.h"
		#include "perl.h"
		#include "XSUB.h"
		
		#ifdef USE_ITHREADS
		
		#define SHAREDSvPTR(a)      ((a)->sv)
		
		/*
		 * The shared things need an intepreter to live in ...
		 */
		PerlInterpreter *PL_sharedsv_space;             /* The shared sv space */
		/* To access shared space we fake aTHX in this scope and thread's context */
		
		/* bug #24255: we include ENTER+SAVETMPS/FREETMPS+LEAVE with
		 * SHARED_CONTEXT/CALLER_CONTEXT macros, so that any mortals etc created
		 * while in the shared interpreter context don't languish */
		
		#define SHARED_CONTEXT \
		    STMT_START {					\
			PERL_SET_CONTEXT((aTHX = PL_sharedsv_space));	\
			ENTER;						\
			SAVETMPS;					\
		    } STMT_END
		
		/* So we need a way to switch back to the caller's context... */
		/* So we declare _another_ copy of the aTHX variable ... */
		#define dTHXc PerlInterpreter *caller_perl = aTHX
		
		/* and use it to switch back */
		#define CALLER_CONTEXT					\
		    STMT_START {					\
		    	FREETMPS;					\
			LEAVE;						\
			PERL_SET_CONTEXT((aTHX = caller_perl));		\
		    } STMT_END
		
		/*
		 * Only one thread at a time is allowed to mess with shared space.
		 */
		
		typedef struct
		{
		 perl_mutex		 mutex;
		 PerlInterpreter	*owner;
		 I32			 locks;
		 perl_cond		 cond;
		#ifdef DEBUG_LOCKS
		 char *			 file;
		 int			 line;
		#endif
		} recursive_lock_t;
		
		recursive_lock_t PL_sharedsv_lock;       /* Mutex protecting the shared sv space */
		
		void
		recursive_lock_init(pTHX_ recursive_lock_t *lock)
		{
		    Zero(lock,1,recursive_lock_t);
		    MUTEX_INIT(&lock->mutex);
		    COND_INIT(&lock->cond);
		}
		
		void
		recursive_lock_destroy(pTHX_ recursive_lock_t *lock)
		{
		    MUTEX_DESTROY(&lock->mutex);
		    COND_DESTROY(&lock->cond);
		}
		
		void
		recursive_lock_release(pTHX_ recursive_lock_t *lock)
		{
		    MUTEX_LOCK(&lock->mutex);
		    if (lock->owner != aTHX) {
			MUTEX_UNLOCK(&lock->mutex);
		    }
		    else {
			if (--lock->locks == 0) {
			    lock->owner = NULL;
			    COND_SIGNAL(&lock->cond);
			}
		    }
		    MUTEX_UNLOCK(&lock->mutex);
		}
		
		void
		recursive_lock_acquire(pTHX_ recursive_lock_t *lock,char *file,int line)
		{
		    assert(aTHX);
		    MUTEX_LOCK(&lock->mutex);
		    if (lock->owner == aTHX) {
			lock->locks++;
		    }
		    else {
			while (lock->owner) {
		#ifdef DEBUG_LOCKS
			    Perl_warn(aTHX_ " %p waiting - owned by %p %s:%d\n",
				      aTHX, lock->owner, lock->file, lock->line);
		#endif
			    COND_WAIT(&lock->cond,&lock->mutex);
		        }
			lock->locks = 1;
			lock->owner = aTHX;
		#ifdef DEBUG_LOCKS
			lock->file  = file;
			lock->line  = line;
		#endif
		    }
		    MUTEX_UNLOCK(&lock->mutex);
		    SAVEDESTRUCTOR_X(recursive_lock_release,lock);
		}
		
		#define ENTER_LOCK         STMT_START { \
					      ENTER; \
					      recursive_lock_acquire(aTHX_ &PL_sharedsv_lock, __FILE__, __LINE__);   \
		                            } STMT_END
		
		#define LEAVE_LOCK       LEAVE
		
		
		/* A common idiom is to acquire access and switch in ... */
		#define SHARED_EDIT	    STMT_START {	\
						ENTER_LOCK;	\
						SHARED_CONTEXT;	\
					    } STMT_END
		
		/* then switch out and release access. */
		#define SHARED_RELEASE     STMT_START {	\
				                CALLER_CONTEXT;	\
						LEAVE_LOCK;	\
					    } STMT_END
		
		
		/*
		
		  Shared SV
		
		  Shared SV is a structure for keeping the backend storage
		  of shared svs.
		
		  Shared-ness really only needs the SV * - the rest is for locks.
		  (Which suggests further space optimization ... )
		
		*/
		
		typedef struct {
		    SV                 *sv;             /* The actual SV - in shared space */
		    recursive_lock_t    lock;
		    perl_cond           user_cond;      /* For user-level conditions */
		} shared_sv;
		
		/* The SV in shared-space has a back-pointer to the shared_sv
		   struct associated with it PERL_MAGIC_ext.
		
		   The vtable used has just one entry - when the SV goes away
		   we free the memory for the above.
		
		 */
		
		int
		sharedsv_shared_mg_free(pTHX_ SV *sv, MAGIC *mg)
		{
		    shared_sv *shared = (shared_sv *) mg->mg_ptr;
		    assert( aTHX == PL_sharedsv_space );
		    if (shared) {
			recursive_lock_destroy(aTHX_ &shared->lock);
			COND_DESTROY(&shared->user_cond);
			PerlMemShared_free(shared);
			mg->mg_ptr = NULL;
		    }
		    return 0;
		}
		
		MGVTBL sharedsv_shared_vtbl = {
		 0,				/* get */
		 0,				/* set */
		 0,				/* len */
		 0,				/* clear */
		 sharedsv_shared_mg_free,	/* free */
		 0,				/* copy */
		 0,				/* dup */
		};
		
		/* Access to shared things is heavily based on MAGIC - in mg.h/mg.c/sv.c sense */
		
		/* In any thread that has access to a shared thing there is a "proxy"
		   for it in its own space which has 'MAGIC' associated which accesses
		   the shared thing.
		 */
		
		MGVTBL sharedsv_scalar_vtbl;    /* scalars have this vtable */
		MGVTBL sharedsv_array_vtbl;     /* hashes and arrays have this - like 'tie' */
		MGVTBL sharedsv_elem_vtbl;      /* elements of hashes and arrays have this
						   _AS WELL AS_ the scalar magic */
		
		/* The sharedsv_elem_vtbl associates the element with the array/hash and
		   the sharedsv_scalar_vtbl associates it with the value
		 */
		
		
		/* Accessor to convert threads::shared::tie objects back shared_sv * */
		shared_sv *
		SV_to_sharedsv(pTHX_ SV *sv)
		{
		    shared_sv *shared = 0;
		    if (SvROK(sv))
		     {
		      shared = INT2PTR(shared_sv *, SvIV(SvRV(sv)));
		     }
		    return shared;
		}
		
		#if 0
		  "Skipped embedded POD."
		#endif
		#line 236 "shared.xs"
		
		shared_sv *
		Perl_sharedsv_find(pTHX_ SV *sv)
		{
		    MAGIC *mg;
		    if (SvTYPE(sv) >= SVt_PVMG) {
			switch(SvTYPE(sv)) {
			case SVt_PVAV:
			case SVt_PVHV:
			    if ((mg = mg_find(sv, PERL_MAGIC_tied))
				&& mg->mg_virtual == &sharedsv_array_vtbl) {
				return (shared_sv *) mg->mg_ptr;
			    }
			    break;
			default:
			    /* This should work for elements as well as they
			     * have scalar magic as well as their element magic
			     */
			    if ((mg = mg_find(sv, PERL_MAGIC_shared_scalar))
				&& mg->mg_virtual == &sharedsv_scalar_vtbl) {
				return (shared_sv *) mg->mg_ptr;
			    }
			    break;
			}
		    }
		    /* Just for tidyness of API also handle tie objects */
		    if (SvROK(sv) && sv_derived_from(sv, "threads::shared::tie")) {
			return SV_to_sharedsv(aTHX_ sv);
		    }
		    return NULL;
		}
		
		/*
		 *  Almost all the pain is in this routine.
		 *
		 */
		
		shared_sv *
		Perl_sharedsv_associate(pTHX_ SV **psv, SV *ssv, shared_sv *data)
		{
		    dTHXc;
		    MAGIC *mg = 0;
		    SV *sv    = (psv) ? *psv : Nullsv;
		
		    /* If we are asked for an private ops we need a thread */
		    assert ( aTHX !=  PL_sharedsv_space );
		
		    /* To avoid need for recursive locks require caller to hold lock */
		    assert ( PL_sharedsv_lock.owner == aTHX );
		
		    /* First try and get existing global data structure */
		
		    /* Try shared SV as 1st choice */
		    if (!data && ssv && SvTYPE(ssv) >= SVt_PVMG) {
			if( (mg = mg_find(ssv, PERL_MAGIC_ext)) ){
			    data = (shared_sv *) mg->mg_ptr;
			}
		    }
		
		    /* Next see if private SV is associated with something */
		    if (!data && sv) {
			data = Perl_sharedsv_find(aTHX_ sv);
		    }
		
		    /* If neither of those then create a new one */
		    if (!data) {
			    SHARED_CONTEXT;
			    if (!ssv) {
				ssv = newSV(0);
				SvREFCNT(ssv) = 0;
			    }
			    data = (shared_sv *) PerlMemShared_malloc(sizeof(shared_sv));
			    Zero(data,1,shared_sv);
			    SHAREDSvPTR(data) = ssv;
			    /* Tag shared side SV with data pointer */
			    sv_magicext(ssv, ssv, PERL_MAGIC_ext, &sharedsv_shared_vtbl,
				   (char *)data, 0);
			    recursive_lock_init(aTHX_ &data->lock);
			    COND_INIT(&data->user_cond);
			    CALLER_CONTEXT;
		    }
		
		    if (!ssv)
			ssv = SHAREDSvPTR(data);
		    if (!SHAREDSvPTR(data))
			SHAREDSvPTR(data) = ssv;
		
		    /* If we know type upgrade shared side SV */
		    if (sv && SvTYPE(ssv) < SvTYPE(sv)) {
			SHARED_CONTEXT;
			sv_upgrade(ssv, SvTYPE(*psv));
			if (SvTYPE(ssv) == SVt_PVAV)	/* #24061 */
			    AvREAL_on(ssv);
			CALLER_CONTEXT;
		    }
		
		    /* Now if requested allocate private SV */
		    if (psv && !sv) {
			*psv = sv = newSV(0);
		    }
		
		    /* Finally if private SV exists check and add magic */
		    if (sv) {
			MAGIC *mg = 0;
			if (SvTYPE(sv) < SvTYPE(ssv)) {
			    sv_upgrade(sv, SvTYPE(ssv));
			}
			switch(SvTYPE(sv)) {
			case SVt_PVAV:
			case SVt_PVHV:
			    if (!(mg = mg_find(sv, PERL_MAGIC_tied))
				|| mg->mg_virtual != &sharedsv_array_vtbl
				|| (shared_sv *) mg->mg_ptr != data) {
				SV *obj = newSV(0);
				sv_setref_iv(obj, "threads::shared::tie",PTR2IV(data));
				if (mg) {
				    sv_unmagic(sv, PERL_MAGIC_tied);
				}
				mg = sv_magicext(sv, obj, PERL_MAGIC_tied, &sharedsv_array_vtbl,
						(char *) data, 0);
				mg->mg_flags |= (MGf_COPY|MGf_DUP);
				SvREFCNT_inc(ssv);
				SvREFCNT_dec(obj);
				if(SvOBJECT(ssv)) {
				  STRLEN len;
				  char* stash_ptr = SvPV((SV*) SvSTASH(ssv), len);
				  HV* stash = gv_stashpvn(stash_ptr, len, TRUE);
				  SvOBJECT_on(sv);
				  SvSTASH_set(sv, (HV*)SvREFCNT_inc(stash));
				}
			    }
			    break;
		
			default:
			    if ((SvTYPE(sv) < SVt_PVMG)
				|| !(mg = mg_find(sv, PERL_MAGIC_shared_scalar))
				|| mg->mg_virtual != &sharedsv_scalar_vtbl
				|| (shared_sv *) mg->mg_ptr != data) {
				if (mg) {
				    sv_unmagic(sv, PERL_MAGIC_shared_scalar);
				}
				mg = sv_magicext(sv, Nullsv, PERL_MAGIC_shared_scalar,
						&sharedsv_scalar_vtbl, (char *)data, 0);
				mg->mg_flags |= (MGf_COPY|MGf_DUP);
				SvREFCNT_inc(ssv);
			    }
			    break;
			}
			assert ( Perl_sharedsv_find(aTHX_ *psv) == data );
		    }
		    return data;
		}
		
		void
		Perl_sharedsv_free(pTHX_ shared_sv *shared)
		{
		    if (shared) {
			dTHXc;
			SHARED_EDIT;
			SvREFCNT_dec(SHAREDSvPTR(shared));
			SHARED_RELEASE;
		    }
		}
		
		void
		Perl_sharedsv_share(pTHX_ SV *sv)
		{
		    switch(SvTYPE(sv)) {
		    case SVt_PVGV:
			Perl_croak(aTHX_ "Cannot share globs yet");
			break;
		
		    case SVt_PVCV:
			Perl_croak(aTHX_ "Cannot share subs yet");
			break;
		
		    default:
			ENTER_LOCK;
			Perl_sharedsv_associate(aTHX_ &sv, 0, 0);
			LEAVE_LOCK;
			SvSETMAGIC(sv);
			break;
		    }
		}
		
		#if defined(WIN32) || defined(OS2)
		#  define ABS2RELMILLI(abs)        \
		    do {                                \
		        abs -= (double)time(NULL);      \
		        if (abs > 0) { abs *= 1000; }   \
		        else         { abs  = 0;    }   \
		    } while (0)
		#endif /* WIN32 || OS2 */
		
		bool
		Perl_sharedsv_cond_timedwait(perl_cond *cond, perl_mutex *mut, double abs)
		{
		#if defined(NETWARE) || defined(FAKE_THREADS) || defined(I_MACH_CTHREADS)
		    Perl_croak_nocontext("cond_timedwait not supported on this platform");
		#else
		#  ifdef WIN32
		    int got_it = 0;
		
		    ABS2RELMILLI(abs);
		
		    cond->waiters++;
		    MUTEX_UNLOCK(mut);
		    /* See comments in win32/win32thread.h COND_WAIT vis-a-vis race */
		    switch (WaitForSingleObject(cond->sem, (DWORD)abs)) {
		        case WAIT_OBJECT_0:   got_it = 1; break;
		        case WAIT_TIMEOUT:                break;
		        default:
		            /* WAIT_FAILED? WAIT_ABANDONED? others? */
		            Perl_croak_nocontext("panic: cond_timedwait (%ld)",GetLastError());
		            break;
		    }
		    MUTEX_LOCK(mut);
		    cond->waiters--;
		    return got_it;
		#  else
		#    ifdef OS2
		    int rc, got_it = 0;
		    STRLEN n_a;
		
		    ABS2RELMILLI(abs);
		
		    if ((rc = DosResetEventSem(*cond,&n_a)) && (rc != ERROR_ALREADY_RESET))
		        Perl_rc = rc, croak_with_os2error("panic: cond_timedwait-reset");
		    MUTEX_UNLOCK(mut);
		    if (CheckOSError(DosWaitEventSem(*cond,abs))
		        && (rc != ERROR_INTERRUPT))
		        croak_with_os2error("panic: cond_timedwait");
		    if (rc == ERROR_INTERRUPT) errno = EINTR;
		    MUTEX_LOCK(mut);
		    return got_it;
		#    else         /* hope you're I_PTHREAD! */
		    struct timespec ts;
		    int got_it = 0;
		
		    ts.tv_sec = (long)abs;
		    abs -= (NV)ts.tv_sec;
		    ts.tv_nsec = (long)(abs * 1000000000.0);
		
		    switch (pthread_cond_timedwait(cond, mut, &ts)) {
		        case 0:         got_it = 1; break;
		        case ETIMEDOUT:             break;
		        default:
		            Perl_croak_nocontext("panic: cond_timedwait");
		            break;
		    }
		    return got_it;
		#    endif /* OS2 */
		#  endif /* WIN32 */
		#endif /* NETWARE || FAKE_THREADS || I_MACH_CTHREADS */
		}
		
		/* MAGIC (in mg.h sense) hooks */
		
		int
		sharedsv_scalar_mg_get(pTHX_ SV *sv, MAGIC *mg)
		{
		    shared_sv *shared = (shared_sv *) mg->mg_ptr;
		    assert(shared);
		
		    ENTER_LOCK;
		    if (SHAREDSvPTR(shared)) {
			if (SvROK(SHAREDSvPTR(shared))) {
			    SV *obj = Nullsv;
			    Perl_sharedsv_associate(aTHX_ &obj, SvRV(SHAREDSvPTR(shared)), NULL);
			    sv_setsv_nomg(sv, &PL_sv_undef);
			    SvRV_set(sv, obj);
			    SvROK_on(sv);
			    
			}
			else {
			    sv_setsv_nomg(sv, SHAREDSvPTR(shared));
			}
		    }
		    LEAVE_LOCK;
		    return 0;
		}
		
		void
		sharedsv_scalar_store(pTHX_ SV *sv, shared_sv *shared)
		{
		    dTHXc;
		    bool allowed = TRUE;
		    if (SvROK(sv)) {
			shared_sv* target = Perl_sharedsv_find(aTHX_ SvRV(sv));
			if (target) {
			    SV *tmp;
			    SHARED_CONTEXT;
			    tmp = newRV(SHAREDSvPTR(target));
			    sv_setsv_nomg(SHAREDSvPTR(shared), tmp);
			    SvREFCNT_dec(tmp);
			    if(SvOBJECT(SvRV(sv))) {
			      SV* fake_stash = newSVpv(HvNAME_get(SvSTASH(SvRV(sv))),0);
			      SvOBJECT_on(SHAREDSvPTR(target));
			      SvSTASH_set(SHAREDSvPTR(target), (HV*)fake_stash);
			    }
			    CALLER_CONTEXT;
			}
			else {
			    allowed = FALSE;
			}
		    }
		    else {
		        SvTEMP_off(sv);
			SHARED_CONTEXT;
			sv_setsv_nomg(SHAREDSvPTR(shared), sv);
			if(SvOBJECT(sv)) {
			  SV* fake_stash = newSVpv(HvNAME_get(SvSTASH(sv)),0);
			  SvOBJECT_on(SHAREDSvPTR(shared));
			  SvSTASH_set(SHAREDSvPTR(shared), (HV*)fake_stash);
			}
			CALLER_CONTEXT;
		    }
		    if (!allowed) {
			Perl_croak(aTHX_ "Invalid value for shared scalar");
		    }
		}
		
		int
		sharedsv_scalar_mg_set(pTHX_ SV *sv, MAGIC *mg)
		{
		    shared_sv *shared;
		    ENTER_LOCK;
		    /* We call associate to potentially upgrade shared side SV */
		    shared = Perl_sharedsv_associate(aTHX_ &sv, Nullsv, (shared_sv *) mg->mg_ptr);
		    assert(shared);
		    sharedsv_scalar_store(aTHX_ sv, shared);
		    LEAVE_LOCK;
		    return 0;
		}
		
		int
		sharedsv_scalar_mg_free(pTHX_ SV *sv, MAGIC *mg)
		{
		    shared_sv *shared = (shared_sv *) mg->mg_ptr;
		#if 0
		    assert (SvREFCNT(SHAREDSvPTR(shared)) < 1000);
		#endif
		    Perl_sharedsv_free(aTHX_ shared);
		    return 0;
		}
		
		int
		sharedsv_scalar_mg_clear(pTHX_ SV *sv, MAGIC *mg)
		{
		    return 0;
		}
		
		/*
		 * Called during cloning of new threads
		 */
		int
		sharedsv_scalar_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
		{
		    shared_sv *shared = (shared_sv *) mg->mg_ptr;
		    if (shared) {
			SvREFCNT_inc(SHAREDSvPTR(shared));
		    }
		    return 0;
		}
		
		MGVTBL sharedsv_scalar_vtbl = {
		 sharedsv_scalar_mg_get,	/* get */
		 sharedsv_scalar_mg_set,	/* set */
		 0,				/* len */
		 sharedsv_scalar_mg_clear,	/* clear */
		 sharedsv_scalar_mg_free,	/* free */
		 0,				/* copy */
		 sharedsv_scalar_mg_dup		/* dup */
		};
		
		/* Now the arrays/hashes stuff */
		int
		sharedsv_elem_mg_FETCH(pTHX_ SV *sv, MAGIC *mg)
		{
		    dTHXc;
		    shared_sv *shared = SV_to_sharedsv(aTHX_ mg->mg_obj);
		    shared_sv *target = Perl_sharedsv_find(aTHX_ sv);
		    SV** svp;
		
		    assert ( shared );
		    assert ( SHAREDSvPTR(shared) );
		
		    ENTER_LOCK;
		    if (SvTYPE(SHAREDSvPTR(shared)) == SVt_PVAV) {
			assert ( mg->mg_ptr == 0 );
			SHARED_CONTEXT;
			svp = av_fetch((AV*) SHAREDSvPTR(shared), mg->mg_len, 0);
		    }
		    else {
			char *key = mg->mg_ptr;
			STRLEN len = mg->mg_len;
			assert ( mg->mg_ptr != 0 );
			if (mg->mg_len == HEf_SVKEY) {
			   key = SvPV((SV *) mg->mg_ptr, len);
			}
			SHARED_CONTEXT;
			svp = hv_fetch((HV*) SHAREDSvPTR(shared), key, len, 0);
		    }
		    CALLER_CONTEXT;
		    if (svp) {
			/* Exists in the array */
			if (SvROK(*svp)) {
			    SV *obj = Nullsv;
			    Perl_sharedsv_associate(aTHX_ &obj, SvRV(*svp), NULL);
			    sv_setsv_nomg(sv, &PL_sv_undef);
			    SvRV_set(sv, obj);
			    SvROK_on(sv);
			    SvSETMAGIC(sv);
			}
			else {
			    target = Perl_sharedsv_associate(aTHX_ &sv, *svp, target);
			    sv_setsv(sv, *svp);
			}
		    }
		    else {
			/* Not in the array */
			sv_setsv(sv, &PL_sv_undef);
		    }
		    LEAVE_LOCK;
		    return 0;
		}
		
		int
		sharedsv_elem_mg_STORE(pTHX_ SV *sv, MAGIC *mg)
		{
		    dTHXc;
		    shared_sv *shared = SV_to_sharedsv(aTHX_ mg->mg_obj);
		    shared_sv *target;
		    SV **svp;
		    /* Theory - SV itself is magically shared - and we have ordered the
		       magic such that by the time we get here it has been stored
		       to its shared counterpart
		     */
		    ENTER_LOCK;
		    assert(shared);
		    assert(SHAREDSvPTR(shared));
		    if (SvTYPE(SHAREDSvPTR(shared)) == SVt_PVAV) {
			assert ( mg->mg_ptr == 0 );
			SHARED_CONTEXT;
			svp = av_fetch((AV*) SHAREDSvPTR(shared), mg->mg_len, 1);
		    }
		    else {
			char *key = mg->mg_ptr;
			STRLEN len = mg->mg_len;
			assert ( mg->mg_ptr != 0 );
			if (mg->mg_len == HEf_SVKEY)
			   key = SvPV((SV *) mg->mg_ptr, len);
			SHARED_CONTEXT;
			svp = hv_fetch((HV*) SHAREDSvPTR(shared), key, len, 1);
		    }
		    CALLER_CONTEXT;
		    target = Perl_sharedsv_associate(aTHX_ &sv, *svp, 0);
		    sharedsv_scalar_store(aTHX_ sv, target);
		    LEAVE_LOCK;
		    return 0;
		}
		
		int
		sharedsv_elem_mg_DELETE(pTHX_ SV *sv, MAGIC *mg)
		{
		    dTHXc;
		    MAGIC *shmg;
		    shared_sv *shared = SV_to_sharedsv(aTHX_ mg->mg_obj);
		    ENTER_LOCK;
		    sharedsv_elem_mg_FETCH(aTHX_ sv, mg);
		    if ((shmg = mg_find(sv, PERL_MAGIC_shared_scalar)))
			sharedsv_scalar_mg_get(aTHX_ sv, shmg);
		    if (SvTYPE(SHAREDSvPTR(shared)) == SVt_PVAV) {
			SHARED_CONTEXT;
			av_delete((AV*) SHAREDSvPTR(shared), mg->mg_len, G_DISCARD);
		    }
		    else {
			char *key = mg->mg_ptr;
			STRLEN len = mg->mg_len;
			assert ( mg->mg_ptr != 0 );
			if (mg->mg_len == HEf_SVKEY)
			   key = SvPV((SV *) mg->mg_ptr, len);
			SHARED_CONTEXT;
			hv_delete((HV*) SHAREDSvPTR(shared), key, len, G_DISCARD);
		    }
		    CALLER_CONTEXT;
		    LEAVE_LOCK;
		    return 0;
		}
		
		int
		sharedsv_elem_mg_free(pTHX_ SV *sv, MAGIC *mg)
		{
		    Perl_sharedsv_free(aTHX_ SV_to_sharedsv(aTHX_ mg->mg_obj));
		    return 0;
		}
		
		int
		sharedsv_elem_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
		{
		    shared_sv *shared = SV_to_sharedsv(aTHX_ mg->mg_obj);
		    SvREFCNT_inc(SHAREDSvPTR(shared));
		    mg->mg_flags |= MGf_DUP;
		    return 0;
		}
		
		MGVTBL sharedsv_elem_vtbl = {
		 sharedsv_elem_mg_FETCH,	/* get */
		 sharedsv_elem_mg_STORE,	/* set */
		 0,				/* len */
		 sharedsv_elem_mg_DELETE,	/* clear */
		 sharedsv_elem_mg_free,		/* free */
		 0,				/* copy */
		 sharedsv_elem_mg_dup		/* dup */
		};
		
		U32
		sharedsv_array_mg_FETCHSIZE(pTHX_ SV *sv, MAGIC *mg)
		{
		    dTHXc;
		    shared_sv *shared = (shared_sv *) mg->mg_ptr;
		    U32 val;
		    SHARED_EDIT;
		    if (SvTYPE(SHAREDSvPTR(shared)) == SVt_PVAV) {
			val = av_len((AV*) SHAREDSvPTR(shared));
		    }
		    else {
			/* not actually defined by tie API but ... */
			val = HvKEYS((HV*) SHAREDSvPTR(shared));
		    }
		    SHARED_RELEASE;
		    return val;
		}
		
		int
		sharedsv_array_mg_CLEAR(pTHX_ SV *sv, MAGIC *mg)
		{
		    dTHXc;
		    shared_sv *shared = (shared_sv *) mg->mg_ptr;
		    SHARED_EDIT;
		    if (SvTYPE(SHAREDSvPTR(shared)) == SVt_PVAV) {
			av_clear((AV*) SHAREDSvPTR(shared));
		    }
		    else {
			hv_clear((HV*) SHAREDSvPTR(shared));
		    }
		    SHARED_RELEASE;
		    return 0;
		}
		
		int
		sharedsv_array_mg_free(pTHX_ SV *sv, MAGIC *mg)
		{
		    Perl_sharedsv_free(aTHX_ (shared_sv *) mg->mg_ptr);
		    return 0;
		}
		
		/*
		 * This is called when perl is about to access an element of
		 * the array -
		 */
		int
		sharedsv_array_mg_copy(pTHX_ SV *sv, MAGIC* mg,
				       SV *nsv, const char *name, int namlen)
		{
		    shared_sv *shared = (shared_sv *) mg->mg_ptr;
		    MAGIC *nmg = sv_magicext(nsv,mg->mg_obj,
					    toLOWER(mg->mg_type),&sharedsv_elem_vtbl,
					    name, namlen);
		    ENTER_LOCK;
		    SvREFCNT_inc(SHAREDSvPTR(shared));
		    LEAVE_LOCK;
		    nmg->mg_flags |= MGf_DUP;
		    return 1;
		}
		
		int
		sharedsv_array_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *param)
		{
		    shared_sv *shared = (shared_sv *) mg->mg_ptr;
		    SvREFCNT_inc(SHAREDSvPTR(shared));
		    mg->mg_flags |= MGf_DUP;
		    return 0;
		}
		
		MGVTBL sharedsv_array_vtbl = {
		 0,				/* get */
		 0,				/* set */
		 sharedsv_array_mg_FETCHSIZE,	/* len */
		 sharedsv_array_mg_CLEAR,	/* clear */
		 sharedsv_array_mg_free,	/* free */
		 sharedsv_array_mg_copy,	/* copy */
		 sharedsv_array_mg_dup		/* dup */
		};
		
		#if 0
		  "Skipped embedded POD."
		#endif
		#line 836 "shared.xs"
		
		void
		Perl_sharedsv_unlock(pTHX_ shared_sv* ssv)
		{
		    recursive_lock_release(aTHX_ &ssv->lock);
		}
		
		#if 0
		  "Skipped embedded POD."
		#endif
		#line 849 "shared.xs"
		
		void
		Perl_sharedsv_lock(pTHX_ shared_sv* ssv)
		{
		    if (!ssv)
			return;
		    recursive_lock_acquire(aTHX_ &ssv->lock, __FILE__, __LINE__);
		}
		
		/* handles calls from lock() builtin via PL_lockhook */
		
		void
		Perl_sharedsv_locksv(pTHX_ SV *sv)
		{
		    shared_sv* shared;
		
		    if(SvROK(sv))
			sv = SvRV(sv);
		    shared = Perl_sharedsv_find(aTHX_ sv);
		    if(!shared)
		       croak("lock can only be used on shared values");
		    Perl_sharedsv_lock(aTHX_ shared);
		}
		
		#if 0
		  "Skipped embedded POD."
		#endif
		#line 880 "shared.xs"
		
		void
		Perl_sharedsv_init(pTHX)
		{
		  dTHXc;
		  /* This pair leaves us in shared context ... */
		  PL_sharedsv_space = perl_alloc();
		  perl_construct(PL_sharedsv_space);
		  CALLER_CONTEXT;
		  recursive_lock_init(aTHX_ &PL_sharedsv_lock);
		  PL_lockhook = &Perl_sharedsv_locksv;
		  PL_sharehook = &Perl_sharedsv_share;
		}
		
		#endif /* USE_ITHREADS */
		
		#ifndef PERL_UNUSED_VAR
		#  define PERL_UNUSED_VAR(var) if (0) var = var
		#endif
		
		#line 902 "shared.c"
		#ifdef USE_ITHREADS
		#define XSubPPtmpAAAA 1
		
		
		XS(XS_threads__shared__tie_PUSH); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared__tie_PUSH)
		{
		    dXSARGS;
		    if (items < 1)
			Perl_croak(aTHX_ "Usage: threads::shared::tie::PUSH(shared, ...)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			shared_sv *	shared = SV_to_sharedsv(aTHX_ ST(0));
		#line 905 "shared.xs"
			dTHXc;
			int i;
			for(i = 1; i < items; i++) {
			    SV* tmp = newSVsv(ST(i));
			    shared_sv *target;
			    ENTER_LOCK;
			    target = Perl_sharedsv_associate(aTHX_ &tmp, Nullsv, 0);
			    sharedsv_scalar_store(aTHX_ tmp, target);
			    SHARED_CONTEXT;
			    av_push((AV*) SHAREDSvPTR(shared), SHAREDSvPTR(target));
			    SvREFCNT_inc(SHAREDSvPTR(target));
			    SHARED_RELEASE;
			    SvREFCNT_dec(tmp);
			}
		#line 931 "shared.c"
		    }
		    XSRETURN_EMPTY;
		}
		
		
		XS(XS_threads__shared__tie_UNSHIFT); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared__tie_UNSHIFT)
		{
		    dXSARGS;
		    if (items < 1)
			Perl_croak(aTHX_ "Usage: threads::shared::tie::UNSHIFT(shared, ...)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			shared_sv *	shared = SV_to_sharedsv(aTHX_ ST(0));
		#line 923 "shared.xs"
			dTHXc;
			int i;
			ENTER_LOCK;
			SHARED_CONTEXT;
			av_unshift((AV*)SHAREDSvPTR(shared), items - 1);
			CALLER_CONTEXT;
			for(i = 1; i < items; i++) {
			    SV* tmp = newSVsv(ST(i));
			    shared_sv *target = Perl_sharedsv_associate(aTHX_ &tmp, Nullsv, 0);
			    sharedsv_scalar_store(aTHX_ tmp, target);
			    SHARED_CONTEXT;
			    av_store((AV*) SHAREDSvPTR(shared), i - 1, SHAREDSvPTR(target));
			    SvREFCNT_inc(SHAREDSvPTR(target));
			    CALLER_CONTEXT;
			    SvREFCNT_dec(tmp);
			}
			LEAVE_LOCK;
		#line 964 "shared.c"
		    }
		    XSRETURN_EMPTY;
		}
		
		
		XS(XS_threads__shared__tie_POP); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared__tie_POP)
		{
		    dXSARGS;
		    if (items != 1)
			Perl_croak(aTHX_ "Usage: threads::shared::tie::POP(shared)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			shared_sv *	shared = SV_to_sharedsv(aTHX_ ST(0));
		#line 944 "shared.xs"
			dTHXc;
			SV* sv;
			ENTER_LOCK;
			SHARED_CONTEXT;
			sv = av_pop((AV*)SHAREDSvPTR(shared));
			CALLER_CONTEXT;
			ST(0) = sv_newmortal();
			Perl_sharedsv_associate(aTHX_ &ST(0), sv, 0);
			SvREFCNT_dec(sv);
			LEAVE_LOCK;
			XSRETURN(1);
		#line 991 "shared.c"
		    }
		    XSRETURN(1);
		}
		
		
		XS(XS_threads__shared__tie_SHIFT); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared__tie_SHIFT)
		{
		    dXSARGS;
		    if (items != 1)
			Perl_croak(aTHX_ "Usage: threads::shared::tie::SHIFT(shared)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			shared_sv *	shared = SV_to_sharedsv(aTHX_ ST(0));
		#line 959 "shared.xs"
			dTHXc;
			SV* sv;
			ENTER_LOCK;
			SHARED_CONTEXT;
			sv = av_shift((AV*)SHAREDSvPTR(shared));
			CALLER_CONTEXT;
			ST(0) = sv_newmortal();
			Perl_sharedsv_associate(aTHX_ &ST(0), sv, 0);
			SvREFCNT_dec(sv);
			LEAVE_LOCK;
			XSRETURN(1);
		#line 1018 "shared.c"
		    }
		    XSRETURN(1);
		}
		
		
		XS(XS_threads__shared__tie_EXTEND); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared__tie_EXTEND)
		{
		    dXSARGS;
		    if (items != 2)
			Perl_croak(aTHX_ "Usage: threads::shared::tie::EXTEND(shared, count)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			shared_sv *	shared = SV_to_sharedsv(aTHX_ ST(0));
			IV	count = (IV)SvIV(ST(1));
		#line 974 "shared.xs"
			dTHXc;
			SHARED_EDIT;
			av_extend((AV*)SHAREDSvPTR(shared), count);
			SHARED_RELEASE;
		#line 1039 "shared.c"
		    }
		    XSRETURN_EMPTY;
		}
		
		
		XS(XS_threads__shared__tie_STORESIZE); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared__tie_STORESIZE)
		{
		    dXSARGS;
		    if (items != 2)
			Perl_croak(aTHX_ "Usage: threads::shared::tie::STORESIZE(shared, count)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			shared_sv *	shared = SV_to_sharedsv(aTHX_ ST(0));
			IV	count = (IV)SvIV(ST(1));
		#line 982 "shared.xs"
			dTHXc;
			SHARED_EDIT;
			av_fill((AV*) SHAREDSvPTR(shared), count);
			SHARED_RELEASE;
		#line 1060 "shared.c"
		    }
		    XSRETURN_EMPTY;
		}
		
		
		XS(XS_threads__shared__tie_EXISTS); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared__tie_EXISTS)
		{
		    dXSARGS;
		    if (items != 2)
			Perl_croak(aTHX_ "Usage: threads::shared::tie::EXISTS(shared, index)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			shared_sv *	shared = SV_to_sharedsv(aTHX_ ST(0));
			SV *	index = ST(1);
		#line 993 "shared.xs"
			dTHXc;
			bool exists;
			if (SvTYPE(SHAREDSvPTR(shared)) == SVt_PVAV) {
			    SHARED_EDIT;
			    exists = av_exists((AV*) SHAREDSvPTR(shared), SvIV(index));
			}
			else {
			    STRLEN len;
			    char *key = SvPV(index,len);
			    SHARED_EDIT;
			    exists = hv_exists((HV*) SHAREDSvPTR(shared), key, len);
			}
			SHARED_RELEASE;
			ST(0) = (exists) ? &PL_sv_yes : &PL_sv_no;
			XSRETURN(1);
		#line 1092 "shared.c"
		    }
		    XSRETURN(1);
		}
		
		
		XS(XS_threads__shared__tie_FIRSTKEY); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared__tie_FIRSTKEY)
		{
		    dXSARGS;
		    if (items != 1)
			Perl_croak(aTHX_ "Usage: threads::shared::tie::FIRSTKEY(shared)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			shared_sv *	shared = SV_to_sharedsv(aTHX_ ST(0));
		#line 1013 "shared.xs"
			dTHXc;
			char* key = NULL;
			I32 len = 0;
			HE* entry;
			ENTER_LOCK;
			SHARED_CONTEXT;
			hv_iterinit((HV*) SHAREDSvPTR(shared));
			entry = hv_iternext((HV*) SHAREDSvPTR(shared));
			if (entry) {
				key = hv_iterkey(entry,&len);
				CALLER_CONTEXT;
				ST(0) = sv_2mortal(newSVpv(key, len));
			} else {
			     CALLER_CONTEXT;
			     ST(0) = &PL_sv_undef;
			}
			LEAVE_LOCK;
			XSRETURN(1);
		#line 1126 "shared.c"
		    }
		    XSRETURN(1);
		}
		
		
		XS(XS_threads__shared__tie_NEXTKEY); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared__tie_NEXTKEY)
		{
		    dXSARGS;
		    if (items != 2)
			Perl_croak(aTHX_ "Usage: threads::shared::tie::NEXTKEY(shared, oldkey)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			shared_sv *	shared = SV_to_sharedsv(aTHX_ ST(0));
			SV *	oldkey = ST(1);
		#line 1035 "shared.xs"
			dTHXc;
			char* key = NULL;
			I32 len = 0;
			HE* entry;
			ENTER_LOCK;
			SHARED_CONTEXT;
			entry = hv_iternext((HV*) SHAREDSvPTR(shared));
			if (entry) {
				key = hv_iterkey(entry,&len);
				CALLER_CONTEXT;
				ST(0) = sv_2mortal(newSVpv(key, len));
			} else {
			     CALLER_CONTEXT;
			     ST(0) = &PL_sv_undef;
			}
			LEAVE_LOCK;
			XSRETURN(1);
		#line 1160 "shared.c"
		    }
		    XSRETURN(1);
		}
		
		
		XS(XS_threads__shared__id); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared__id)
		{
		    dXSARGS;
		    if (items != 1)
			Perl_croak(aTHX_ "Usage: threads::shared::_id(ref)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			SV *	ref = ST(0);
		#line 1061 "shared.xs"
			shared_sv *shared;
			ref = SvRV(ref);
			if(SvROK(ref))
			    ref = SvRV(ref);
			if( (shared = Perl_sharedsv_find(aTHX_ ref)) ){
			    ST(0) = sv_2mortal(newSViv(PTR2IV(shared)));
			    XSRETURN(1);
			}
			XSRETURN_UNDEF;
		#line 1185 "shared.c"
		    }
		    XSRETURN(1);
		}
		
		
		XS(XS_threads__shared__refcnt); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared__refcnt)
		{
		    dXSARGS;
		    if (items != 1)
			Perl_croak(aTHX_ "Usage: threads::shared::_refcnt(ref)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			SV *	ref = ST(0);
		#line 1076 "shared.xs"
			shared_sv *shared;
			ref = SvRV(ref);
			if(SvROK(ref))
			    ref = SvRV(ref);
			if( (shared = Perl_sharedsv_find(aTHX_ ref)) ){
			  if (SHAREDSvPTR(shared)) {
			    ST(0) = sv_2mortal(newSViv(SvREFCNT(SHAREDSvPTR(shared))));
			    XSRETURN(1);
			  }
			  else {
			     Perl_warn(aTHX_ "%" SVf " s=%p has no shared SV",ST(0),shared);
			  }
			}
			else {
			     Perl_warn(aTHX_ "%" SVf " is not shared",ST(0));
			}
			XSRETURN_UNDEF;
		#line 1218 "shared.c"
		    }
		    XSRETURN(1);
		}
		
		
		XS(XS_threads__shared_share); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared_share)
		{
		    dXSARGS;
		    if (items != 1)
			Perl_croak(aTHX_ "Usage: threads::shared::share(ref)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			SV *	RETVAL;
			SV *	ref = ST(0);
		#line 1098 "shared.xs"
			if(!SvROK(ref))
		            Perl_croak(aTHX_ "Argument to share needs to be passed as ref");
			ref = SvRV(ref);
			if(SvROK(ref))
			    ref = SvRV(ref);
			Perl_sharedsv_share(aTHX_ ref);
			RETVAL = newRV(ref);
		#line 1242 "shared.c"
			ST(0) = RETVAL;
			sv_2mortal(ST(0));
		    }
		    XSRETURN(1);
		}
		
		
		XS(XS_threads__shared_lock_enabled); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared_lock_enabled)
		{
		    dXSARGS;
		    if (items != 1)
			Perl_croak(aTHX_ "Usage: threads::shared::lock_enabled(ref)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			SV *	ref = ST(0);
		#line 1112 "shared.xs"
			shared_sv* shared;
			if(!SvROK(ref))
		            Perl_croak(aTHX_ "Argument to lock needs to be passed as ref");
			ref = SvRV(ref);
			if(SvROK(ref))
			    ref = SvRV(ref);
			shared = Perl_sharedsv_find(aTHX_ ref);
			if(!shared)
			   croak("lock can only be used on shared values");
			Perl_sharedsv_lock(aTHX_ shared);
		#line 1270 "shared.c"
		    }
		    XSRETURN_EMPTY;
		}
		
		
		XS(XS_threads__shared_cond_wait_enabled); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared_cond_wait_enabled)
		{
		    dXSARGS;
		    if (items < 1 || items > 2)
			Perl_croak(aTHX_ "Usage: threads::shared::cond_wait_enabled(ref_cond, ref_lock= 0)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
		#line 1127 "shared.xs"
			shared_sv* shared;
			perl_cond* user_condition;
			int locks;
			int same = 0;
		
		#line 1290 "shared.c"
			SV *	ref_cond = ST(0);
			SV *	ref_lock;
		
			if (items < 2)
			    ref_lock = 0;
			else {
			    ref_lock = ST(1);
			}
		#line 1133 "shared.xs"
			if (!ref_lock || ref_lock == ref_cond) same = 1;
		
			if(!SvROK(ref_cond))
		            Perl_croak(aTHX_ "Argument to cond_wait needs to be passed as ref");
			ref_cond = SvRV(ref_cond);
			if(SvROK(ref_cond))
			    ref_cond = SvRV(ref_cond);
			shared = Perl_sharedsv_find(aTHX_ ref_cond);
			if(!shared)
			    croak("cond_wait can only be used on shared values");
		
			user_condition = &shared->user_cond;
			if (! same) {
			    if (!SvROK(ref_lock))
			        Perl_croak(aTHX_ "cond_wait lock needs to be passed as ref");
			    ref_lock = SvRV(ref_lock);
			    if (SvROK(ref_lock)) ref_lock = SvRV(ref_lock);
			    shared = Perl_sharedsv_find(aTHX_ ref_lock);
			    if (!shared)
			        croak("cond_wait lock must be a shared value");
			}
			if(shared->lock.owner != aTHX)
			    croak("You need a lock before you can cond_wait");
			/* Stealing the members of the lock object worries me - NI-S */
			MUTEX_LOCK(&shared->lock.mutex);
			shared->lock.owner = NULL;
			locks = shared->lock.locks;
			shared->lock.locks = 0;
		
			/* since we are releasing the lock here we need to tell other
			people that is ok to go ahead and use it */
			COND_SIGNAL(&shared->lock.cond);
			COND_WAIT(user_condition, &shared->lock.mutex);
			while(shared->lock.owner != NULL) {
			    /* OK -- must reacquire the lock */
			    COND_WAIT(&shared->lock.cond, &shared->lock.mutex);
			}
			shared->lock.owner = aTHX;
			shared->lock.locks = locks;
			MUTEX_UNLOCK(&shared->lock.mutex);
		#line 1340 "shared.c"
		    }
		    XSRETURN_EMPTY;
		}
		
		
		XS(XS_threads__shared_cond_timedwait_enabled); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared_cond_timedwait_enabled)
		{
		    dXSARGS;
		    if (items < 2 || items > 3)
			Perl_croak(aTHX_ "Usage: threads::shared::cond_timedwait_enabled(ref_cond, abs, ref_lock= 0)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
		#line 1178 "shared.xs"
			shared_sv* shared;
			perl_cond* user_condition;
			int locks;
			int same = 0;
		
		#line 1360 "shared.c"
			int	RETVAL;
			dXSTARG;
			SV *	ref_cond = ST(0);
			double	abs = (double)SvNV(ST(1));
			SV *	ref_lock;
		
			if (items < 3)
			    ref_lock = 0;
			else {
			    ref_lock = ST(2);
			}
		#line 1184 "shared.xs"
			if (!ref_lock || ref_cond == ref_lock) same = 1;
		
			if(!SvROK(ref_cond))
			    Perl_croak(aTHX_ "Argument to cond_timedwait needs to be passed as ref");
			ref_cond = SvRV(ref_cond);
			if(SvROK(ref_cond))
			    ref_cond = SvRV(ref_cond);
			shared = Perl_sharedsv_find(aTHX_ ref_cond);
			if(!shared)
			    croak("cond_timedwait can only be used on shared values");
		
			user_condition = &shared->user_cond;
			if (! same) {
			    if (!SvROK(ref_lock))
			        Perl_croak(aTHX_ "cond_timedwait lock needs to be passed as ref");
			    ref_lock = SvRV(ref_lock);
			    if (SvROK(ref_lock)) ref_lock = SvRV(ref_lock);
			    shared = Perl_sharedsv_find(aTHX_ ref_lock);
			    if (!shared)
			        croak("cond_timedwait lock must be a shared value");
			}
			if(shared->lock.owner != aTHX)
			    croak("You need a lock before you can cond_wait");
		
			MUTEX_LOCK(&shared->lock.mutex);
			shared->lock.owner = NULL;
			locks = shared->lock.locks;
			shared->lock.locks = 0;
			/* since we are releasing the lock here we need to tell other
			people that is ok to go ahead and use it */
			COND_SIGNAL(&shared->lock.cond);
			RETVAL = Perl_sharedsv_cond_timedwait(user_condition, &shared->lock.mutex, abs);
			while (shared->lock.owner != NULL) {
			    /* OK -- must reacquire the lock... */
			    COND_WAIT(&shared->lock.cond, &shared->lock.mutex);
			}
			shared->lock.owner = aTHX;
			shared->lock.locks = locks;
			MUTEX_UNLOCK(&shared->lock.mutex);
		
			if (RETVAL == 0)
		            XSRETURN_UNDEF;
		#line 1415 "shared.c"
			XSprePUSH; PUSHi((IV)RETVAL);
		    }
		    XSRETURN(1);
		}
		
		
		XS(XS_threads__shared_cond_signal_enabled); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared_cond_signal_enabled)
		{
		    dXSARGS;
		    if (items != 1)
			Perl_croak(aTHX_ "Usage: threads::shared::cond_signal_enabled(ref)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			SV *	ref = ST(0);
		#line 1233 "shared.xs"
			shared_sv* shared;
			if(!SvROK(ref))
		            Perl_croak(aTHX_ "Argument to cond_signal needs to be passed as ref");
			ref = SvRV(ref);
			if(SvROK(ref))
			    ref = SvRV(ref);
			shared = Perl_sharedsv_find(aTHX_ ref);
			if(!shared)
			    croak("cond_signal can only be used on shared values");
			if (ckWARN(WARN_THREADS) && shared->lock.owner != aTHX)
			    Perl_warner(aTHX_ packWARN(WARN_THREADS),
					    "cond_signal() called on unlocked variable");
			COND_SIGNAL(&shared->user_cond);
		#line 1445 "shared.c"
		    }
		    XSRETURN_EMPTY;
		}
		
		
		XS(XS_threads__shared_cond_broadcast_enabled); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared_cond_broadcast_enabled)
		{
		    dXSARGS;
		    if (items != 1)
			Perl_croak(aTHX_ "Usage: threads::shared::cond_broadcast_enabled(ref)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			SV *	ref = ST(0);
		#line 1251 "shared.xs"
			shared_sv* shared;
			if(!SvROK(ref))
		            Perl_croak(aTHX_ "Argument to cond_broadcast needs to be passed as ref");
			ref = SvRV(ref);
			if(SvROK(ref))
			    ref = SvRV(ref);
			shared = Perl_sharedsv_find(aTHX_ ref);
			if(!shared)
			    croak("cond_broadcast can only be used on shared values");
			if (ckWARN(WARN_THREADS) && shared->lock.owner != aTHX)
			    Perl_warner(aTHX_ packWARN(WARN_THREADS),
					    "cond_broadcast() called on unlocked variable");
			COND_BROADCAST(&shared->user_cond);
		#line 1474 "shared.c"
		    }
		    XSRETURN_EMPTY;
		}
		
		
		XS(XS_threads__shared_bless); /* prototype to pass -Wmissing-prototypes */
		XS(XS_threads__shared_bless)
		{
		    dXSARGS;
		    if (items < 1)
			Perl_croak(aTHX_ "Usage: threads::shared::bless(ref, ...)");
		    PERL_UNUSED_VAR(cv); /* -W */
		    {
			SV *	RETVAL;
			SV*	ref = ST(0);
		#line 1270 "shared.xs"
		        {
			  HV* stash;
			  shared_sv* shared;
			  if (items == 1)
			    stash = CopSTASH(PL_curcop);
			  else {
			    SV* ssv = ST(1);
			    STRLEN len;
			    char *ptr;
		
			    if (ssv && !SvGMAGICAL(ssv) && !SvAMAGIC(ssv) && SvROK(ssv))
			      Perl_croak(aTHX_ "Attempt to bless into a reference");
			    ptr = SvPV(ssv,len);
			    if (ckWARN(WARN_MISC) && len == 0)
			      Perl_warner(aTHX_ packWARN(WARN_MISC),
					  "Explicit blessing to '' (assuming package main)");
			    stash = gv_stashpvn(ptr, len, TRUE);
			  }
			  SvREFCNT_inc(ref);
			  (void)sv_bless(ref, stash);
			  RETVAL = ref;
			  shared = Perl_sharedsv_find(aTHX_ ref);
			  if(shared) {
			    dTHXc;
			    ENTER_LOCK;
			    SHARED_CONTEXT;
			    {
			      SV* fake_stash = newSVpv(HvNAME_get(stash),0);
			      (void)sv_bless(SHAREDSvPTR(shared),(HV*)fake_stash);
			    }
			    CALLER_CONTEXT;
			    LEAVE_LOCK;
			  }
			}
		#line 1525 "shared.c"
			ST(0) = RETVAL;
			sv_2mortal(ST(0));
		    }
		    XSRETURN(1);
		}
		
		#endif /* USE_ITHREADS */
		#ifdef __cplusplus
		extern "C"
		#endif
		XS(boot_threads__shared); /* prototype to pass -Wmissing-prototypes */
		XS(boot_threads__shared)
      ######    {
      ######        dXSARGS;
      ######        char* file = __FILE__;
		
      ######        PERL_UNUSED_VAR(cv); /* -W */
      ######        PERL_UNUSED_VAR(items); /* -W */
      ######        XS_VERSION_BOOTCHECK ;
		
		#if XSubPPtmpAAAA
		        newXS("threads::shared::tie::PUSH", XS_threads__shared__tie_PUSH, file);
		        newXS("threads::shared::tie::UNSHIFT", XS_threads__shared__tie_UNSHIFT, file);
		        newXS("threads::shared::tie::POP", XS_threads__shared__tie_POP, file);
		        newXS("threads::shared::tie::SHIFT", XS_threads__shared__tie_SHIFT, file);
		        newXS("threads::shared::tie::EXTEND", XS_threads__shared__tie_EXTEND, file);
		        newXS("threads::shared::tie::STORESIZE", XS_threads__shared__tie_STORESIZE, file);
		        newXS("threads::shared::tie::EXISTS", XS_threads__shared__tie_EXISTS, file);
		        newXS("threads::shared::tie::FIRSTKEY", XS_threads__shared__tie_FIRSTKEY, file);
		        newXS("threads::shared::tie::NEXTKEY", XS_threads__shared__tie_NEXTKEY, file);
		        newXSproto("threads::shared::_id", XS_threads__shared__id, file, "\\[$@%]");
		        newXSproto("threads::shared::_refcnt", XS_threads__shared__refcnt, file, "\\[$@%]");
		        newXSproto("threads::shared::share", XS_threads__shared_share, file, "\\[$@%]");
		        newXSproto("threads::shared::lock_enabled", XS_threads__shared_lock_enabled, file, "\\[$@%]");
		        newXSproto("threads::shared::cond_wait_enabled", XS_threads__shared_cond_wait_enabled, file, "\\[$@%];\\[$@%]");
		        newXSproto("threads::shared::cond_timedwait_enabled", XS_threads__shared_cond_timedwait_enabled, file, "\\[$@%]$;\\[$@%]");
		        newXSproto("threads::shared::cond_signal_enabled", XS_threads__shared_cond_signal_enabled, file, "\\[$@%]");
		        newXSproto("threads::shared::cond_broadcast_enabled", XS_threads__shared_cond_broadcast_enabled, file, "\\[$@%]");
		        newXSproto("threads::shared::bless", XS_threads__shared_bless, file, "$;$");
		#endif
		
		    /* Initialisation Section */
		
		#if XSubPPtmpAAAA
		#endif
		#line 1310 "shared.xs"
		{
		#ifdef USE_ITHREADS
		     Perl_sharedsv_init(aTHX);
		#endif /* USE_ITHREADS */
		}
		
		#line 1578 "shared.c"
		
		    /* End of Initialisation Section */
		
      ######        XSRETURN_YES;
		}
		
