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