OSDN Git Service

Handling of Molecule object was not consistent. Hopefully fixed...
authortoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Tue, 24 Jul 2012 17:21:47 +0000 (17:21 +0000)
committertoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Tue, 24 Jul 2012 17:21:47 +0000 (17:21 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@267 a2be9bc6-48de-4e38-9406-05402d4bc13c

MolLib/Molecule.c
MolLib/Molecule.h
MolLib/Ruby_bind/ruby_bind.c

index 53f29bb..f794212 100755 (executable)
@@ -443,6 +443,7 @@ Molecule *
 MoleculeRetain(Molecule *mp)
 {
        ObjectIncrRefCount((Object *)mp);
+       MoleculeRetainExternalObj(mp);
        return mp;
 }
 
@@ -548,10 +549,7 @@ MoleculeRelease(Molecule *mp)
 {
        if (mp == NULL)
                return;
-       if (mp->exmolobj != NULL) {
-               MoleculeReleaseExternalHook(mp);
-               mp->exmolobj = NULL;
-       }
+       MoleculeReleaseExternalObj(mp);
        if (ObjectDecrRefCount((Object *)mp) == 0) {
                MoleculeClear(mp);
                ObjectDealloc((Object *)mp, (Object **)&sMoleculeRoot);
index 52c2565..bf8482b 100755 (executable)
@@ -333,6 +333,7 @@ typedef struct Molecule {
        
        /*  Ruby pointer (see ruby_bind.c)  */
        void *exmolobj;
+       Byte exmolobjProtected;
 
 } Molecule;
 
@@ -355,7 +356,6 @@ const char *MoleculeGetPath(Molecule *mol);
 Molecule *MoleculeWithName(const char *name);
 Molecule *MoleculeRetain(Molecule *mp);
 void MoleculeRelease(Molecule *mp);
-extern void MoleculeReleaseExternalHook(Molecule *mol);
 void MoleculeExchange(Molecule *mp1, Molecule *mp2);
 
 int MoleculeAddGaussianOrbitalShell(Molecule *mol, Int sym, Int nprims, Int a_idx);
@@ -523,6 +523,9 @@ int MoleculeOutputCube(Molecule *mp, Int index, const char *fname, const char *c
 extern char *gMoleculePasteboardType;
 extern char *gParameterPasteboardType;
 
+STUB void MoleculeRetainExternalObj(Molecule *mol);
+STUB void MoleculeReleaseExternalObj(Molecule *mol);
+
 STUB int MoleculeCallback_writeToPasteboard(const char *type, const void *data, int length);
 STUB int MoleculeCallback_readFromPasteboard(const char *type, void **dptr, int *length);
 STUB int MoleculeCallback_isDataInPasteboard(const char *type);
index 53af174..0fa5432 100644 (file)
@@ -4154,23 +4154,52 @@ MoleculeFromValue(VALUE val)
 
 static VALUE sMoleculeRetainArray = Qnil;
 
-/*  The hook function to be called from MoleculeRelease()  */
+/*  The function is called from MoleculeRelease()  */
 /*  The Ruby Molecule object is held as mol->exmolobj, and is also protected from */
 /*  GC by registering in the sMoleculeRetainArray. This causes the same Ruby */
 /*  object is always returned for the same Molecule.  */
-/*  When the reference count of the Molecule becomes 1, then the Ruby object becomes */
-/*  unprotected from GC. In this situation, the Molecule is retained only by the */
-/*  currently alive Ruby objects, and when the last Ruby Molecule object is collected */
-/*  by GC, the Molecule structure is properly released. */
+/*  When the reference count of the Molecule becomes 1, then the Ruby object is */
+/*  removed from sMoleculeRetainArray. In this situation, the Molecule is retained  */
+/*  only by the currently alive Ruby containers.  When the Ruby Molecule object is */
+/*  removed from all alive Ruby containers, the Ruby object will be collected by */
+/*  the next GC invocation, and at that time the Molecule structure is properly released. */
+
+/*  Register/unregister the exmolobj Ruby object  */
 void
-MoleculeReleaseExternalHook(Molecule *mol)
+MoleculeReleaseExternalObj(Molecule *mol)
 {
-       if (mol->base.refCount == 2) {
-               /*  The reference count will become 1: remove the Ruby object from sMoleculeRetainArray  */
+       if (mol != NULL && mol->base.refCount <= 2 && mol->exmolobjProtected == 1) {
                rb_ary_delete(sMoleculeRetainArray, (VALUE)mol->exmolobj);
+               mol->exmolobjProtected = 0;
+       }
+}
+
+void
+MoleculeRetainExternalObj(Molecule *mol)
+{
+       if (mol != NULL && mol->base.refCount >= 2 && mol->exmolobj != NULL && mol->exmolobjProtected == 0) {
+               if (sMoleculeRetainArray == Qnil) {
+                       rb_define_readonly_variable("molecules", &sMoleculeRetainArray);
+                       sMoleculeRetainArray = rb_ary_new();
+               }
+               
+               rb_ary_push(sMoleculeRetainArray, (VALUE)mol->exmolobj);
+               mol->exmolobjProtected = 1;
        }
 }
 
+/*  Release hook function for Ruby  */
+void
+MoleculeReleaseHook(Molecule *mol)
+{
+       if (mol->exmolobj != NULL) {
+               /*  No need to remove from sMoleculeRetainArray  */
+               mol->exmolobj = NULL;
+               mol->exmolobjProtected = 0;
+       }
+       MoleculeRelease(mol);
+}
+
 VALUE
 ValueFromMolecule(Molecule *mol)
 {
@@ -4178,17 +4207,22 @@ ValueFromMolecule(Molecule *mol)
                return Qnil;
        if (mol->exmolobj != NULL)
                return (VALUE)mol->exmolobj;
-       MoleculeRetain(mol);
-       mol->exmolobj = (void *)Data_Wrap_Struct(rb_cMolecule, 0, (void (*)(void *))MoleculeRelease, mol);
-       /*  Register this object to protect from GC  */
-       if (sMoleculeRetainArray == Qnil) {
-               rb_define_readonly_variable("molecules", &sMoleculeRetainArray);
-               sMoleculeRetainArray = rb_ary_new();
-       }
-       rb_ary_push(sMoleculeRetainArray, (VALUE)mol->exmolobj);
+       mol->exmolobj = (void *)Data_Wrap_Struct(rb_cMolecule, 0, (void (*)(void *))MoleculeReleaseHook, mol);
+       MoleculeRetain(mol);  /*  MoleculeRetainExternalObj() is automatically called  */
        return (VALUE)mol->exmolobj;
 }
 
+/*  Allocator  */
+static VALUE
+s_Molecule_Alloc(VALUE klass)
+{
+       VALUE val;
+       Molecule *mol = MoleculeNew();
+       val = ValueFromMolecule(mol);
+       MoleculeRelease(mol); /*  Only the returned Ruby object retains this molecule  */
+       return val;
+}
+
 static int
 s_Molecule_AtomIndexFromValue(Molecule *mol, VALUE val)
 {
@@ -4225,14 +4259,6 @@ s_Molecule_AtomGroupFromValue(VALUE self, VALUE val)
        return ig;
 }
 
-/*  Allocator  */
-static VALUE
-s_Molecule_Alloc(VALUE klass)
-{
-       Molecule *mol = MoleculeNew();
-    return Data_Wrap_Struct(klass, 0, (void (*)(void *))MoleculeRelease, mol);
-}
-
 /*
  *  call-seq:
  *     dup          -> Molecule