On Tue, 2004-10-26 at 08:54, Robert Klemme wrote:
> "Markus" <markus / reality.com> schrieb im Newsbeitrag
> news:1098804673.21256.734.camel / lapdog.reality.com...
> > On Tue, 2004-10-26 at 02:14, Erwan Loisant wrote:
> > > What could be a better design? I there a way to design my C library
> > > better so I can tell Ruby's garbage collector about references without
> > > introducing a Ruby dependency in my library's source code ?
> >
> >      One idea might be to give ruby "handles" of some sort that were
> > only usable/meaningful via calls to your library.  As far as ruby's GC
> > was concerned, they would just be integers.  You would then be able to
> > manage your storage as you saw fit, and ruby would be able to do
> > likewise.
> 
> IMHO this is probably the most reasonable approach.  Additionally Erwan
> should then have some mechanism of verifying the handle stored in a
> wrapper object to be able to detect the situation that you have a wrapper
> whose corresponding C model instance is gone.  Unfortunately you would
> have to check the validity in every method that needs the C model instance
> or even in *every* method.  Alternatively you need some kind of observer
> mechanism so your Ruby model instances get to know that their C model
> counterparts are gone.  But even then you still some other object might
> reference the Ruby model instance...
> 
> Another issue is aliasing: depending on the application it might be
> crucial that you have at most one Ruby model instance per C model
> instance, i.e., you want the same representant on the higher level.  This
> is typically the case when you store additional state in the wrapper
> instance.  You can handle this with some sort of mapping - but you'll have
> to be careful with respect to GC in order to not fix wrapper instances in
> mem: You might need a Hash where values are WeakReferences to the wrapping
> instances.
> 
> This is all not very nice and personally I haven't found a clean, nice and
> efficient solution to this issue...

     If he wants to be truly independent of ruby (so that his library
can be used elsewhere) I would suggest the following:

      * Assign each C object a handle (int) on creation.
      * Store the handle in the object
      * Maintain an index mapping handle --> C object
      * Only talk to outsiders in terms of handles
      * When an outsider tries to talk to you about a C object, first
        check that the handle is valid (via the index)


     There are several operations that would need to be implemented in
the library:

      * Assigning a handle
      * Adding a handle=>object to the index
      * Looking up an object given a handle
      * Cleaning up the index when an object is deleted
      * Detecting if an object is valid

     All of them admit to rather simple, time & space efficient
solutions, provided you know what sort of load (lots of lookups, few
creations, or visa versa, etc.) to expect.  For example, if deletions
were going to be rare or done all at the end, the index could be a
hierarchical array and:

      * Assigning a handle-- this_handle = (next_handle++)
      * Adding a handle=>object to the index -- 
                index[this_handle] = this_object
      * Looking up an object given a handle -- index[handle]
      * Cleaning up the index when an object is deleted --
                index[this_handle] = NULL
      * Detecting if an object is valid -- index[handle]


     If there was going to be more turnover, you could use a hash for
the index, or store an additional id with the object (and in the index)
to detect recycled handles.  In effect, the handle becomes a
(slot,version) pair.  The later may be a tad faster but a hash is less
ad hoc and might be easier to maintain.

         -- Markus