Maxence, hello.

On 25 Nov 2011, at 14:16, Maxence Guesdon wrote:

>> 
>> These structs are therefore conceptually 'owned' by the Racket layer, so 
>> where the librdf documentation notes that a returned object is shared, I 
>> make a copy of it using one of the librdf copy-create functions. 
> 
> That is: 
> - when you retrieve an already existing object (with a foo_get... function for
>  example), you make a copy and make the gc call the free function on this
>  copy when the value is no more reachabe,

I typically wouldn't make a copy in that case, since most of these cases are 
documented to return a new librdf object.  That's a new object in the sense 
that it is the caller's (ie my) responsibility to free it when it is no longer 
needed.

In some cases, the library documents that the object (or string, or whatever) 
is a _shared_ object.  In this case, the caller must not free it.  In this 
case, I explicitly make a copy using, say, librdf_new_uri_from_uri: that 
returns a 'new' object, which is what I wrap in a scheme object and return.  
Now, internally, this librdf 'copy' may be the same as the original, but with 
an incremented reference count, but that's nothing to do with me.

> - when you create an object, you don't make a copy, but you just embed it
>  in a racket value.

That's correct.  The created object is (implicitly) documented not to be 
shared, so that it's my responsibility to manage it and free it when necessary.

> Is so, that's the way I began to before being afraid of freeing objects
> still in use. I wasn't aware of the counter already used internally.

You shouldn't need to be aware of the counter used internally.  As long as you 
don't attempt to call librdf_free_* on an object documented to be shared, but 
do call librdf_free_* for every object that's not documented to be shared, you 
should be fine.

Below, in case it's useful, is an illustration of the code for the FFI function 
wrapping librdf_new_model.  All of these details are for the Racket FFI, of 
course, but I imagine there'll be very closely analogous things for the OCaml 
FFI.

static Scheme_Object* wrap_librdf_new_model (int argc, Scheme_Object **argv){
    librdf_model* model;
    librdf_world* world = 0;librdf_storage* storage = 0;char* model_uri = 0;

    /* blah blah blah handle arguments */

    if ((model = librdf_new_model(world, storage, model_uri)) == NULL) {
        scheme_signal_error("Unable to construct Model");
    }
    /* model is now a new librdf object
    {
        Scheme_Object* result = NULL;
        /* hairy bookkeeping */
        MZ_GC_DECL_REG(1);
        MZ_GC_VAR_IN_REG(0, result);
        MZ_GC_REG();
        /* wrap this in a Scheme object */
        result = scheme_make_cptr(model, scheme_intern_symbol("librdf-model"));
        /* register the new object with the appropriate custodian function */
        scheme_add_managed(NULL, result, mzrdf_model_custodian, 
(void*)&mzrdf_marker, 0);
        MZ_GC_UNREG();
        return result;
    }
}

And here, for comparison, is my custodian function.  This is called by the GC 
just before it 'forgets' about a scheme object.

void mzrdf_model_custodian(Scheme_Object *o, void* data) {
    librdf_model *model;
    /* sanity check */
    if (! (is_model_p(o))) { scheme_signal_error("librdf assertion 
[is_model_p(o)] failed in %s: model_custodian not given a model object; given 
%V instead", __func__, o); }
    /* retrieve the librdf object from the scheme object */
    model = (librdf_model *)SCHEME_CPTR_VAL(o);
    /* call the librdf_free_model function */
    if (model != NULL) librdf_free_model(model);
}



-- 
Norman Gray  :  http://nxg.me.uk

_______________________________________________
redland-dev mailing list
[email protected]
http://lists.librdf.org/mailman/listinfo/redland-dev

Reply via email to