You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2012/11/15 05:16:27 UTC
[lucy-commits] [8/8] git commit: refs/heads/kill_clownfish_host - Consolidate XS
code.
Consolidate XS code.
Consolidate all XS code related to the Clownfish core runtime into
XSBind.c.
Project: http://git-wip-us.apache.org/repos/asf/lucy/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/f6a05ea6
Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/f6a05ea6
Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/f6a05ea6
Branch: refs/heads/kill_clownfish_host
Commit: f6a05ea61c1dc67685755963f81aee82a1e43a01
Parents: 413bf56
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Nov 14 16:19:12 2012 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Nov 14 16:19:12 2012 -0800
----------------------------------------------------------------------
perl/xs/Clownfish/Err.c | 146 ---------------
perl/xs/Clownfish/LockFreeRegistry.c | 36 ----
perl/xs/Clownfish/Obj.c | 113 ------------
perl/xs/Clownfish/VTable.c | 70 -------
perl/xs/XSBind.c | 285 +++++++++++++++++++++++++++++
5 files changed, 285 insertions(+), 365 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy/blob/f6a05ea6/perl/xs/Clownfish/Err.c
----------------------------------------------------------------------
diff --git a/perl/xs/Clownfish/Err.c b/perl/xs/Clownfish/Err.c
deleted file mode 100644
index 763178d..0000000
--- a/perl/xs/Clownfish/Err.c
+++ /dev/null
@@ -1,146 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "XSBind.h"
-#include "Clownfish/Host.h"
-
-// Anonymous XSUB helper for Err#trap(). It wraps the supplied C function
-// so that it can be run inside a Perl eval block.
-static SV *attempt_xsub = NULL;
-
-XS(lucy_Err_attempt_via_xs) {
- dXSARGS;
- CHY_UNUSED_VAR(cv);
- SP -= items;
- if (items != 2) {
- CFISH_THROW(CFISH_ERR, "Usage: $sub->(routine, context)");
- };
- IV routine_iv = SvIV(ST(0));
- IV context_iv = SvIV(ST(1));
- Cfish_Err_Attempt_t routine = INT2PTR(Cfish_Err_Attempt_t, routine_iv);
- void *context = INT2PTR(void*, context_iv);
- routine(context);
- XSRETURN(0);
-}
-
-void
-lucy_Err_init_class(void) {
- char *file = (char*)__FILE__;
- attempt_xsub = (SV*)newXS(NULL, lucy_Err_attempt_via_xs, file);
-}
-
-lucy_Err*
-lucy_Err_get_error() {
- lucy_Err *error
- = (lucy_Err*)lucy_Host_callback_obj(LUCY_ERR, "get_error", 0);
- CFISH_DECREF(error); // Cancel out incref from callback.
- return error;
-}
-
-void
-lucy_Err_set_error(lucy_Err *error) {
- lucy_Host_callback(LUCY_ERR, "set_error", 1,
- CFISH_ARG_OBJ("error", error));
- CFISH_DECREF(error);
-}
-
-void
-lucy_Err_do_throw(lucy_Err *err) {
- dSP;
- SV *error_sv = (SV*)Lucy_Err_To_Host(err);
- CFISH_DECREF(err);
- ENTER;
- SAVETMPS;
- PUSHMARK(SP);
- XPUSHs(sv_2mortal(error_sv));
- PUTBACK;
- call_pv("Clownfish::Err::do_throw", G_DISCARD);
- FREETMPS;
- LEAVE;
-}
-
-void*
-lucy_Err_to_host(lucy_Err *self) {
- Lucy_Err_To_Host_t super_to_host
- = CFISH_SUPER_METHOD_PTR(LUCY_ERR, Lucy_Err_To_Host);
- SV *perl_obj = (SV*)super_to_host(self);
- XSBind_enable_overload(perl_obj);
- return perl_obj;
-}
-
-void
-lucy_Err_throw_mess(lucy_VTable *vtable, lucy_CharBuf *message) {
- Lucy_Err_Make_t make
- = CFISH_METHOD_PTR(CFISH_CERTIFY(vtable, LUCY_VTABLE), Lucy_Err_Make);
- lucy_Err *err = (lucy_Err*)CFISH_CERTIFY(make(NULL), LUCY_ERR);
- Lucy_Err_Cat_Mess(err, message);
- CFISH_DECREF(message);
- lucy_Err_do_throw(err);
-}
-
-void
-lucy_Err_warn_mess(lucy_CharBuf *message) {
- SV *error_sv = XSBind_cb_to_sv(message);
- CFISH_DECREF(message);
- warn("%s", SvPV_nolen(error_sv));
- SvREFCNT_dec(error_sv);
-}
-
-lucy_Err*
-lucy_Err_trap(Cfish_Err_Attempt_t routine, void *context) {
- lucy_Err *error = NULL;
- SV *routine_sv = newSViv(PTR2IV(routine));
- SV *context_sv = newSViv(PTR2IV(context));
- dSP;
- ENTER;
- SAVETMPS;
- PUSHMARK(SP);
- EXTEND(SP, 2);
- PUSHs(sv_2mortal(routine_sv));
- PUSHs(sv_2mortal(context_sv));
- PUTBACK;
-
- int count = call_sv(attempt_xsub, G_EVAL | G_DISCARD);
- if (count != 0) {
- lucy_CharBuf *mess
- = lucy_CB_newf("'attempt' returned too many values: %i32",
- (int32_t)count);
- error = lucy_Err_new(mess);
- }
- else {
- SV *dollar_at = get_sv("@", FALSE);
- if (SvTRUE(dollar_at)) {
- if (sv_isobject(dollar_at)
- && sv_derived_from(dollar_at,"Clownfish::Err")
- ) {
- IV error_iv = SvIV(SvRV(dollar_at));
- error = INT2PTR(lucy_Err*, error_iv);
- CFISH_INCREF(error);
- }
- else {
- STRLEN len;
- char *ptr = SvPVutf8(dollar_at, len);
- lucy_CharBuf *mess = lucy_CB_new_from_trusted_utf8(ptr, len);
- error = lucy_Err_new(mess);
- }
- }
- }
- FREETMPS;
- LEAVE;
-
- return error;
-}
-
http://git-wip-us.apache.org/repos/asf/lucy/blob/f6a05ea6/perl/xs/Clownfish/LockFreeRegistry.c
----------------------------------------------------------------------
diff --git a/perl/xs/Clownfish/LockFreeRegistry.c b/perl/xs/Clownfish/LockFreeRegistry.c
deleted file mode 100644
index 41f7899..0000000
--- a/perl/xs/Clownfish/LockFreeRegistry.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_LUCY_OBJ
-#define C_LUCY_LOCKFREEREGISTRY
-#include "XSBind.h"
-
-#include "Clownfish/LockFreeRegistry.h"
-#include "Clownfish/Host.h"
-
-void*
-lucy_LFReg_to_host(lucy_LockFreeRegistry *self) {
- chy_bool_t first_time = self->ref.count < 4 ? true : false;
- Lucy_LFReg_To_Host_t to_host
- = CFISH_SUPER_METHOD_PTR(LUCY_LOCKFREEREGISTRY, Lucy_LFReg_To_Host);
- SV *host_obj = (SV*)to_host(self);
- if (first_time) {
- SvSHARE((SV*)self->ref.host_obj);
- }
- return host_obj;
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy/blob/f6a05ea6/perl/xs/Clownfish/Obj.c
----------------------------------------------------------------------
diff --git a/perl/xs/Clownfish/Obj.c b/perl/xs/Clownfish/Obj.c
deleted file mode 100644
index 38fcd2d..0000000
--- a/perl/xs/Clownfish/Obj.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_LUCY_OBJ
-
-#include "EXTERN.h"
-#include "perl.h"
-#include "XSUB.h"
-#include "ppport.h"
-
-#include "Clownfish/Obj.h"
-#include "Clownfish/CharBuf.h"
-#include "Clownfish/Err.h"
-#include "Clownfish/VTable.h"
-#include "Clownfish/Util/Memory.h"
-
-static void
-S_lazy_init_host_obj(lucy_Obj *self) {
- SV *inner_obj = newSV(0);
- SvOBJECT_on(inner_obj);
- PL_sv_objcount++;
- SvUPGRADE(inner_obj, SVt_PVMG);
- sv_setiv(inner_obj, PTR2IV(self));
-
- // Connect class association.
- lucy_CharBuf *class_name = Lucy_VTable_Get_Name(self->vtable);
- HV *stash = gv_stashpvn((char*)Lucy_CB_Get_Ptr8(class_name),
- Lucy_CB_Get_Size(class_name), TRUE);
- SvSTASH_set(inner_obj, (HV*)SvREFCNT_inc(stash));
-
- /* Up till now we've been keeping track of the refcount in
- * self->ref.count. We're replacing ref.count with ref.host_obj, which
- * will assume responsibility for maintaining the refcount. ref.host_obj
- * starts off with a refcount of 1, so we need to transfer any refcounts
- * in excess of that. */
- size_t old_refcount = self->ref.count;
- self->ref.host_obj = inner_obj;
- while (old_refcount > 1) {
- SvREFCNT_inc_simple_void_NN(inner_obj);
- old_refcount--;
- }
-}
-
-uint32_t
-lucy_Obj_get_refcount(lucy_Obj *self) {
- return self->ref.count < 4
- ? self->ref.count
- : SvREFCNT((SV*)self->ref.host_obj);
-}
-
-lucy_Obj*
-lucy_Obj_inc_refcount(lucy_Obj *self) {
- switch (self->ref.count) {
- case 0:
- CFISH_THROW(LUCY_ERR, "Illegal refcount of 0");
- break; // useless
- case 1:
- case 2:
- self->ref.count++;
- break;
- case 3:
- S_lazy_init_host_obj(self);
- // fall through
- default:
- SvREFCNT_inc_simple_void_NN((SV*)self->ref.host_obj);
- }
- return self;
-}
-
-uint32_t
-lucy_Obj_dec_refcount(lucy_Obj *self) {
- uint32_t modified_refcount = I32_MAX;
- switch (self->ref.count) {
- case 0:
- CFISH_THROW(LUCY_ERR, "Illegal refcount of 0");
- break; // useless
- case 1:
- modified_refcount = 0;
- Lucy_Obj_Destroy(self);
- break;
- case 2:
- case 3:
- modified_refcount = --self->ref.count;
- break;
- default:
- modified_refcount = SvREFCNT((SV*)self->ref.host_obj) - 1;
- // If the SV's refcount falls to 0, DESTROY will be invoked from
- // Perl-space.
- SvREFCNT_dec((SV*)self->ref.host_obj);
- }
- return modified_refcount;
-}
-
-void*
-lucy_Obj_to_host(lucy_Obj *self) {
- if (self->ref.count < 4) { S_lazy_init_host_obj(self); }
- return newRV_inc((SV*)self->ref.host_obj);
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy/blob/f6a05ea6/perl/xs/Clownfish/VTable.c
----------------------------------------------------------------------
diff --git a/perl/xs/Clownfish/VTable.c b/perl/xs/Clownfish/VTable.c
deleted file mode 100644
index 5287924..0000000
--- a/perl/xs/Clownfish/VTable.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define C_LUCY_OBJ
-#define C_LUCY_VTABLE
-#include "XSBind.h"
-
-#include "Clownfish/VTable.h"
-#include "Clownfish/Host.h"
-#include "Clownfish/Util/Memory.h"
-
-lucy_Obj*
-lucy_VTable_foster_obj(lucy_VTable *self, void *host_obj) {
- lucy_Obj *obj
- = (lucy_Obj*)lucy_Memory_wrapped_calloc(self->obj_alloc_size, 1);
- SV *inner_obj = SvRV((SV*)host_obj);
- obj->vtable = self;
- sv_setiv(inner_obj, PTR2IV(obj));
- obj->ref.host_obj = inner_obj;
- return obj;
-}
-
-void
-lucy_VTable_register_with_host(lucy_VTable *singleton, lucy_VTable *parent) {
- // Register class with host.
- lucy_Host_callback(LUCY_VTABLE, "_register", 2,
- CFISH_ARG_OBJ("singleton", singleton),
- CFISH_ARG_OBJ("parent", parent));
-}
-
-lucy_VArray*
-lucy_VTable_fresh_host_methods(const lucy_CharBuf *class_name) {
- return (lucy_VArray*)lucy_Host_callback_obj(
- LUCY_VTABLE,
- "fresh_host_methods", 1,
- CFISH_ARG_STR("class_name", class_name));
-}
-
-lucy_CharBuf*
-lucy_VTable_find_parent_class(const lucy_CharBuf *class_name) {
- return lucy_Host_callback_str(LUCY_VTABLE, "find_parent_class", 1,
- CFISH_ARG_STR("class_name", class_name));
-}
-
-void*
-lucy_VTable_to_host(lucy_VTable *self) {
- chy_bool_t first_time = self->ref.count < 4 ? true : false;
- Lucy_VTable_To_Host_t to_host
- = CFISH_SUPER_METHOD_PTR(LUCY_VTABLE, Lucy_VTable_To_Host);
- SV *host_obj = (SV*)to_host(self);
- if (first_time) {
- SvSHARE((SV*)self->ref.host_obj);
- }
- return host_obj;
-}
-
-
http://git-wip-us.apache.org/repos/asf/lucy/blob/f6a05ea6/perl/xs/XSBind.c
----------------------------------------------------------------------
diff --git a/perl/xs/XSBind.c b/perl/xs/XSBind.c
index ee28681..c210f01 100644
--- a/perl/xs/XSBind.c
+++ b/perl/xs/XSBind.c
@@ -15,10 +15,15 @@
*/
#define C_LUCY_OBJ
+#define C_LUCY_VTABLE
+#define C_LUCY_LOCKFREEREGISTRY
#define NEED_newRV_noinc
#include "XSBind.h"
+#include "Clownfish/Host.h"
+#include "Clownfish/LockFreeRegistry.h"
#include "Clownfish/Util/StringHelper.h"
#include "Clownfish/Util/NumberUtils.h"
+#include "Clownfish/Util/Memory.h"
// Convert a Perl hash into a Clownfish Hash. Caller takes responsibility for
// a refcount.
@@ -579,4 +584,284 @@ XSBind_allot_params(SV** stack, int32_t start, int32_t num_stack_elems, ...) {
return true;
}
+/***************************************************************************
+ * The routines below are declared within the Clownfish core but left
+ * unimplemented and must be defined for each host language.
+ ***************************************************************************/
+
+/**************************** Clownfish::Obj *******************************/
+
+static void
+S_lazy_init_host_obj(lucy_Obj *self) {
+ SV *inner_obj = newSV(0);
+ SvOBJECT_on(inner_obj);
+ PL_sv_objcount++;
+ SvUPGRADE(inner_obj, SVt_PVMG);
+ sv_setiv(inner_obj, PTR2IV(self));
+
+ // Connect class association.
+ lucy_CharBuf *class_name = Lucy_VTable_Get_Name(self->vtable);
+ HV *stash = gv_stashpvn((char*)Lucy_CB_Get_Ptr8(class_name),
+ Lucy_CB_Get_Size(class_name), TRUE);
+ SvSTASH_set(inner_obj, (HV*)SvREFCNT_inc(stash));
+
+ /* Up till now we've been keeping track of the refcount in
+ * self->ref.count. We're replacing ref.count with ref.host_obj, which
+ * will assume responsibility for maintaining the refcount. ref.host_obj
+ * starts off with a refcount of 1, so we need to transfer any refcounts
+ * in excess of that. */
+ size_t old_refcount = self->ref.count;
+ self->ref.host_obj = inner_obj;
+ while (old_refcount > 1) {
+ SvREFCNT_inc_simple_void_NN(inner_obj);
+ old_refcount--;
+ }
+}
+
+uint32_t
+lucy_Obj_get_refcount(lucy_Obj *self) {
+ return self->ref.count < 4
+ ? self->ref.count
+ : SvREFCNT((SV*)self->ref.host_obj);
+}
+
+lucy_Obj*
+lucy_Obj_inc_refcount(lucy_Obj *self) {
+ switch (self->ref.count) {
+ case 0:
+ CFISH_THROW(LUCY_ERR, "Illegal refcount of 0");
+ break; // useless
+ case 1:
+ case 2:
+ self->ref.count++;
+ break;
+ case 3:
+ S_lazy_init_host_obj(self);
+ // fall through
+ default:
+ SvREFCNT_inc_simple_void_NN((SV*)self->ref.host_obj);
+ }
+ return self;
+}
+
+uint32_t
+lucy_Obj_dec_refcount(lucy_Obj *self) {
+ uint32_t modified_refcount = I32_MAX;
+ switch (self->ref.count) {
+ case 0:
+ CFISH_THROW(LUCY_ERR, "Illegal refcount of 0");
+ break; // useless
+ case 1:
+ modified_refcount = 0;
+ Lucy_Obj_Destroy(self);
+ break;
+ case 2:
+ case 3:
+ modified_refcount = --self->ref.count;
+ break;
+ default:
+ modified_refcount = SvREFCNT((SV*)self->ref.host_obj) - 1;
+ // If the SV's refcount falls to 0, DESTROY will be invoked from
+ // Perl-space.
+ SvREFCNT_dec((SV*)self->ref.host_obj);
+ }
+ return modified_refcount;
+}
+
+void*
+lucy_Obj_to_host(lucy_Obj *self) {
+ if (self->ref.count < 4) { S_lazy_init_host_obj(self); }
+ return newRV_inc((SV*)self->ref.host_obj);
+}
+
+/*************************** Clownfish::VTable ******************************/
+
+lucy_Obj*
+lucy_VTable_foster_obj(lucy_VTable *self, void *host_obj) {
+ lucy_Obj *obj
+ = (lucy_Obj*)lucy_Memory_wrapped_calloc(self->obj_alloc_size, 1);
+ SV *inner_obj = SvRV((SV*)host_obj);
+ obj->vtable = self;
+ sv_setiv(inner_obj, PTR2IV(obj));
+ obj->ref.host_obj = inner_obj;
+ return obj;
+}
+
+void
+lucy_VTable_register_with_host(lucy_VTable *singleton, lucy_VTable *parent) {
+ // Register class with host.
+ lucy_Host_callback(LUCY_VTABLE, "_register", 2,
+ CFISH_ARG_OBJ("singleton", singleton),
+ CFISH_ARG_OBJ("parent", parent));
+}
+
+lucy_VArray*
+lucy_VTable_fresh_host_methods(const lucy_CharBuf *class_name) {
+ return (lucy_VArray*)lucy_Host_callback_obj(
+ LUCY_VTABLE,
+ "fresh_host_methods", 1,
+ CFISH_ARG_STR("class_name", class_name));
+}
+
+lucy_CharBuf*
+lucy_VTable_find_parent_class(const lucy_CharBuf *class_name) {
+ return lucy_Host_callback_str(LUCY_VTABLE, "find_parent_class", 1,
+ CFISH_ARG_STR("class_name", class_name));
+}
+
+void*
+lucy_VTable_to_host(lucy_VTable *self) {
+ chy_bool_t first_time = self->ref.count < 4 ? true : false;
+ Lucy_VTable_To_Host_t to_host
+ = CFISH_SUPER_METHOD_PTR(LUCY_VTABLE, Lucy_VTable_To_Host);
+ SV *host_obj = (SV*)to_host(self);
+ if (first_time) {
+ SvSHARE((SV*)self->ref.host_obj);
+ }
+ return host_obj;
+}
+
+
+/***************************** Clownfish::Err *******************************/
+
+// Anonymous XSUB helper for Err#trap(). It wraps the supplied C function
+// so that it can be run inside a Perl eval block.
+static SV *attempt_xsub = NULL;
+
+XS(lucy_Err_attempt_via_xs) {
+ dXSARGS;
+ CHY_UNUSED_VAR(cv);
+ SP -= items;
+ if (items != 2) {
+ CFISH_THROW(CFISH_ERR, "Usage: $sub->(routine, context)");
+ };
+ IV routine_iv = SvIV(ST(0));
+ IV context_iv = SvIV(ST(1));
+ Cfish_Err_Attempt_t routine = INT2PTR(Cfish_Err_Attempt_t, routine_iv);
+ void *context = INT2PTR(void*, context_iv);
+ routine(context);
+ XSRETURN(0);
+}
+
+void
+lucy_Err_init_class(void) {
+ char *file = (char*)__FILE__;
+ attempt_xsub = (SV*)newXS(NULL, lucy_Err_attempt_via_xs, file);
+}
+
+lucy_Err*
+lucy_Err_get_error() {
+ lucy_Err *error
+ = (lucy_Err*)lucy_Host_callback_obj(LUCY_ERR, "get_error", 0);
+ CFISH_DECREF(error); // Cancel out incref from callback.
+ return error;
+}
+
+void
+lucy_Err_set_error(lucy_Err *error) {
+ lucy_Host_callback(LUCY_ERR, "set_error", 1,
+ CFISH_ARG_OBJ("error", error));
+ CFISH_DECREF(error);
+}
+
+void
+lucy_Err_do_throw(lucy_Err *err) {
+ dSP;
+ SV *error_sv = (SV*)Lucy_Err_To_Host(err);
+ CFISH_DECREF(err);
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
+ XPUSHs(sv_2mortal(error_sv));
+ PUTBACK;
+ call_pv("Clownfish::Err::do_throw", G_DISCARD);
+ FREETMPS;
+ LEAVE;
+}
+
+void*
+lucy_Err_to_host(lucy_Err *self) {
+ Lucy_Err_To_Host_t super_to_host
+ = CFISH_SUPER_METHOD_PTR(LUCY_ERR, Lucy_Err_To_Host);
+ SV *perl_obj = (SV*)super_to_host(self);
+ XSBind_enable_overload(perl_obj);
+ return perl_obj;
+}
+
+void
+lucy_Err_throw_mess(lucy_VTable *vtable, lucy_CharBuf *message) {
+ Lucy_Err_Make_t make
+ = CFISH_METHOD_PTR(CFISH_CERTIFY(vtable, LUCY_VTABLE), Lucy_Err_Make);
+ lucy_Err *err = (lucy_Err*)CFISH_CERTIFY(make(NULL), LUCY_ERR);
+ Lucy_Err_Cat_Mess(err, message);
+ CFISH_DECREF(message);
+ lucy_Err_do_throw(err);
+}
+
+void
+lucy_Err_warn_mess(lucy_CharBuf *message) {
+ SV *error_sv = XSBind_cb_to_sv(message);
+ CFISH_DECREF(message);
+ warn("%s", SvPV_nolen(error_sv));
+ SvREFCNT_dec(error_sv);
+}
+
+lucy_Err*
+lucy_Err_trap(Cfish_Err_Attempt_t routine, void *context) {
+ lucy_Err *error = NULL;
+ SV *routine_sv = newSViv(PTR2IV(routine));
+ SV *context_sv = newSViv(PTR2IV(context));
+ dSP;
+ ENTER;
+ SAVETMPS;
+ PUSHMARK(SP);
+ EXTEND(SP, 2);
+ PUSHs(sv_2mortal(routine_sv));
+ PUSHs(sv_2mortal(context_sv));
+ PUTBACK;
+
+ int count = call_sv(attempt_xsub, G_EVAL | G_DISCARD);
+ if (count != 0) {
+ lucy_CharBuf *mess
+ = lucy_CB_newf("'attempt' returned too many values: %i32",
+ (int32_t)count);
+ error = lucy_Err_new(mess);
+ }
+ else {
+ SV *dollar_at = get_sv("@", FALSE);
+ if (SvTRUE(dollar_at)) {
+ if (sv_isobject(dollar_at)
+ && sv_derived_from(dollar_at,"Clownfish::Err")
+ ) {
+ IV error_iv = SvIV(SvRV(dollar_at));
+ error = INT2PTR(lucy_Err*, error_iv);
+ CFISH_INCREF(error);
+ }
+ else {
+ STRLEN len;
+ char *ptr = SvPVutf8(dollar_at, len);
+ lucy_CharBuf *mess = lucy_CB_new_from_trusted_utf8(ptr, len);
+ error = lucy_Err_new(mess);
+ }
+ }
+ }
+ FREETMPS;
+ LEAVE;
+
+ return error;
+}
+
+/*********************** Clownfish::LockFreeRegistry ************************/
+
+void*
+lucy_LFReg_to_host(lucy_LockFreeRegistry *self) {
+ chy_bool_t first_time = self->ref.count < 4 ? true : false;
+ Lucy_LFReg_To_Host_t to_host
+ = CFISH_SUPER_METHOD_PTR(LUCY_LOCKFREEREGISTRY, Lucy_LFReg_To_Host);
+ SV *host_obj = (SV*)to_host(self);
+ if (first_time) {
+ SvSHARE((SV*)self->ref.host_obj);
+ }
+ return host_obj;
+}