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 2009/09/15 02:55:31 UTC

svn commit: r814946 - in /lucene/lucy/trunk: core/Lucy/Object/ core/Lucy/Test/Object/ perl/lib/Lucy/Object/ perl/t/core/ perl/xs/Lucy/ perl/xs/Lucy/Object/

Author: marvin
Date: Tue Sep 15 00:55:31 2009
New Revision: 814946

URL: http://svn.apache.org/viewvc?rev=814946&view=rev
Log:
Commit LUCY-41, adding Lucy::Object::Obj -- the class from which all
instantiable Lucy classes descend.

Added:
    lucene/lucy/trunk/core/Lucy/Object/
    lucene/lucy/trunk/core/Lucy/Object/Obj.bp   (with props)
    lucene/lucy/trunk/core/Lucy/Object/Obj.c   (with props)
    lucene/lucy/trunk/core/Lucy/Test/Object/
    lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.bp   (with props)
    lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.c   (with props)
    lucene/lucy/trunk/perl/lib/Lucy/Object/
    lucene/lucy/trunk/perl/lib/Lucy/Object/Obj.pm   (with props)
    lucene/lucy/trunk/perl/t/core/019-obj.t   (with props)
    lucene/lucy/trunk/perl/xs/Lucy/
    lucene/lucy/trunk/perl/xs/Lucy/Object/
    lucene/lucy/trunk/perl/xs/Lucy/Object/Obj.c   (with props)

Added: lucene/lucy/trunk/core/Lucy/Object/Obj.bp
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Object/Obj.bp?rev=814946&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Object/Obj.bp (added)
+++ lucene/lucy/trunk/core/Lucy/Object/Obj.bp Tue Sep 15 00:55:31 2009
@@ -0,0 +1,209 @@
+parcel Lucy;
+
+/** Base class for all Lucy objects.
+ */
+
+class Lucy::Object::Obj {
+
+    VTable *vtable;
+    lucy_ref_t ref;
+
+    /** Abstract initializer.
+     */
+    public inert Obj*
+    init(Obj* self);
+
+    /** Zero argument factory constructor.
+     */
+    public abstract incremented Obj*
+    Make(Obj *self);
+
+    /** Return an object's refcount.
+     */
+    u32_t
+    Get_RefCount(Obj *self);
+
+    /** Increment an object's refcount.
+     * 
+     * @return The object, allowing an assignment idiom.
+     */
+    incremented Obj* 
+    Inc_RefCount(Obj *self);
+
+    /** NULL-safe invocation of Inc_RefCount().
+     *
+     * @return NULL if <code>self</code> is NULL, otherwise the return value
+     * of Inc_RefCount().
+     */
+    inert inline incremented Obj*
+    incref(Obj *self);
+
+    /** Decrement an object's refcount, calling Destroy() if it hits 0.
+     * 
+     * @return the modified refcount.
+     */
+    u32_t
+    Dec_RefCount(Obj *self);
+
+    /** NULL-safe invocation of Dec_RefCount().
+     *
+     * @return NULL if <code>self</code> is NULL, otherwise the return value
+     * of Dec_RefCount().
+     */
+    inert inline u32_t 
+    decref(Obj *self);
+
+    /** Return a host-language object wrapper for this object.
+     */
+    void*
+    To_Host(Obj *self);
+
+    /** Return a clone of the object.
+     */
+    public abstract incremented Obj*
+    Clone(Obj *self);
+
+    /** Generic destructor.  Frees the struct itself but not any complex
+     * member elements.
+     */
+    public void
+    Destroy(Obj *self);
+
+    /** Invoke the Destroy() method found in <code>vtable</code> on
+     * <code>self</code>.
+     * 
+     * TODO: Eliminate this function if we can arrive at a proper SUPER syntax.
+     */
+    inert inline void
+    super_destroy(Obj *self, VTable *vtable);
+
+    /** Indicate whether two objects are the same.  By default, compares the
+     * memory address.
+     *
+     * @param other Another Obj.
+     */
+    public bool_t
+    Equals(Obj *self, Obj *other);
+
+    /** Indicate whether one object is less than, equal to, or greater than
+     * another.
+     *
+     * @param other Another Obj.
+     * @return 0 if the objects are equal, a negative number if
+     * <code>self</code> is less than <code>other</code>, and a positive
+     * number if <code>self</code> is greater than <code>other</code>.
+     */
+    public abstract i32_t
+    Compare_To(Obj *self, Obj *other);
+
+    /** Return a hash code for the object -- by default, the memory address.
+     */
+    public i32_t
+    Hash_Code(Obj *self);
+
+    /** Return the object's VTable.
+     */
+    public VTable*
+    Get_VTable(Obj *self);
+
+    /** Return the name of the class that the object belongs to.
+     */
+    public CharBuf*
+    Get_Class_Name(Obj *self);
+
+    /** Indicate whether the object is a descendent of <code>ancestor</code>.
+     */
+    public bool_t
+    Is_A(Obj *self, VTable *ancestor);
+
+    /** Generic stringification: "ClassName@hex_mem_address".
+     */
+    public incremented CharBuf*
+    To_String(Obj *self);
+
+    /** Convert the object to a 64-bit integer. 
+     */
+    public abstract i64_t
+    To_I64(Obj *self);
+
+    /** Convert the object to a double precision floating point number.
+     */
+    public abstract double
+    To_F64(Obj *self);
+
+    /** Return a representation of the object using only scalars, hashes, and
+     * arrays.  Some implementations support JSON serialization via Dump() and
+     * its companion method, Load(); for others, Dump() is only a debugging
+     * aid.  The default simply calls To_String().
+     */
+    public incremented Obj*
+    Dump(Obj *self);
+
+    /** Create an object from the output of a call to Dump().  Implementations
+     * should not reference the caller.
+     * 
+     * @param dump The output of Dump().  
+     */
+    public abstract incremented Obj*
+    Load(Obj *self, Obj *dump);
+
+    /** Update the internal state of the object to mimic that of
+     * <code>other</code>. 
+     */
+    public abstract void
+    Mimic(Obj *self, Obj *other);
+}
+
+__C__
+static CHY_INLINE void
+lucy_Obj_super_destroy(lucy_Obj *self, lucy_VTable *vtable)
+{
+    lucy_Obj_destroy_t super_destroy 
+        = (lucy_Obj_destroy_t)LUCY_SUPER_METHOD(vtable, Obj, Destroy);
+    super_destroy(self);
+}
+
+#define LUCY_SUPER_DESTROY(_self, _vtable) \
+    lucy_Obj_super_destroy((lucy_Obj*)_self, _vtable)
+
+static CHY_INLINE lucy_Obj* 
+lucy_Obj_incref(lucy_Obj *self)
+{
+    if (self != NULL) { return Lucy_Obj_Inc_RefCount(self); }
+    else { return NULL; }
+}
+
+#define LUCY_INCREF(_self) lucy_Obj_incref((lucy_Obj*)_self)
+
+static CHY_INLINE chy_u32_t 
+lucy_Obj_decref(lucy_Obj *self)
+{
+    if (self != NULL) { return Lucy_Obj_Dec_RefCount(self); }
+    else { return 0; }
+}
+
+#define LUCY_DECREF(_self) lucy_Obj_decref((lucy_Obj*)_self)
+
+#ifdef LUCY_USE_SHORT_NAMES
+  #define SUPER_DESTROY(_self, _vtable)   LUCY_SUPER_DESTROY(_self, _vtable)
+  #define INCREF(_self)                   LUCY_INCREF(_self)
+  #define DECREF(_self)                   LUCY_DECREF(_self)
+#endif
+
+__END_C__
+
+/* Copyright 2009 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Object/Obj.bp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/core/Lucy/Object/Obj.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Object/Obj.c?rev=814946&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Object/Obj.c (added)
+++ lucene/lucy/trunk/core/Lucy/Object/Obj.c Tue Sep 15 00:55:31 2009
@@ -0,0 +1,96 @@
+#define C_LUCY_OBJ
+#define C_LUCY_VTABLE
+#define LUCY_USE_SHORT_NAMES
+#define CHY_USE_SHORT_NAMES
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "Lucy/Object/Obj.h"
+#include "Lucy/Object/CharBuf.h"
+#include "Lucy/Object/Err.h"
+#include "Lucy/Object/Hash.h"
+#include "Lucy/Object/VTable.h"
+#include "Lucy/Util/Memory.h"
+
+Obj*
+Obj_init(Obj *self)
+{
+    ABSTRACT_CLASS_CHECK(self, OBJ);
+    return self;
+}
+
+void
+Obj_destroy(Obj *self)
+{
+    Obj_Dec_RefCount(self->vtable);
+    FREEMEM(self);
+}
+
+i32_t
+Obj_hash_code(Obj *self)
+{
+    return (i32_t)self;
+}
+
+bool_t
+Obj_is_a(Obj *self, VTable *ancestor)
+{
+    VTable *vtable = self ? self->vtable : NULL;
+
+    while (vtable != NULL) {
+        if (vtable == ancestor)
+            return true;
+        vtable = vtable->parent;
+    }
+
+    return false;
+}
+
+bool_t
+Obj_equals(Obj *self, Obj *other)
+{
+    return (self == other);
+}
+
+CharBuf*
+Obj_to_string(Obj *self)
+{
+#if (SIZEOF_PTR == 4)
+    return CB_newf("%o@0x%x32", Obj_Get_Class_Name(self), self);
+#elif (SIZEOF_PTR == 8)
+    size_t address = self;
+    u32_t  address_hi = address >> 32;
+    u32_t  address_lo = address & 0xFFFFFFFF;
+    return CB_newf("%o@0x%x32%x32", Obj_Get_Class_Name(self), address_hi,
+        address_lo);
+#endif
+}
+
+Obj*
+Obj_dump(Obj *self)
+{
+    return (Obj*)Obj_To_String(self);
+}
+
+VTable*
+Obj_get_vtable(Obj *self) { return self->vtable; }
+CharBuf*
+Obj_get_class_name(Obj *self) { return VTable_Get_Name(self->vtable); }
+
+/* Copyright 2009 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Object/Obj.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.bp
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.bp?rev=814946&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.bp (added)
+++ lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.bp Tue Sep 15 00:55:31 2009
@@ -0,0 +1,22 @@
+parcel Lucy;
+
+inert class Lucy::Test::Object::TestObj {
+    inert void
+    run_tests();
+}
+
+/* Copyright 2009 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.bp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.c?rev=814946&view=auto
==============================================================================
--- lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.c (added)
+++ lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.c Tue Sep 15 00:55:31 2009
@@ -0,0 +1,138 @@
+#define C_LUCY_TESTOBJ
+#include "Lucy/Util/ToolSet.h"
+
+#include "Lucy/Test.h"
+#include "Lucy/Test/Object/TestObj.h"
+
+static Obj*
+S_new_testobj()
+{
+    static ZombieCharBuf klass = ZCB_LITERAL("TestObj");
+    Obj *obj;
+    VTable *vtable = VTable_fetch_vtable((CharBuf*)&klass);
+    if (!vtable) {
+        vtable = VTable_singleton((CharBuf*)&klass, OBJ);
+    }
+    obj = VTable_Make_Obj(vtable);
+    return Obj_init(obj);
+}
+
+static void
+test_refcounts(TestBatch *batch)
+{
+    Obj     *obj      = S_new_testobj();
+
+    ASSERT_INT_EQ(batch, Obj_Get_RefCount(obj), 1, 
+        "Correct starting refcount");
+
+    Obj_Inc_RefCount(obj);
+    ASSERT_INT_EQ(batch, Obj_Get_RefCount(obj), 2, "Inc_RefCount" );
+
+    Obj_Dec_RefCount(obj);
+    ASSERT_INT_EQ(batch, Obj_Get_RefCount(obj), 1, "Dec_RefCount" );
+
+    DECREF(obj);
+}
+
+static void
+test_To_String(TestBatch *batch)
+{
+    Obj *testobj = S_new_testobj();
+    CharBuf *string = Obj_To_String(testobj);
+    ZombieCharBuf temp = ZCB_make(string);
+    while(ZCB_Get_Size(&temp)) {
+        if (ZCB_Starts_With_Str(&temp, "TestObj", 7)) { break; }
+        ZCB_Nip_One(&temp);
+    }
+    ASSERT_TRUE(batch, ZCB_Starts_With_Str(&temp, "TestObj", 7), "To_String");
+    DECREF(string);
+    DECREF(testobj);
+}
+
+static void
+test_Dump(TestBatch *batch)
+{
+    Obj *testobj = S_new_testobj();
+    CharBuf *string = Obj_To_String(testobj);
+    Obj *dump = Obj_Dump(testobj);
+    ASSERT_TRUE(batch, Obj_Equals(dump, (Obj*)string), 
+        "Default Dump returns To_String");
+    DECREF(dump);
+    DECREF(string);
+    DECREF(testobj);
+}
+
+static void
+test_Equals(TestBatch *batch)
+{
+    Obj *testobj = S_new_testobj();
+    Obj *other   = S_new_testobj();
+
+    ASSERT_TRUE(batch, Obj_Equals(testobj, testobj), 
+        "Equals is true for the same object");
+    ASSERT_FALSE(batch, Obj_Equals(testobj, other), 
+        "Distinct objects are not equal");
+
+    DECREF(testobj);
+    DECREF(other);
+}
+
+static void
+test_Hash_Code(TestBatch *batch)
+{
+    Obj *testobj = S_new_testobj();
+    i32_t address = (i32_t)testobj;
+    ASSERT_TRUE(batch, (Obj_Hash_Code(testobj) == address), 
+        "Hash_Code uses memory address");
+    DECREF(testobj);
+}
+
+static void
+test_Is_A(TestBatch *batch)
+{
+    CharBuf *charbuf   = CB_new(0);
+    VTable  *bb_vtable = CB_Get_VTable(charbuf);
+    CharBuf *klass     = Obj_Get_Class_Name(charbuf);
+
+    ASSERT_TRUE(batch, Obj_Is_A(charbuf, CHARBUF), "CharBuf Is_A CharBuf.");
+    ASSERT_TRUE(batch, Obj_Is_A(charbuf, OBJ), "CharBuf Is_A Obj.");
+    ASSERT_TRUE(batch, bb_vtable == CHARBUF, "Get_VTable");
+    ASSERT_TRUE(batch, CB_Equals(VTable_Get_Name(CHARBUF), (Obj*)klass),
+        "Get_Class_Name");
+
+    DECREF(charbuf);
+}
+
+
+void
+TestObj_run_tests()
+{
+    TestBatch *batch = Test_new_batch("TestObj", 12, NULL);
+
+    PLAN(batch);
+
+    test_refcounts(batch);
+    test_To_String(batch);
+    test_Dump(batch);
+    test_Equals(batch);
+    test_Hash_Code(batch);
+    test_Is_A(batch);
+
+    batch->destroy(batch);
+}
+
+/* Copyright 2009 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+

Propchange: lucene/lucy/trunk/core/Lucy/Test/Object/TestObj.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/perl/lib/Lucy/Object/Obj.pm
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/perl/lib/Lucy/Object/Obj.pm?rev=814946&view=auto
==============================================================================
--- lucene/lucy/trunk/perl/lib/Lucy/Object/Obj.pm (added)
+++ lucene/lucy/trunk/perl/lib/Lucy/Object/Obj.pm Tue Sep 15 00:55:31 2009
@@ -0,0 +1,78 @@
+use Lucy;
+
+1;
+
+__END__
+
+__BINDING__
+
+my $xs_code = <<'END_XS_CODE';
+MODULE = Lucy     PACKAGE = Lucy::Object::Obj
+
+chy_bool_t
+is_a(self, class_name)
+    lucy_Obj *self;
+    lucy_ZombieCharBuf class_name;
+CODE:
+{
+    lucy_VTable *target = lucy_VTable_fetch_vtable((lucy_CharBuf*)&class_name);
+    RETVAL = Lucy_Obj_Is_A(self, target);
+}
+OUTPUT: RETVAL
+
+void
+DESTROY(self)
+    lucy_Obj *self;
+PPCODE:
+    /*
+    {
+        char *perl_class = HvNAME(SvSTASH(SvRV(ST(0))));
+        warn("Destroying: 0x%x %s", (unsigned)self, perl_class);
+    }
+    */
+    Lucy_Obj_Destroy(self);
+END_XS_CODE
+
+Boilerplater::Binding::Perl::Class->register(
+    parcel       => "Lucy",
+    class_name   => "Lucy::Object::Obj",
+    xs_code      => $xs_code,
+    bind_methods => [
+        qw(
+            Get_RefCount
+            Inc_RefCount
+            Dec_RefCount
+            Get_VTable
+            To_String
+            To_I64
+            To_F64
+            Dump
+            _load|Load
+            Clone
+            Mimic
+            Equals
+            Hash_Code
+            Destroy
+            )
+    ],
+    bind_constructors => ["new"],
+);
+
+__COPYRIGHT__
+
+    /**
+     * Copyright 2009 The Apache Software Foundation
+     *
+     * Licensed 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.
+     */
+

Propchange: lucene/lucy/trunk/perl/lib/Lucy/Object/Obj.pm
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/perl/t/core/019-obj.t
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/perl/t/core/019-obj.t?rev=814946&view=auto
==============================================================================
--- lucene/lucy/trunk/perl/t/core/019-obj.t (added)
+++ lucene/lucy/trunk/perl/t/core/019-obj.t Tue Sep 15 00:55:31 2009
@@ -0,0 +1,6 @@
+use strict;
+use warnings;
+
+use Lucy::Test;
+Lucy::Test::run_tests("TestObj");
+

Propchange: lucene/lucy/trunk/perl/t/core/019-obj.t
------------------------------------------------------------------------------
    svn:eol-style = native

Added: lucene/lucy/trunk/perl/xs/Lucy/Object/Obj.c
URL: http://svn.apache.org/viewvc/lucene/lucy/trunk/perl/xs/Lucy/Object/Obj.c?rev=814946&view=auto
==============================================================================
--- lucene/lucy/trunk/perl/xs/Lucy/Object/Obj.c (added)
+++ lucene/lucy/trunk/perl/xs/Lucy/Object/Obj.c Tue Sep 15 00:55:31 2009
@@ -0,0 +1,125 @@
+#define C_LUCY_OBJ
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include "ppport.h"
+
+#include "Lucy/Object/Obj.h"
+#include "Lucy/Object/CharBuf.h"
+#include "Lucy/Object/Err.h"
+#include "Lucy/Object/VTable.h"
+#include "Lucy/Util/Memory.h"
+
+static void
+S_lazy_init_host_obj(lucy_Obj *self) 
+{
+    size_t old_refcount = self->ref.count;
+
+    /* Find the Perl stash entry. */
+    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);
+
+    /* In Perl, object SVs are never accessed directly; they are always
+     * wrapped within a reference SV.  However, we have no need for the extra
+     * level of indirection, so we create the inner object directly and avoid
+     * the extra allocation.  If and when we need to send the object back into
+     * Perl space, we'll create the RV (in To_Host).
+     * 
+     * (Note: Some code cribbed from Perl_sv_bless, in sv.c.) */
+    SV *inner_obj = newSV(0);
+    SvOBJECT_on(inner_obj);
+    PL_sv_objcount++;
+    SvUPGRADE(inner_obj, SVt_PVMG);
+    SvSTASH_set(inner_obj, (HV*)SvREFCNT_inc(stash));
+    sv_setiv(inner_obj, PTR2IV(self));
+
+    /* 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. */
+    self->ref.host_obj = inner_obj;
+    while(old_refcount > 1) {
+        SvREFCNT_inc_simple_void_NN(inner_obj);
+        old_refcount--;
+    }
+}
+
+chy_u32_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:
+            LUCY_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;
+}
+
+chy_u32_t
+lucy_Obj_dec_refcount(lucy_Obj *self)
+{
+    chy_u32_t modified_refcount = I32_MAX;
+    switch (self->ref.count) {
+        case 0:
+            LUCY_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);
+}
+
+/* Copyright 2009 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+

Propchange: lucene/lucy/trunk/perl/xs/Lucy/Object/Obj.c
------------------------------------------------------------------------------
    svn:eol-style = native