+ SHARED_CONTEXT;
+ svp = hv_fetch((HV*) SHAREDSvPTR(shared), key, len, 0);
+ }
+ CALLER_CONTEXT;
+ if (svp) {
+ /* Exists in the array */
+ 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 */
+};
+
+=for apidoc sharedsv_unlock
+
+Recursively unlocks a shared sv.
+
+=cut